ADDED ChangeLog Index: ChangeLog ================================================================== --- /dev/null +++ ChangeLog @@ -0,0 +1,987 @@ +1999-04-13 + + * library/encoding/gb2312.enc: + * library/encoding/euc-cn.enc: + * tools/encoding/gb2312.txt: + * tools/encoding/cp950.txt: + * tools/encoding/Makefile: 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. [Bug: 632] + +1999-04-13 + + * win/tclWinSock.c: Apply patch to allow write access to a socket + if FD_WRITE is sent but FD_CONNECT is not. Some strange problem + with either Win32 or a socket driver. [Bug: 1664 1776] + +1999-04-09 + + * unix/tclUnixNotfy.c: Fixed notifier deadlock situation when the + pipe used to talk back notifier thread is filled with data. When + calling the write() function to feed data down that pipe, unlock + the notifierMutex to allow the notifier to wake up again. Found + as a result of the focus.test for Tk hanging. [Bug: 1700] + +1999-04-06 + + * tests/unixNotfy.test: Fixed hang in tests when built with thread + support. + + * tests/httpold.test: Fixed broken test that didn't wait long + enough for events to arrive. + + * tests/unixInit.test: Fixed race condition in test. + + * tests/unixInit.test: + * tests/fileName.test: Minor test nits. + + * unix/tclUnixInit.c (TclpSetInitialEncodings): Fixed bad initial + encoding string. + +1999-04-06 + + * generic/tclVar.c: + * generic/tclEnv.c: 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. + + * generic/tclEnv.c: + * generic/tclWinInit.h: + * generic/tclUnixInit.h: + * generic/tclInt.h: Made the Env module I18N compliant. Changed the + FindVariable routine to TclpFindVariable, that now does a case + insensitive string comparison on Windows, and not on UNIX. [Bug: + 1299, 1500] + +1999-04-05 + + * tests/io.test: Minor test cleanup. + + * generic/tclEncoding.c (Tcl_CreateEncoding): Minor lint to make + it easier to compile on Digital-unix. [Bug: 1659] + + * unix/configure.in: + * unix/tclUnixPort.h: Applied patch for OS/390 to handle lack of + sys/param.h. [Bug: 1725] + + * unix/configure.in: Fixed BSD/OS 4.* configuration to support + shared libraries properly. [Bug: 1730] + +1999-04-05 + + * win/tclWinDde.c: decrease timeout value for DDE calls to 30k + [Bug: 1639] + + * generic/tcl.decls: + * generic/tcl.h: + * generic/tclDecls.h: + * generic/tclInt.decls: + * generic/tclInt.h: + * generic/tclIntDecls.h: + * generic/tclStubInit.c: + * generic/tclUtil.c: Added more functions to the Tcl stubs table, + including all Tcl_ functions not already in it (except Cmd + functions) and Tcl_GetCwd() and Tcl_Chdir() (new functions). + + * tests/safe.test: + * doc/safe.n: + * generic/tclBasic.c: + * library/safe.tcl: The encoding command is not safe as-is, so + create a safe alias to mask out the "encoding system " but + allow all other uses including "encoding system". Added test cases + and updated the man page for Safe Tcl. + +1999-04-05 + + * tests/winTime.test: + * win/tclWinTime.c: Fixed crash in clock command that occurred + when manipulating negative time values in timezones east of + GMT. [Bug: 1142, 1458] + + * tests/platform.test: + * tests/fileName.test: Fixed broken tests. + + * generic/tclFileName.c: Moved global regexps into thread local + storage. + + * tests/socket.test: Changed so tests don't reuse sockets, + since Windows is slow to release sockets. + + * win/tclWinConsole.c: + * win/tclWinPipe.c: + * win/tclWinSerial.c: Fixed race condition where background + threads were terminated while they still held a lock in the + notifier. + +1999-04-02 + + * tests/http.test: Fixed bad test initialization code. + + * generic/tclThreadTest.c (ThreadExitProc): Fixed bug where static + memory was being returned instead of a dynamically allocated + result in error cases. + +1999-04-02 + + * doc/dde.n: + * tools/tcl.wse.in: + * win/makefile.vc: + * win/pkgIndex.tcl: + * win/tclWinDde.c: Add new DDE package, code removed from Tk now + separated into its own package. Changed DDE-based send code into + "dde eval" command. Can be loaded into tclsh (not just wish). + Windows only. + +1999-04-02 + + * tests/expr.test: + * tests/for-old.test: + * tests/for.test: + * tests/foreach.test: + * tests/format.test: + * tests/httpold.test: + * tests/if.test: + * tests/init.test: + * tests/interp.test: + * tests/while.test: Added some tests for known bugs (marked with + knownBug constraint), and cleaned up a few bad tests. + + * generic/regc_locale.c: + * generic/regcustom.h: + * generic/tcl.decls: + * generic/tclCmdIL.c: + * generic/tclCmdMZ.c: + * generic/tclInt.h: + * generic/tclRegexp.c: + * generic/tclScan.c: + * generic/tclTest.c: + * generic/tclUtf.c: + * win/tclWinFCmd.c: + * win/tclWinFile.c: Made various Unicode utility functions + public. The following functions were made public and added to the + stubs table: + Tcl_UtfToUniCharDString, Tcl_UniCharToUtfDString, + Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharIsAlnum, + Tcl_UniCharIsAlpha, Tcl_UniCharIsDigit, Tcl_UniCharIsLower, + Tcl_UniCharIsSpace, Tcl_UniCharIsUpper, Tcl_UniCharIsWordChar + +1999-04-01 + + * tests/registry.test: + * win/tclWinReg.c: Internationalized the registry code. It now + uses Unicode interfaces on NT. [Bug: 1197] + + * tests/parse.test: + * generic/tclParse.c: Fixed crash due to multiple frees in parser + during error cleanup when parsing commands with more tokens than + will fit in the static area of the parse structure. [Bug: 1681] + + * generic/tclInt.h: Removed duplicate declarations. + + * generic/tclInt.decls: + * generic/tcl.decls: Added Tcl_WinUtfToTChar and Tcl_WinTCharToUtf + to the tclPlat table. + +1999-04-01 + + * generic/tcl.decls: + * generic/tcl.h: + * generic/tclBasic.c: + * generic/tclDecls.h: + * generic/StubInit.c: + * tools/genStubs.tcl: + * unix/Makefile.in: + * win/makefile.vc: Applied patch from Jan Nijtmans to fix Ultrix + multiple symbol definition problem. Now, even Tcl includes a copy + of the Tcl stub library. Also fixed TCL_MEM_DEBUG mode (for Tk). + +1999-03-31 + + * win/tclWinConsole.c: WinNT has a bug when reading a single + character from the console. Rewrote the code for the console to + read an entire line at a time using the reader thread. + +1999-03-30 + + * unix/Makefile.in: Removed trailing backslash that broke the + "depend" target. + + * unix/tclUnixInit.c (TclpSetInitialEncodings): Changed to avoid + calling setlocale(). We now look directly at env(LANG) and + env(LC_CTYPE) instead. [Bug: 1636] + + * generic/tclFileName.c: + * generic/tclDecls.h: + * generic/tcl.decls: Removed CONST from Tcl_JoinPath and + Tcl_TranslateFileName because it changes the signature of + Tcl_JoinPath in an incompatible manner. + + * generic/tclInt.h: + * generic/tclLoad.c (TclFinalizeLoad): + * generic/tclEvent.c (Tcl_Finalize): Defer unloading of loadable + modules until all exit handlers have been invoked. + [Bug: 998, 1273, 1573, 1593] + +1999-03-29 + + * generic/tclFileName.c: + * generic/tclDecls.h: + * generic/tcl.decls: Added CONST to Tcl_JoinPath and + Tcl_TranslateFileName. + +1999-03-29 + + * tools/genStubs.tcl: + * unix/configure.in: + * unix/Makefile.in: + * win/makefile.vc: + * generic/tcl.h: + * generic/tclBasic.c: + * generic/tclDecls.h: + * generic/tclIntDecls.h: + * generic/tclPlatDecls.h: + * generic/tclIntPlatDecls.h: 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). + +1999-03-27 + + * win/makefile.bc: Removed makefile for Borland compiler, no + longer supported. + +1999-03-26 + + * win/tclWinSerial.c: + * win/tclWinConsole.c: + * win/tclWinPipe.c: Don't close the Win32 handle for a channel if + it's a stdio handle (GetStdHandle()) during shutdown of a thread + to prevent it from destroying the stdio of other threads. + +1999-03-26 + + * unix/configure.in + --nameble-shared is now the default and build Tcl as a shared + library; specify --disable-shared to build a static Tcl library + and shell. + +1999-03-25 + + * tests/interp.test: + * generic/tclInterp.c (AliasObjCmd): 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. [Bug: 1153, 1556] + + * library/encoding/big5.enc: + * library/encoding/gb2312.enc: + * tools/encoding/big5.enc: + * tools/encoding/gb2312.enc: Added ASCII to big5 and gb2312 + encodings. [Bug: 632] + + * generic/tclPkg.c (Tcl_PkgRequireEx): Fixed broken clientData + initialization in package code. + + * unix/Makefile.in (dist): Added tcl.decls and tclInt.decls to + source distribution. [Bug: 1571] + + * doc/Thread.3: Updated documentation of Tcl_MutexLock to indicate + that the recursive locking behavior is undefined. On Windows, it + does not block, on Unix it deadlocks. [Bug: 1275] + +1999-03-24 + + * tests/execute.test: + * generic/tclExecute.c (TclExecuteByteCode): Fixed expression code + that incorrectly returned floating point values for integers if + the internal rep happened to be a double. Now we check to see if + the object has a string rep that looks like an integer before + using the double internal rep. [Bug: 1516] + +1999-03-24 + + * generic/tclAlloc.c: + * generic/tclEncoding.c: + * generic/tclProc.c: + * unix/tclUnixTime.c: + * win/tclWinSerial.c: Fixed compilation warnings/errors for VC++ + 5.0 and 6.0 and HP-UX native compiler without -Aa or -Ae. + [Bug: 1323 1518 1324 1583 1585 1586] + + * win/tclWinSock.c: Make sockets thread-safe on Windows. The + current implementation uses windows to handle events on the + socket, one for each thread (thread local storage). Previously, + there was only one window shared between threads, which didn't + work. [Bug: 1326] + +1999-03-23 + + * tools/tcl.wse: Fixed file association to look in the right place + for the wish icon. [Bug: 1544] + + * tests/winNotify.test: + * tests/ioCmd.test: + * tests/event.test: Changed to use new style conditionals. + + * tests/encoding.test: Fixed nonportable test. + + * unix/dltest/configure.in: + * unix/dltest/Makefile.in: Added missing DBGX macros. [Bug: 1564] + + * tests/winNotify.test: + * mac/tclMacNotify.c: + * win/tclWinNotify.c: + * unix/tclUnixNotfy.c: + * generic/tclNotify.c: Added a new Tcl_ServiceModeHook interface + that is invoked whenever the service mode changes. This is needed + to allow the Windows notifier to create a communication window the + first time Tcl is about to enter an external modal event loop + instead of at startup time. This will avoid the various problems + that people have been seeing where the system hangs when tclsh + is running outside of the event loop. [Bug: 783] + + * generic/tclInt.h: + * generic/tcl.decls: Renamed TclpAlertNotifier back to + Tcl_AlertNotifier since it is part of the public notifier driver + API. + +1999-03-23 + + * win/tclWinSerial.c: Fixed problem with fileevent on the serial + port and nonblocking mode. Gets no longer hangs, fileevents fire + whenever there is any character data on the port. + + * tests/winConsole.test: + * win/tclWinConsole.c: Fixed problem with fileevents and gets from + a console stdin. Previously, fileevents were firing before an + entire line was available for reading, which meant that when you + did a gets or read, it blocked (even in nonblocking mode). Now, it + should work the same as Unix: fileevents fire when an entire line + is ready, and gets and read do not block in non-blocking mode. + Added an interactive test case to check for this. + +1999-03-22 + + * tests/reg.test: + * generic/regc_color.c: Applied regexp bug fix from Henry Spencer. + +1999-03-19 + + * generic/tclCmdIL.c: Fixed the initialization of an array so that + the Sun 5.0 C compiler wouldn't complain. + + * unix/configure.in: Added support for --enable-64bit. For now, + this is only supported on Solaris 7 64bit (SunOS 5.7) using the Sun + compiler (not gcc). + +1999-03-18 + + * win/tclWinChan.c (TclpOpenFileChannel, Tcl_MakeFileChannel): + Changed to only test for console or comm handles when the type is + FILE_TYPE_CHAR to avoid useless tests on simple files. Also + reordered tests so consoles are tested first as this is more + common. + + * win/makefile.vc: Regularized usage of mkd and rmd and rm. + + * library/encoding/shiftjis.enc: + * tools/encoding/shiftjis.txt: Missing/incorrect characters in + shift-jis table. [Bug: 1008, 1526] + + * generic/tclInt.decls: + * generic/tcl.decls: Eliminated use of "string" and "list" from + argument lists to avoid conflicts with C++ STL. [Bug: 1181] + + * win/tclWinFile.c (TclpMatchFiles): Changed to ignore the + FS_CASE_IS_PRESERVED bit and always return exactly what we get + from the system. + +1999-03-17 + + * win/README.binary: + * win/README: + * unix/configure.in: + * generic/tcl.h: + * README: Updated version to 8.1b3. + +1999-03-14 + + * win/tclWinConsole.c: + * win/tclWinPipe.c: + * win/tclWinSerial.c: Changed so channel drivers wait for the + reader/writer threads to exit before returning during a close + operation. This ensures that the main thread is the last thread + to exit, so the process return value is set properly. + + * generic/tclIntDecls.h: + * generic/tclIntPlatDecls.h: + * generic/tclIntPlatStubs.c: + * generic/tclIntStubs.c: + * generic/tclPlatDecls.h: + * generic/tclPlatStubs.c: + * generic/tclStubInit.c: + * generic/tclStubs.c: Fixed bad eol characters. + + * generic/tclInt.decls: Changed "const" to "CONST" in + declarations for better portability. + + * generic/tcl.decls: Renamed panic and panicVA to Tcl_Panic and + Tcl_PanicVA in the stub files. + + * generic/tclInterp.c (Tcl_MakeSafe): Remove tcl_platform(user) + from safe interps. + +1999-03-11 + + * unix/Makefile.in: + * unix/configure.in: Include compat files in the stub library in + addition to the main library. Compat files are now built for + dynamic use in all cases. + + * generic/tcl.h: Changed magic number so it doesn't match the plus + patch, at Jan's request. + + * unix/tclConfig.sh.in: + * unix/dltest/Makefile.in: + * unix/dltest/configure.in: + * unix/dltest/pkga.c: + * unix/dltest/pkgb.c: + * unix/dltest/pkgc.c: + * unix/dltest/pkgd.c: + * unix/dltest/pkge.c: + * unix/dltest/pkgf.c: Changed package tests to build against the + stubs library. + +1999-03-10 + + * generic/tcl.h: + * generic/tcl.decls: Changed Tcl_ReleaseType from an enum to + macros so it can be used in .rc files. + Added Tcl_GetString. + + * mac/tclMacNotify.c: + * generic/tclNotify.c: + * generic/tclInt.h: + * win/tclWinNotify.c: + * generic/tcl.h: Renamed Tcl_AlertNotifier to TclpAlertNotifier. + + * generic/tclInt.decls: Added TclWinAddProcess to make it possible + for expect to use Tcl_WaitForPid(). This patch is from Gordon + Chaffee. + + * mac/tclMacPort.h: + * win/tclWinInit.c: + * unix/tclUnixPort.h: + * generic/tclAsync.c: Added TclpAsyncMark to fix bug in async + handling on Windows where async events don't wake up the event + loop. This patch comes from Gordon Chaffee. + + * generic/tcl.decls: Fixed declarations of reserved slots. + +1999-03-10 + + * generic/tclCompile.h: Ensure that the ByteCode struct is binary + compatible with the version in 8.0.6. + + * generic/tcl.h: + * generic/tclBasic.c: Add Tcl_GetVersion() function to the public + C API to allow programs to check the version number of the Tcl + library at runtime. Also added an enum to clarify the release + level (alpha, beta, final). + +1999-03-09 + + * Integrated changes from Tcl 8.0 including: + stubs mechanism + configure patches from Jan Nijtmans + rename of panic to Tcl_Panic + +1999-03-08 + + * win/tclWin32Dll.c: Removed Dll instance from thread-local + storage. + +1999-03-08 + + * generic/tcl.h: Moved Tcl_Mutex, etc. macros above the inclusion + of tclDecls.h to avoid macro conflicts. + + * generic/tclInt.h: + * generic/regc_color.c: + * generic/regcomp.c: + * generic/tclCmdIL.c: + * generic/tclCmdAH.c: + * generic/tclIOCmd.c: + * generic/tclParse.c: + * generic/tclStringObj.c: + * unix/tclUnixNotfy.c: Cleaned up various compiler warnings, + eliminated UCHAR bugs. + + * unix/tclUnixNotfy.c: + * unix/tclUnixThrd.c: + * generic/tclThreadTest.c: + * mac/tclMacThrd.c: Changed TclpCondition*() to Tcl_Condition*(). + + * INTEGRATED PATCHES FROM 8.0.6: + + * generic/tcl.decls: + * generic/tcl.h: + * generic/tclBasic.c: + * generic/tclDecls.h: + * generic/tclInt.decls: + * generic/tclInt.h: + * generic/tclIntDecls.h: + * generic/tclIntPlatDecls.h: + * generic/tclIntPlatStubs.c: + * generic/tclIntStubs.c: + * generic/tclPlatDecls.h: + * generic/tclPlatStubs.c: + * generic/tclStubInit.c: + * generic/tclStubLib.c: + * generic/tclStubs.c: + * tools/genStubs.tcl: + * unix/configure.in: + * unix/Makefile.in: + * unix/tclConfig.sh.in: + * win/makefile.vc: + * win/tclWinPort.h: Added Tcl stubs implementation. There are + now two new macros USE_TCL_STUBS and USE_TCL_STUB_PROCS that + enable use of stubs and disable stub macros respectively. All of + the public and private function declarations from tcl.h and + tclInt.h have moved into the *.decls files and the *Stubs.c and + *Decls.h files are generated using the genStubs.tcl script. + + * unix/Makefile.in: + * unix/configure.in: + * unix/ldAix: Enhanced AIX shared library support. + + * win/tclWinSock.c: Removed a bunch of extraneous PASCAL FAR + attributes from internal functions. + + * win/tclWinReg.c: Changed registry package to use stubs mechanism + so it no longer depends on the specific version of Tcl. + + * doc/AddErrInfo.3: + * doc/Eval.3: + * doc/PkgRequire.3: + * doc/SetResult.3: + * doc/StringObj.3: + * generic/tcl.h: + * generic/tclBasic.c: + * generic/tclPanic.c: + * generic/tclStringObj.c: + * generic/tclUtil.c: + * unix/mkLinks: Added va_list versions of all VARARGS + functions so they can be invoked from the stub functions. + + * doc/package.n: + * doc/PkgRequire.3: + * generic/tclPkg.c: Added Tcl_PkgProvideEx, Tcl_RequireEx, + Tcl_PresentEx, and Tcl_PkgPresent. Added "package present" + command. + + * generic/tclFileName.c: + * mac/tclMacFile.c: + * mac/tclMacShLib.exp: + * unix/tclUnixFile.c: + * win/tclWinFile.c: Changed so TclGetUserHome is defined on + all platforms, even though it is currently a noop on mac and + windows, and renamed it to TclpGetUserHome. + + * generic/tclPanic.c: + * generic/panic.c: Renamed panic to Tcl_Panic. + +1999-02-25 + + * win/makefile.vc: Added tclWinConsole.c and tclWinSerial.c + + * win/tclWinConsole.c: New code to properly deal with fileevents + and nonblocking mode on consoles. + + * win/tclWinSerial.c: New code to properly deal with fileevents + and nonblocking mode on serial ports. + + * win/tclWinPipe.c: + * win/tclWinPort.h: Exported functions to allow creation of pipe + channels from tclWinChan.c + + * win/tclWinChan.c: Check the type of a channel, including for the + standard (stdin/stdout/stderr), and use the correct channel type + to create the channel (file, serial, console, or pipe). + +1999-02-11 + + * README: + * generic/tcl.h: + * win/README.binary: + * win/README: + * unix/configure.in: + * mac/README: Updated version numbers to 8.1b2. + +1999-02-10 + + * library/auto.tcl: Fixed auto_mkindex so it handles .tbc files. + Did some general cleanup to handle bad eval statements that didn't + use "list". + + * unix/mkLinks: + * doc/SetVar.3: + * generic/tcl.h: + * generic/tclVar.c: Restored Tcl_ObjGetVar2 and Tcl_ObjSetVar2 + from 8.0. Renamed Tcl_Get/SetObjVar2 to Tcl_GetVar2Ex and + Tcl_SetVar2Ex. + +1999-02-10 + + INTEGRATED PATCHES FROM 8.0.5b2: + + * test/winPipe.test: Changed to remove echoArgs.tcl temporary file + when done. + + * tests/cmdAH.test: + * generic/tclFileName.c (TclGetExtension): Changed behavior so the + split happens at the last period in the name instead of the first + period of the last run of periods. So, "foo..o" is split into + "foo." and ".o" now. [Bug: 1126] + + * win/makefile.vc: Added better support for paths with spaces in + the name. Added .lib and support .dlls to the install-binaries + target. Added generate of a pkgIndex.tcl script to the + install-libraries target. + + * win/tclAppInit.c: + * unix/tclAppInit.c: + * mac/tclMacAppInit.c: + * generic/tclTest.c: Changed some EXTERN declarations to extern + since they are not defining exported interfaces. This avoids + generating useless declspec() attributes and makes the windows + makefile simpler. + + * generic/tcl.h: Moved Tcl_AppInit declaration to end and cleared + out TCL_STORAGE_CLASS so it is not declared with a declspec(). + + * tests/interp.test: + * generic/tclInterp.c (DeleteAlias): Changed to use + Tcl_DeleteCommandFromToken so we handle renames properly. This + avoids senseless panic. [Bug: 736] + + * unix/tclUnixChan.c: + * win/tclWinSock.c: + * doc/socket.n: Applied Gordon Chaffee's patch to handle failures + during asynchronous socket connection operations. This adds a new + "-error" fconfgure option to socket channels. [Bug: 893] + + * generic/tclProc.c: + * generic/tclNamesp.c: + * generic/tclInt.h: + * generic/tclCmdIL.c: + * generic/tclBasic.c: + * generic/tclVar.c: Applied patch from Viktor Dukhovni to + rationalize TCL_LEAVE_ERR_MSG behavior when creating variables. + + * generic/tclVar.c: Fixed bug in namespace tail computation. + Fixed bug where upvar could resurrect a namespace variable whose + namespace had been deleted. + + * generic/tclCompile.c (TclCompileExprCmd): Eliminated yet another + bogus optimization in expression compilation. + + * unix/configure.in: Added branch for BSD/OS-4* to shared library + case statement. [Bug: 975] + Fixed to correctly handle IRIX 6.5 n32 library support. [Bug: 1117] + + * win/winDumpExts.c: Patched to be pickier about stripping + @'s. [Bug: 920] + + * library/http2.0/http.tcl: Added catch around eof test in + CopyDone since the user may have already called http::reset. + [Bug: 1108] + + * unix/configure.in: Changed Linux and IRIX to set SHLIB_LIBS to + LIBS so shared libraries are linked with the system + libraries. [Bug: 1018] + + * generic/tclCompile.c (CompileExprWord): Fixed exception stack + overflow bug caused by missing statement. [Bug: 928] + + * generic/tclIOCmd.c: + * generic/tclBasic.c: Objectified the "open" command. [Bug: 1113] + + * generic/tclPosixStr.c (Tcl_ErrnoId, Tcl_ErrnoMsg): When using + egcs, ENOTSUP and EOPNOTSUPP are the same, so now we handle that + case. [Bug: 1137] + + * library/init.tcl: Various small changes requested by Jan Nijtmans. + - If the variable $tcl_library contains the empty string, this + empty string will be put in $auto_path. This is not useful at all, + it only slows down later package processing. + - If the variable tcl_pkgPath is not set, the "unset __dir" + fails. Thich makes init.tcl totally unusable. Better put a "catch" + around it. + - In the function tcl_findLibraries, the "string match" function + only works correctly if $tcl_patchLevel is in one of the forms + "?.?a?", "?.?b?" or "?.?.?". Could a "regexp" be used instead, + then it allows anything to be appended to the patchLevel + string. And it is more efficient. + - The tclPkgSetup function assumes that if $type != "load" then + the type must be "source". This needn't be true. Some users want + to add their own setup types. + [RFE: 1138] [Bug: 978] + + * win/tclWinReg.c: + * doc/registry.n: Added support for HKEY_PERFORMANCE_DATA and + HKEY_DYN_DATA keys. [Bug: 1109] + + * win/tclWinInit.c (TclPlatformInit): Added code to ensure + tcl_pkgPath is set to "" when no registry entry is found. [Bug: 978] + +1999-02-01 + + * generic/tclBasic.c: + * generic/tclCmdAH.c: + * generic/tclCmdIL.c: + * generic/tclCmdMZ.c: + * generic/tclExecute.c: + * generic/tclHistory.c: + * generic/tclIO.c: + * generic/tclIOUtil.c: + * generic/tclInterp.c: + * generic/tclMain.c: + * generic/tclNamesp.c: + * generic/tclParse.c: + * generic/tclProc.c: + * generic/tclTest.c: + * generic/tclTimer.c: + * generic/tcl.h: Made 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. + +1999-01-28 + + * Merged Tcl 8.0.5b1 changes. + + * generic/tclUtil.c (Tcl_DStringSetLength): Changed so the buffer + overallocates in a manner similar to Tcl_DStringAppend. This + should improve performance for TclUniCharToUtfDString. + +1998-12-11 === Tcl 8.1b1 Release === + +1998-12-10 + + * Fixed lots of files that used TCL_THREAD instead of TCL_THREADS. + + * generic/tclEncoding.c (Tcl_FreeEncoding): Moved most of the code + into a static FreeEncoding routine that does not grab the + encodingMutex to avoid deadlocks/races when called from other + routines that already have the mutex. + +1998-12-09 + + * library/msgcat1.0/msgcat.tcl: Fixed bad export list, fixed so + all locale strings are converted to lower case, including file + names. + + * generic/regcomp.c (makescan): Fixed bug in longest match case + that caused anchored patterns to fail. [Bug: 897] + +1998-12-08 + + * library/msgcat1.0/msgcat.tcl: changed mc to invoke mcunknown in + the calling context, changed locale lookups to be case insensitive + +1998-12-07 + + * generic/tclAlloc.c (TclpRealloc): Fixed a memory allocation bug + where big blocks that were reallocated into a different heap + location were not being placed into the bigBlocks list. [Bug: 933] + + * tests/msgcat.test: Added message catalog test suite. + + * library/msgcat1.0/msgcat.tcl: minor bug fixes, integrated latest + changes from Mark Harrison. + +1998-12-04 + + * library/msgcat1.0/msgcat.tcl: Changed code to conform to Tcl + coding standards. Changed to use file join for portability. + + * library/msgcat1.0: Added initial implementaion of Tcl message + catalog package contributed by Mark Harrison. + +1998-12-03 + + * win/tclWinPipe.c (BuildCommandLine): Fixed bug that kept + arguments containing spaces from being properly quoted. + + * tests/defs: Changed so auto_path is set to only contain the Tcl + library directory. This keeps the tests from accidentally picking + up stuff in installed packages. + + * generic/tclUtil.c (Tcl_StringMatch): Changed to match 8.0 + behavior in corner case where there is no closing bracket. + +1998-12-02 + + * win/tclWinPipe.c (TclpCreateCommandChannel): Changed + reader/writer threads to have THREAD_PRIORITY_HIGHEST so they will + have a chance to run whenever there is something to do. + + * generic/tclIO.c (WriteBytes, WriteChars): Fixed so extraneous + flushes do not happen in line mode. + (TranslateOutputEOL): Made translation more efficient in line mode + and fixed a buffer overflow bug in CRLF translation. [Bug: 887] + +1998-12-02 + + * Updated patchlevel to 8.1b1 + +1998-12-02 + + * generic/regc_color.c (subcolor): Added check for error case to + avoid an out of bounds array reference. + + * generic/tclCmdAH.c (Tcl_EncodingObjCmd): Changed to avoid using + Tcl_DStringResult because it is not binary clean. + + * generic/tclParse.c (Tcl_ParseCommand): Fixed bug in comment + parsing where a trailing comment looked like an incomplete + command. + +1998-12-02 + + * Merged changes from 8.0.4, especially the new pkg_mkIndex + +1998-12-01 + + * generic/tclIO.c (Tcl_ReadChars): Added a call to UpdateInterest + so we don't block when there is data sitting in the buffers. + + * generic/tclTest.c (TestevalobjvObjCmd): Updated for EvalObjv + change. + + * tests/parse.test: Updated tests for EvalObjv change. + + * generic/tclParse.c (EvalObjv, Tcl_EvalObjv): Changed + Tcl_EvalObjv interface to remove string and length arguments, + preserved original interface as EvalObjv for internal use. + + * generic/tcl.h: Changed Tcl_EvalObjv interface to remove string + and length arguments. + + * doc/Eval.3: Updated documentation for Tcl_EvalObjv to remove + string and length arguments. + + * generic/tclCompCmds.c (TclCompileForeachCmd): Fixed code that + corrupted the exceptDepth value in the compile environment when + foreach failed to compile inline. [Bug: 884] + + * library/encoding/euc-kr.enc: + * library/encoding/ksc5601.enc: + * tools/encoding/ksc5601.txt: + * unix/tclUnixInit.c: Added support for Korean EUC. + + * win/tclWinChan.c (TclpGetDefaultStdChannel): added check for a + failure during Tcl_MakeFileChannel. + +1998-11-30 + + * unix/tclUnixNotfy.c (Tcl_WaitForEvent): Fixed hang that occurs + when trying to close a pipe that is currently being waited on by + the notifier thread. [Bug: 607] + + * unix/tclUnixFCmd.c (GetPermissionsAttribute): Increase size of + returnString buffer to avoid overflow. [Bug: 584] + + * generic/tclThreadTest.c (TclThreadSend): Fixed memory leak due + to use of TCL_VOLATILE instead of TCL_DYNAMIC. + + * generic/tclThread.c (TclRememberSyncObject): Fixed memory leak + caused by failure to reuse condition variables. + + * unix/tclUnixNotfy.c: (Tcl_AlertNotifier, Tcl_WaitForEvent, + NotifierThreadProc, Tcl_InitNotifier): Fixed race condition caused + by incorrect use of condition variables when sending messages + between threads.. [Bug: 607] + + * generic/tclTestObj.c (TeststringobjCmd): MAX_STRINGS was off by one + so the strings array was too small. + + * generic/tclCkalloc.c (Tcl_DbCkfree): Moved mutex lock so + ValidateMemory is done inside the mutex to avoid a race condition + when validate_memory is enabled. [Bug: 880] + +1998-11-23 + + * regexec.c: more performance tuning from Henry Spencer. + +1998-11-17 + + * tclScan.c: moved "scan" implementation out of tclCmdMZ.c and + added Unicode support. This required a complete reimplementation + of the command to avoid using scanf(), which isn't Unicode aware. + Two new features were added in the process: %n to return the + current number of characters consumed, and XPG3-style %n$ argument + order specifiers similar to those provided by the "format" + command. [Bug: 833] + + * tclAlloc.c: changed so allocated memory is always 8-byte aligned + to improve memory performance and to ensure that it will work on + systems that don't like accessing 4-byte aligned values + (e.g. Solaris and HP-UX). [Bug: 834] + +1998-11-06 + + * tclVar.c (TclGetIndexedScalar): Fixed bug 796, var name was + getting lost before being passed to CallTraces. + +1998-10-21 + + * added "encoding" command + + * Moved internal regexp declarations from tclInt.h to tclRegexp.h + + * integrated regexp updates from Henry Spencer + +1998-10-15 + + * tclUtf.c: added Unicode character table support + + * tclInt.h: added TclUniCharIsWordChar + + * tclCmdMZ.c (Tcl_StringObjCmd): added "totitle" subcommand, + changed "wordend" and "wordstart" to properly handle Unicode word + characters and connector punctuation + +1998-10-05 + + * auto.tcl, package.tcl: fixed SCCS strings + + * tclIndex: updated index to reflect 8.1 files + + * tclCompile.c (TclCompileScript): changed to avoid modifying the + input string in place because name lookup operations could have + arbitrary side effects + + * tclInterp.c: added guard against deleting current interpreter + + * tclMacFile.c, tclUnixFile.c, tclWinFile.c, tclFileName.c: added + warnings around code that modifies strings in place + + * tclExecute.c: fixed off-by-one copying error, fixed merge bugs + + * tclEvent.c: changed so USE_TCLALLOC is tested for value instead + of definition + + * tclCompCmds.c: replaced SCCS strings, added warnings around code + that modifies strings in place + + * interp.test: added test for interp deleting itself + +1998-09-30 + + * makefile.vc: fixed so TCL_LIBRARY is set before running tcltest + + * tclWin32Dll.c: removed TclpFinalize, cleanup of merges + Index: README ================================================================== --- README +++ README @@ -1,31 +1,68 @@ -Tcl +README: Tcl -SCCS: @(#) README 1.52 97/11/20 12:43:16 + Tcl is maintained, enhanced, and distributed freely as a + service to the Tcl community by Scriptics Corporation. + +RCS: @(#) $Id: README,v 1.1.2.10 1999/03/17 21:29:56 stanton Exp $ + +Contents +-------- + 1. Introduction + 2. Documentation + 3. Compiling and installing Tcl + 4. Summary of changes in Tcl 8.1 + 5. Development tools + 6. Tcl newsgroup + 7. Tcl contributed archive + 8. Tcl Resource Center + 9. Mailing lists + 10. Support and bug fixes + 11. Tcl version numbers 1. Introduction --------------- -This directory and its descendants contain the sources and documentation -for Tcl, an embeddable scripting language. The information here -corresponds to release 8.0p2, which is the second patch update for Tcl -8.0. Tcl 8.0 is a major new release that replaces the core of the -interpreter with an on-the-fly bytecode compiler to improve execution -speed. It also includes several other new features such as namespaces -and binary I/O, plus many bug fixes. The compiler introduces a few -incompatibilities that may affect existing Tcl scripts; the -incompatibilities are relatively obscure but may require modifications -to some old scripts before they can run with this version. The compiler -introduces many new C-level APIs, but the old APIs are still supported. -See below for more details. This patch release fixes various bugs in -Tcl 8.0; there are no feature changes relative to Tcl 8.0. +Tcl provides a powerful platform for creating integration +applications that tie together diverse applications, protocols, +devices, and frameworks. When paired with the Tk toolkit, Tcl +provides the fastest and most powerful way to create GUI applications +that run on PCs, Unix, and the Macintosh. Tcl can also be used for a +variety of web-related tasks and for creating powerful command +languages for applications. + +This directory contains the sources and documentation for Tcl. The +information here corresponds to release 8.1b3, which is the third +beta release for Tcl 8.1. This release is mostly feature complete but +may have bugs and be missing some minor features. This release is for +early adopters who are willing to help us find and fix problems. +Please let us know about any problems you uncover. + +Tcl 8.1 includes four major new features: Unicode support (all internal +strings are now stored in UTF-8 form), a new regular expression matcher +with most of the Perl features, support for multithreading, and a new +message catalog package. For details on features, incompatibilities, and +potential problems with this release, see the Tcl/Tk 8.1 Web page at +http://www.scriptics.com/software/8.1.html or refer to the "changes" file +in this directory, which contains a historical record of all changes to +Tcl. + +Tcl is a freely available open source package. You can do virtually +anything you like with it, such as modifying it, redistributing it, +and selling it either in whole or in part. See the file +"license.terms" for complete information. 2. Documentation ---------------- -The best way to get started with Tcl is to read one of the introductory -books on Tcl: +The best way to get started with Tcl is to read about Tcl on the +Scriptics Web site at: + + http://www.scriptics.com/scripting + +Another good way to get started with Tcl is to read one of the +introductory books on Tcl: Practical Programming in Tcl and Tk, 2nd Edition, by Brent Welch, Prentice-Hall, 1997, ISBN 0-13-616830-2 Tcl and the Tk Toolkit, by John Ousterhout, @@ -32,241 +69,186 @@ Addison-Wesley, 1994, ISBN 0-201-63337-X Exploring Expect, by Don Libes, O'Reilly and Associates, 1995, ISBN 1-56592-090-2 -The "doc" subdirectory in this release contains a complete set of reference -manual entries for Tcl. Files with extension ".1" are for programs (for -example, tclsh.1); files with extension ".3" are for C library procedures; -and files with extension ".n" describe Tcl commands. The file "doc/Tcl.n" -gives a quick summary of the Tcl language syntax. To print any of the man -pages, cd to the "doc" directory and invoke your favorite variant of -troff using the normal -man macros, for example +Other books are listed at +http://www.scriptics.com/resource/doc/books/ + +There is also an official home for Tcl and Tk on the Scriptics Web site: + + http://www.scriptics.com + +These Web pages include information about the latest releases, products +related to Tcl and Tk, reports on bug fixes and porting issues, HTML +versions of the manual pages, and pointers to many other Tcl/Tk Web +pages at other sites. Check them out! + +2a. Unix Documentation +---------------------- + +The "doc" subdirectory in this release contains a complete set of +reference manual entries for Tcl. Files with extension ".1" are for +programs (for example, tclsh.1); files with extension ".3" are for C +library procedures; and files with extension ".n" describe Tcl +commands. The file "doc/Tcl.n" gives a quick summary of the Tcl +language syntax. To print any of the man pages on Unix, cd to the +"doc" directory and invoke your favorite variant of troff using the +normal -man macros, for example ditroff -man Tcl.n to print Tcl.n. If Tcl has been installed correctly and your "man" program supports it, you should be able to access the Tcl manual entries using the normal "man" mechanisms, such as man Tcl -There is also an official home for Tcl and Tk on the Web: - http://sunscript.sun.com -These Web pages include information about the latest releases, products -related to Tcl and Tk, reports on bug fixes and porting issues, HTML -versions of the manual pages, and pointers to many other Tcl/Tk Web -pages at other sites. Check them out! +2b. Windows Documentation +------------------------- + +The "doc/help" subdirectory in this release contains a complete set of +Windows help files for TclPro. Once you install this Tcl release, a +shortcut to the Windows help Tcl documentation will appear in the +"Start" menu: + + Start | Programs | Tcl | Tcl Help 3. Compiling and installing Tcl ------------------------------- This release contains everything you should need to compile and run -Tcl under UNIX, Macintoshes, and PCs (either Windows NT, Windows 95, -or Win 3.1 with Win32s). +Tcl under UNIX, PCs (either Windows NT, Windows 95, or Win 3.1 with +Win32s), and Macintoshes. Before trying to compile Tcl you should do the following things: (a) Check for a binary release. Pre-compiled binary releases are available now for PCs, Macintoshes, and several flavors of UNIX. Binary releases are much easier to install than source releases. To find out whether a binary release is available for your - platform, check the home page for SunScript - (http://sunscript.sun.com) under "Tech Corner". Also, check in + platform, check the Scriptics Tcl Resource Center + (http://www.scriptics.com/resource). Also, check in the FTP directory from which you retrieved the base - distribution. Some of the binary releases are available freely, - while others are for sale. + distribution. (b) Make sure you have the most recent patch release. Look in the FTP directory from which you retrieved this distribution to see if it has been updated with patches. Patch releases fix bugs without changing any features, so you should normally use the latest patch release for the version of Tcl that you want. - Patch releases are available in two forms. A file like - tcl8.0p2.tar.Z is a complete release for patch level 2 of Tcl - version 8.0. If there is a file with a higher patch level than - this release, just fetch the file with the highest patch level - and use it. - - Patches are also available in the form of patch files that just - contain the changes from one patch level to another. These - files will have names like tcl8.0p1.patch, tcl8.0p2.patch, etc. They - may also have .gz or .Z extensions to indicate compression. To - use one of these files, you apply it to an existing release with - the "patch" program. Patches must be applied in order: - tcl8.0p1.patch must be applied to an unpatched Tcl 8.0 release - to produce a Tcl 8.0p1 release; tcl8.0p2.patch can then be - applied to Tcl8.0p1 to produce Tcl 8.0p2, and so on. To apply an - uncompressed patch file such as tcl8.0p1.patch, invoke a shell - command like the following from the directory containing this - file: - patch -p < tcl8.0p1.patch - If the patch file has a .gz extension, invoke a command like the - following: - gunzip -c tcl8.0p1.patch.gz | patch -p - If the patch file has a .Z extension, it was compressed with - compress. To apply it, invoke a command like the following: - zcat tcl8.0p1.patch.Z | patch -p - If you're applying a patch to a release that has already been - compiled, then before applying the patch you should cd to the - "unix" subdirectory and type "make distclean" to restore the - directory to a pristine state. Once you've done this, change to the "unix" subdirectory if you're compiling under UNIX, "win" if you're compiling under Windows, or "mac" if you're compiling on a Macintosh. Then follow the instructions in the README file in that directory for compiling Tcl, installing it, and running the test suite. -4. Summary of changes in Tcl 8.0 +4. Summary of changes in Tcl 8.1 -------------------------------- -Here are the most significant changes in Tcl 8.0. In addition to these +Here are the most significant changes in Tcl 8.1. In addition to these changes, there are several smaller changes and bug fixes. See the file "changes" for a complete list of all changes. - 1. Bytecode compiler. The core of the Tcl interpreter has been - replaced with an on-the-fly compiler that translates Tcl scripts to - byte codes; a new interpreter then executes the byte codes. In - earlier versions of Tcl, strings were used as a universal - representation; in Tcl 8.0 strings are replaced with Tcl_Obj - structures ("objects") that can hold both a string value and an - internal form such as a binary integer or compiled bytecodes. The - new objects make it possible to store information in efficient - internal forms and avoid the constant translations to and from - strings that occurred with the old interpreter. We have not yet - converted all of Tcl to take full advantage of the compiler and - objects and have not converted any of Tk yet, but even so you - should see speedups of 2-3x on many programs and you may see - speedups as much as 10-20x in some cases (such as code that - manipulates long lists). Future releases should achieve even - greater speedups. The compiler introduces only a few minor changes - at the level of Tcl scripts, but it introduces many new C APIs for - managing objects. See, for example, the manual entries doc/*Obj*.3. - - 2. Namespaces. There is a new namespace mechanism based on the - namespace implementation by Michael McLennan of Lucent Technologies. - This includes new "namespace" and "variable" commands. There are - many new C APIs associated with namespaces, but they will not be - exported until Tcl 8.1. Note: the syntax of the namespace command - has been changed slightly since the b1 release. See the changes - file for details. - - 3. Binary I/O. The new object system in Tcl 8.0 supports binary - strings (internally, strings are counted in addition to being null - terminated). There is a new "binary" command for inserting and - extracting data to/from binary strings. Commands such as "puts", - "gets", and "read" commands now operate correctly on binary data. - There is a new variable tcl_platform(byteOrder) to identify the - native byte order for the current host. - - 4. Random numbers. The "expr" command now contains a random number - generator, which can be accessed via the "rand()" and "srand()" math - functions. - - 5. Safe-Tcl enhancements. There is a new "hidden command" - mechanism, implemented with the Tcl commands "interp hide", "interp - expose", "interp invokehidden", and "interp hidden" and the C APIs - Tcl_HideCommand and Tcl_ExposeCommand. There is now support for - safe packages and extension loading, including new library - procedures such as safe::interpCreate (see the manual entry safe.n - for details). - - 6. There is a new package "registry" available under Windows for - accessing the Windows registry. - - 7. There is a new command "file attributes" for getting and setting - things like permissions and owner. There is also a new command - "file nativename" for getting back the platform-specific name for a - particular file. - - 8. There is a new "fcopy" command to copy data between channels. - This replaces and improves upon the not-so-secret unsupported old - command "unsupported0". - - 9. There is a new package "http" for doing GET, POST, and HEAD - requests via the HTTP/1.0 protocol. See the manual entry http.n - for details. - - 10. There are new library procedures for finding word breaks in - strings. See the manual entry library.n for details. - - 11. There are new C APIs Tcl_Finalize (for cleaning up before - unloading the Tcl DLL) and Tcl_Ungets for pushing bytes back into a - channel's input buffer. - - 12. Tcl now supports serial I/O devices on Windows and Unix, with a - new fconfigure -mode option. The Windows driver does not yet - support event-driven I/O. - - 13. The lsort command has new options -dictionary and -index. The - -index option allows for very rapid sorting based on an element - of a list. - - 14. The event notifier has been completely rewritten (again). It - should now allow Tcl to use an external event loop (like Motif's) - when it is embedded in other applications. No script-level - interfaces have changed, but many of the C APIs have. - -Tcl 8.0 introduces the following incompatibilities that may affect Tcl -scripts that worked under Tcl 7.6 and earlier releases: - - 1. Variable and command names may not include the character sequence - "::" anymore: this sequence is now used as a namespace separator. - - 2. The semantics of some Tcl commands have been changed slightly to - maximize performance under the compiler. These incompatibilities - are documented on the Web so that we can keep the list up-to-date. - See the URL http://www.sunlabs.com/research/tcl/compiler.html. - - 3. 2-digit years are now parsed differently by the "clock" command - to handle year 2000 issues better (years 00-38 are treated as - 2000-2038 instead of 1900-1938). - - 4. The old Macintosh commands "cp", "mkdir", "mv", "rm", and "rmdir" - are no longer supported; all of these features are now available on - all platforms via the "file" command. - - 5. The variable tcl_precision is now shared between interpreters - and defaults to 12 digits instead of 6; safe interpreters cannot - modify tcl_precision. The new object system in Tcl 8.0 causes - floating-to-string conversions (and the associated rounding) to - occur much less often than in Tcl 7.6, which can sometimes cause - behavioral changes. - - 6. The C APIs associated with the notifier have changed substantially. - - 7. The procedures Tcl_CreateModalTimeout and Tcl_DeleteModalTimeout - have been removed. - - 8. Tcl_CreateFileHandler and Tcl_DeleteFileHandler now take Unix - fd's and are only supported on the Unix platform - - 9. The C APIs for creating channel drivers have changed as part of - the new notifier implementation. The Tcl_File interfaces have been - removed. Tcl_GetChannelFile has been replaced with - Tcl_GetChannelHandle. Tcl_MakeFileChannel now takes a platform- - specific file handle. Tcl_DriverGetOptionProc procedures now take - an additional interp argument. - -5. Tcl newsgroup ------------------ - -There is a network news group "comp.lang.tcl" intended for the exchange -of information about Tcl, Tk, and related applications. Feel free to use -the newsgroup both for general information questions and for bug reports. -We read the newsgroup and will attempt to fix bugs and problems reported -to it. - -When using comp.lang.tcl, please be sure that your e-mail return address -is correctly set in your postings. This allows people to respond directly -to you, rather than the entire newsgroup, for answers that are not of -general interest. A bad e-mail return address may prevent you from -getting answers to your questions. You may have to reconfigure your news -reading software to ensure that it is supplying valid e-mail addresses. - -6. Tcl contributed archive + 1. Internationalization. Tcl has undergone a major revision to + support international character sets: + + All strings in Tcl are now represented in UTF-8 instead of ASCII, + so that Tcl now supports the full Unicode character set. The + representation of ASCII characters is unchanged (in UTF-8 anything + that looks like an ASCII character is an ASCII character), but + characters with the high-order bit set, such as those in ISO-8859, + are represented with multi-byte sequences, as are all Unicode + characters with values greater than 127. This change does not + affect Tcl scripts but it does affect C code that parses strings. + Tcl automatically translates between UTF-8 and the normal encoding + for the platform during interactions with the system. + + In Tcl scripts the backslash sequence \u can be used to enter + 16-bit Unicode characters. \o and \x generate only 8-bit + characters as before. + + There is a new "encoding" command that allows scripts to determine + what encodings are available as well as to convert strings between + different encodings. 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. + + There are several new C APIs that support UTF-8 and various + encodings. See the manual entry 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. + + 2. Binary data. Binary data is handled differently in Tcl 8.1 + than in Tcl 8.0. Tcl 8.1 uses the UTF-8 facilities to represent + binary data: the character value zero is represented with a + multi-byte sequence, so that (once again) strings in Tcl 8.1 never + contain null bytes. This means that binary data is now accepted + everywhere in Tcl and Tk (in Tcl 8.0 the support for binary data + was incomplete). If you have C code that needs to manipulate the + bytes of binary data (as opposed to just passing the data through) + you should use a new object type called "byte array". See the + manual entry ByteArrObj.3 for information about procedures such as + Tcl_GetByteArrayFromObj. + + 3. Regular expressions. Tcl 8.1 contains a brand new + implementation of regular expressions from Henry Spencer. The + regular expression syntax has been greatly expanded to include + most of the features in Perl. In addition, the regexp engine + supports Unicode and binary data. See the doc/regexp.n manual + entry for more details. + + 4. Threads. If configured with the --enable-threads flag, Tcl can + now be compiled for use in a multi-threaded application. + Individual threads are allowed to use one or more interpreters as + long as each interpreter (and any slave interpreters) is only + accessed by one thread. Each thread runs its own event loop, and + you can post events to other threads. There are new C APIs for + mutexes, condition variables, and thread local storage. See the + doc/Thread.3 manual entry for more details. Tk 8.1 is not yet + multi-thread safe. There is not yet support for tcl level use of + threading except for a test command. (Compile tcltest and try + testthread.) + + 5. Message catalog. There is a new message catalog package which makes + it easy to localize the strings in a script. See the doc/msgcat.n + manual entry for more details. + + 6. Stubbs library for building extensions. There is now a new + way to build extensions for Tcl. Instead of linking with the + tcl shared library you can now link to a stubs library that gets + built in this release. By linking with the stubs library it + is possible to use dynamically loaded extensions in staticlly + built applications. It will also be possible for some extensions + to work for both Tcl 8.0 & 8.1 with out having to recompile. + +5. Development tools +-------------------- + +A high quality set of commercial development tools is now available to +accelerate your Tcl application development. Scriptics' TclPro +product provides a debugger, static code checker, packaging utility, +and bytecode compiler. Visit the Scriptics Web site at: + + http://www.scriptics.com/tclpro + +for more information on TclPro and for a free 30-day evaluation +download. + +6. Tcl newsgroup +---------------- + +There is a network news group "comp.lang.tcl" intended for the +exchange of information about Tcl, Tk, and related applications. The +newsgroup is a greata place to ask general information questions. For +bug reports, please see the "Support and bug fixes" section below. + +7. Tcl contributed archive -------------------------- Many people have created exciting packages and applications based on Tcl and/or Tk and made them freely available to the Tcl community. An archive of these contributions is kept on the machine ftp.neosoft.com. You @@ -273,78 +255,101 @@ can access the archive using anonymous FTP; the Tcl contributed archive is in the directory "/pub/tcl". The archive also contains several FAQ ("frequently asked questions") documents that provide solutions to problems that are commonly encountered by TCL newcomers. -7. Mailing lists +8. Tcl Resource Center +---------------------- + +Visit http://www.scriptics.com/resource/ to see an annotated index of +many Tcl resources available on the World Wide Web. This includes +papers, books, and FAQs, as well as development tools, extensions, +applications, binary releases, and patches. You can also recommend +additional URLs for the resource center using the forms labeled "Add a +Resource". + +9. Mailing lists ---------------- A couple of Mailing List have been set up to discuss Macintosh or -Windows related Tcl issues. In order to use these Mailing Lists you -must have access to the internet. If you have access to the WWW the -home pages for these mailing lists are located at the following URLs: - - http://www.sunlabs.com/research/tcl/lists/mactcl-list.html - - -and- - - http://www.sunlabs.com/research/tcl/lists/wintcl-list.html - -The home pages contain information about the lists and an HTML archive -of all the past messages on the list. To subscribe send a message to: - - listserv@sunlabs.sun.com +Windows related Tcl issues. To subscribe send a message to: + + wintcl-request@tclconsortium.org + mactcl-request@tclconsortium.org In the body of the message (the subject will be ignored) put: - subscribe mactcl Joe Blow + subscribe mactcl Joe Smith -Replacing Joe Blow with your real name, of course. (Use wintcl +Replacing Joe Smith with your real name, of course. (Use wintcl instead of mactcl if your interested in the Windows list.) If you would just like to receive more information about the list without subscribing put the line: information mactcl in the body instead (or wintcl). -8. Support and bug fixes ------------------------- - -We're very interested in receiving bug reports and suggestions for -improvements. We prefer that you send this information to the -comp.lang.tcl newsgroup rather than to any of us at Sun. We'll see -anything on comp.lang.tcl, and in addition someone else who reads -comp.lang.tcl may be able to offer a solution. The normal turn-around -time for bugs is 3-6 weeks. Enhancements may take longer and may not -happen at all unless there is widespread support for them (we're -trying to slow the rate at which Tcl turns into a kitchen sink). It's -very difficult to make incompatible changes to Tcl at this point, due -to the size of the installed base. - -When reporting bugs, please provide a short tclsh script that we can -use to reproduce the bug. Make sure that the script runs with a -bare-bones tclsh and doesn't depend on any extensions or other -programs, particularly those that exist only at your site. Also, -please include three additional pieces of information with the -script: +10. Support and bug fixes +------------------------- + +Scriptics is very interested in receiving bug reports, patches, and +suggestions for improvements. We prefer that you send this +information to us via the bug form on the Scriptics Web site, rather +than emailing us directly. The bug form is at: + + http://www.scriptics.com/support/bugForm.html + +The bug form was designed to give uniform structure to bug reports as +well as to solicit enough information to minimize followup questions. +The bug form also includes an option to automatically post your report +on comp.lang.tcl. We strongly recommend that you select this option +because someone else who reads comp.lang.tcl may be able to offer a +solution. + +When reporting bugs, please provide full information about the Tcl/Tk +version and the platform on which you are running Tcl/Tk. Also, +please include a short tclsh script that we can use to reproduce the +bug. Make sure that the script runs with a bare-bones tclsh and +doesn't depend on any extensions or other programs, particularly those +that exist only at your site. Also, please include three additional +pieces of information with the script: + (a) how do we use the script to make the problem happen (e.g. what things do we click on, in what order)? (b) what happens when you do these things (presumably this is undesirable)? (c) what did you expect to happen instead? + +We will log and follow-up on each bug, although we cannot promise a +specific turn-around time. Enhancements may take longer and may not +happen at all unless there is widespread support for them (we're +trying to slow the rate at which Tcl/Tk turns into a kitchen sink). +It's very difficult to make incompatible changes to Tcl/Tk at this +point, due to the size of the installed base. The Tcl community is too large for us to provide much individual -support for users. If you need help we suggest that you post questions -to comp.lang.tcl. We read the newsgroup and will attempt to answer -esoteric questions for which no-one else is likely to know the answer. -In addition, Tcl support and training are available commercially from -NeoSoft (info@neosoft.com), Computerized Processes Unlimited -(gwl@cpu.com), and Data Kinetics (education@dkl.com). - -9. Tcl version numbers ----------------------- +support for users. If you need help we suggest that you post +questions to comp.lang.tcl. We read the newsgroup and will attempt to +answer esoteric questions for which no-one else is likely to know the +answer. In addition, Tcl/Tk support and training are available +commercially from Scriptics at: + + http://www.scriptics.com/training + +Also see the following Web site for links to other organizations that +offer Tcl/Tk training: + + http://www.scriptics.com/resource/commercial/training + +11. Tcl version numbers +----------------------- + +You can test the current version of Tcl by examining the +tcl_version and tcl_patchLevel variables. The tcl_patchLevel +variable follows the naming rules outlined below (e.g., 8.0.5). +The tcl_version just has the major.minor numbers in it (e.g., 8.0) Each Tcl release is identified by two numbers separated by a dot, e.g. 6.7 or 7.0. If a new release contains changes that are likely to break existing C code or Tcl scripts then the major release number increments and the minor number resets to zero: 6.0, 7.0, etc. If a new release @@ -373,9 +378,24 @@ a major problem turns up then we'll fix it even if it introduces an incompatibility. Once the official release is made then there won't be any more incompatibilities until the next release with a new major version number. -Patch releases have a suffix such as p1 or p2. These releases contain -bug fixes only. A patch release (e.g Tcl 7.6p2) should be completely -compatible with the base release from which it is derived (e.g. Tcl -7.6), and you should normally use the highest available patch release. +(Note: This compatibility is true for Tcl scripts, but historically +the Tcl C APIs have changed enough between releases that you may need +to work a bit to upgrade extensions.) + +Patch releases now have a suffix such as ".4" or ".5". Prior to +version 8.0.3, patch releases had the suffix "p1" or "p2". So, the +8.0 release went to 8.0p1, 8.0p2, 8.0.3, 8.0.4, and 8.0.5. The alphas +and betas continue to use the 'a' and 'b' letters in their +tcl_patchLevel. Patch releases normally contain bug fixes only. A +patch release (e.g Tcl 8.0.5) should be completely compatible with the +base release from which it is derived (e.g. Tcl 8.0), and you should +normally use the highest available patch release. + +12. Thank You +------------- + +We'd like to express our thanks to the Tcl community for all the +helpful suggestions, bug reports, and patches we have received. +Tcl/Tk has improved vastly and will continue to do so with your help. Index: changes ================================================================== --- changes +++ changes @@ -1,8 +1,8 @@ Recent user-visible changes to Tcl: -SCCS: @(#) changes 1.338 97/11/25 08:30:52 +RCS: @(#) $Id: changes,v 1.1.2.28 1999/04/06 19:06:51 surles Exp $ 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. @@ -2545,11 +2545,11 @@ 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.sunlabs.com/research/tcl/compiler.html. (BL) +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 @@ -3113,11 +3113,11 @@ 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 sunscript.sun.com (BW) +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) @@ -3449,5 +3449,861 @@ 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) --nameble-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 ---------------------- + Index: compat/README ================================================================== --- compat/README +++ compat/README @@ -3,6 +3,6 @@ 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. -sccsid = SCCS: @(#) README 1.3 96/02/16 08:56:51 +RCS: @(#) $Id: README,v 1.1.2.1 1998/09/24 23:58:16 stanton Exp $ Index: compat/dirent.h ================================================================== --- compat/dirent.h +++ compat/dirent.h @@ -8,11 +8,11 @@ * 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. * - * SCCS: @(#) dirent.h 1.4 96/02/15 14:43:50 + * RCS: @(#) $Id: dirent.h,v 1.1.2.1 1998/09/24 23:58:16 stanton Exp $ */ #ifndef _DIRENT #define _DIRENT Index: compat/dirent2.h ================================================================== --- compat/dirent2.h +++ compat/dirent2.h @@ -8,11 +8,11 @@ * 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. * - * SCCS: @(#) dirent2.h 1.4 96/02/15 14:43:51 + * RCS: @(#) $Id: dirent2.h,v 1.1.2.1 1998/09/24 23:58:16 stanton Exp $ */ #ifndef _DIRENT #define _DIRENT Index: compat/dlfcn.h ================================================================== --- compat/dlfcn.h +++ compat/dlfcn.h @@ -15,11 +15,11 @@ * 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. * - * SCCS: @(#) dlfcn.h 1.4 96/09/17 09:05:59 + * RCS: @(#) $Id: dlfcn.h,v 1.1.2.1 1998/09/24 23:58:16 stanton Exp $ */ /* * @(#)dlfcn.h 1.4 revision of 95/04/25 09:36:52 * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH Index: compat/fixstrtod.c ================================================================== --- compat/fixstrtod.c +++ compat/fixstrtod.c @@ -8,11 +8,11 @@ * 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. * - * SCCS: @(#) fixstrtod.c 1.5 96/02/15 12:08:21 + * RCS: @(#) $Id: fixstrtod.c,v 1.1.2.1 1998/09/24 23:58:17 stanton Exp $ */ #include #undef strtod Index: compat/float.h ================================================================== --- compat/float.h +++ compat/float.h @@ -10,7 +10,7 @@ * 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. * - * SCCS: @(#) float.h 1.3 96/02/15 14:43:52 + * RCS: @(#) $Id: float.h,v 1.1.2.1 1998/09/24 23:58:17 stanton Exp $ */ Index: compat/gettod.c ================================================================== --- compat/gettod.c +++ compat/gettod.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) gettod.c 1.2 96/02/15 12:08:26 + * RCS: @(#) $Id: gettod.c,v 1.1.2.1 1998/09/24 23:58:17 stanton Exp $ */ #include "tcl.h" #include "tclPort.h" #include Index: compat/limits.h ================================================================== --- compat/limits.h +++ compat/limits.h @@ -11,11 +11,11 @@ * 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. * - * SCCS: @(#) limits.h 1.8 96/07/08 18:00:13 + * RCS: @(#) $Id: limits.h,v 1.1.2.1 1998/09/24 23:58:17 stanton Exp $ */ #define LONG_MIN 0x80000000 #define LONG_MAX 0x7fffffff #define INT_MIN 0x80000000 ADDED compat/memcmp.c Index: compat/memcmp.c ================================================================== --- /dev/null +++ compat/memcmp.c @@ -0,0 +1,61 @@ +/* + * 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. + * + * SCCS: @(#) memcmp.c 1.2 98/01/19 10:48:58 + */ + +#include "tcl.h" +#include "tclPort.h" + +/* + * Here is the prototype just in case it is not included + * in tclPort.h. + */ + +int memcmp _ANSI_ARGS_((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, accord- + * ing as s1 is less than, equal to, or + * greater than s2 when taken to be unsigned 8 bit numbers. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +memcmp(s1, s2, n) + CONST VOID *s1; /* First string. */ + CONST VOID *s2; /* Second string. */ + size_t n; /* Length to compare. */ +{ + unsigned char u1, u2; + + for ( ; n-- ; s1++, s2++) { + u1 = * (unsigned char *) s1; + u2 = * (unsigned char *) s2; + if ( u1 != u2) { + return (u1-u2); + } + } + return 0; +} Index: compat/opendir.c ================================================================== --- compat/opendir.c +++ compat/opendir.c @@ -5,11 +5,11 @@ * 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. * * - * SCCS: @(#) opendir.c 1.3 96/02/15 12:08:21 + * RCS: @(#) $Id: opendir.c,v 1.1.2.1 1998/09/24 23:58:17 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" Index: compat/stdlib.h ================================================================== --- compat/stdlib.h +++ compat/stdlib.h @@ -7,16 +7,16 @@ * 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 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) stdlib.h 1.10 96/02/15 14:43:54 + * RCS: @(#) $Id: stdlib.h,v 1.1.2.2 1998/09/24 23:58:17 stanton Exp $ */ #ifndef _STDLIB #define _STDLIB Index: compat/strftime.c ================================================================== --- compat/strftime.c +++ compat/strftime.c @@ -6,11 +6,11 @@ * * This file is a modified version of the strftime.c file from the BSD 4.4 * source. See the copyright notice below for details on redistribution * restrictions. The "license.terms" file does not apply to this file. * - * SCCS: @(#) strftime.c 1.4 97/08/07 17:17:02 + * RCS: @(#) $Id: strftime.c,v 1.1.2.3 1999/03/10 06:49:09 stanton Exp $ */ /* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. @@ -42,14 +42,13 @@ * 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. */ -#if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)strftime.c 5.11 (Berkeley) 2/24/91";*/ -static char *rcsid = "$Id: strftime.c,v 1.1 1998/03/26 14:46:31 rjohnson Exp $"; -#endif /* LIBC_SCCS and not lint */ +#if defined(LIBC_SCCS) +static char *rcsid = "$Id: strftime.c,v 1.1.2.3 1999/03/10 06:49:09 stanton Exp $"; +#endif /* LIBC_SCCS */ #include #include #include #include "tclInt.h" @@ -104,11 +103,11 @@ static int _secs _ANSI_ARGS_((const struct tm *t)); static size_t _fmt _ANSI_ARGS_((const char *format, const struct tm *t)); size_t -TclStrftime(s, maxsize, format, t) +TclpStrftime(s, maxsize, format, t) char *s; size_t maxsize; const char *format; const struct tm *t; { @@ -314,11 +313,11 @@ if (!_conv((t->tm_year + TM_YEAR_BASE), 4, '0')) return(0); continue; #ifndef MAC_TCL case 'Z': { - char *name = TclpGetTZName(); + char *name = TclpGetTZName(t->tm_isdst); if (name && !_add(name)) { return 0; } continue; } Index: compat/string.h ================================================================== --- compat/string.h +++ compat/string.h @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) string.h 1.13 96/04/09 22:14:53 + * RCS: @(#) $Id: string.h,v 1.1.2.2 1998/09/24 23:58:17 stanton Exp $ */ #ifndef _STRING #define _STRING @@ -30,12 +30,16 @@ extern char * memchr _ANSI_ARGS_((CONST VOID *s, int c, size_t n)); extern int memcmp _ANSI_ARGS_((CONST VOID *s1, CONST VOID *s2, size_t n)); extern char * memcpy _ANSI_ARGS_((VOID *t, CONST VOID *f, size_t n)); +#ifdef NO_MEMMOVE +#define memmove(d, s, n) bcopy ((s), (d), (n)) +#else extern char * memmove _ANSI_ARGS_((VOID *t, CONST VOID *f, size_t n)); +#endif extern char * memset _ANSI_ARGS_((VOID *s, int c, size_t n)); extern int strcasecmp _ANSI_ARGS_((CONST char *s1, CONST char *s2)); extern char * strcat _ANSI_ARGS_((char *dst, CONST char *src)); Index: compat/strncasecmp.c ================================================================== --- compat/strncasecmp.c +++ compat/strncasecmp.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) strncasecmp.c 1.7 96/10/24 15:23:36 + * RCS: @(#) $Id: strncasecmp.c,v 1.1.2.1 1998/09/24 23:58:17 stanton Exp $ */ #include "tclPort.h" /* Index: compat/strstr.c ================================================================== --- compat/strstr.c +++ compat/strstr.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) strstr.c 1.4 96/02/15 12:08:22 + * RCS: @(#) $Id: strstr.c,v 1.1.2.1 1998/09/24 23:58:18 stanton Exp $ */ /* *---------------------------------------------------------------------- * Index: compat/strtod.c ================================================================== --- compat/strtod.c +++ compat/strtod.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) strtod.c 1.9 96/12/13 15:02:46 + * RCS: @(#) $Id: strtod.c,v 1.1.2.1 1998/09/24 23:58:18 stanton Exp $ */ #include "tcl.h" #ifdef NO_STDLIB_H # include "../compat/stdlib.h" Index: compat/strtol.c ================================================================== --- compat/strtol.c +++ compat/strtol.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) strtol.c 1.4 96/02/15 12:08:23 + * RCS: @(#) $Id: strtol.c,v 1.1.2.1 1998/09/24 23:58:18 stanton Exp $ */ #include Index: compat/strtoul.c ================================================================== --- compat/strtoul.c +++ compat/strtoul.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) strtoul.c 1.5 96/02/15 12:08:24 + * RCS: @(#) $Id: strtoul.c,v 1.1.2.1 1998/09/24 23:58:18 stanton Exp $ */ #include /* Index: compat/tclErrno.h ================================================================== --- compat/tclErrno.h +++ compat/tclErrno.h @@ -9,11 +9,11 @@ * 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. * - * SCCS: @(#) tclErrno.h 1.1 96/04/29 15:25:31 + * RCS: @(#) $Id: tclErrno.h,v 1.1.2.1 1998/09/24 23:58:18 stanton Exp $ */ extern int errno; /* global error number */ #define EPERM 1 /* Operation not permitted */ Index: compat/tmpnam.c ================================================================== --- compat/tmpnam.c +++ compat/tmpnam.c @@ -7,11 +7,11 @@ * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific written prior permission. This software * is provided ``as is'' without express or implied warranty. * - * SCCS: @(#) tmpnam.c 1.3 96/02/15 12:08:25 + * RCS: @(#) $Id: tmpnam.c,v 1.1.2.1 1998/09/24 23:58:18 stanton Exp $ */ #include #include #include Index: compat/unistd.h ================================================================== --- compat/unistd.h +++ compat/unistd.h @@ -10,11 +10,11 @@ * 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. * - * SCCS: @(#) unistd.h 1.7 96/02/15 14:43:57 + * RCS: @(#) $Id: unistd.h,v 1.1.2.1 1998/09/24 23:58:18 stanton Exp $ */ #ifndef _UNISTD #define _UNISTD Index: compat/waitpid.c ================================================================== --- compat/waitpid.c +++ compat/waitpid.c @@ -10,11 +10,11 @@ * 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. * - * SCCS: @(#) waitpid.c 1.9 96/02/15 12:08:26 + * RCS: @(#) $Id: waitpid.c,v 1.1.2.1 1998/09/24 23:58:18 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" Index: doc/AddErrInfo.3 ================================================================== --- doc/AddErrInfo.3 +++ doc/AddErrInfo.3 @@ -3,17 +3,17 @@ '\" 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. '\" -'\" SCCS: @(#) AddErrInfo.3 1.28 97/06/12 13:39:53 +'\" RCS: @(#) $Id: AddErrInfo.3,v 1.1.2.2 1999/03/10 06:49:10 stanton Exp $ '\" .so man.macros .TH Tcl_AddErrorInfo 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME -Tcl_AddObjErrorInfo, Tcl_AddErrorInfo, Tcl_SetErrorCode, Tcl_PosixError \- record information about errors +Tcl_AddObjErrorInfo, Tcl_AddErrorInfo, Tcl_SetErrorCode, Tcl_SetErrorCodeVA, Tcl_PosixError \- record information about errors .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_AddObjErrorInfo\fR(\fIinterp, message, length\fR) @@ -21,10 +21,12 @@ \fBTcl_AddErrorInfo\fR(\fIinterp, message\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 char * \fBTcl_PosixError\fR(\fIinterp\fR) .SH ARGUMENTS .AS Tcl_Interp *message @@ -45,10 +47,13 @@ .AP Tcl_Obj *errorObjPtr in This variable \fBerrorCode\fR will be set to this value. .AP char *element in String to record as one element of \fBerrorCode\fR variable. Last \fIelement\fR argument must be NULL. +.AP va_list argList in +An argument list which must have been initialised using +\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR. .BE .SH DESCRIPTION .PP These procedures are used to manipulate two Tcl global variables @@ -116,10 +121,13 @@ The procedure \fBTcl_SetErrorCode\fR is also used to set the \fBerrorCode\fR variable. However, it takes one or more strings to record instead of an object. 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 \fBTcl_PosixError\fR sets the \fBerrorCode\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 \fBerrorCode\fR in the \fBPOSIX\fR format. The caller must previously have called \fBTcl_SetErrno\fR to set Index: doc/Alloc.3 ================================================================== --- doc/Alloc.3 +++ doc/Alloc.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) Alloc.3 1.2 96/06/05 18:00:19 +'\" RCS: @(#) $Id: Alloc.3,v 1.1.2.1 1998/09/24 23:58:19 stanton Exp $ '\" .so man.macros .TH Tcl_Alloc 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/AllowExc.3 ================================================================== --- doc/AllowExc.3 +++ doc/AllowExc.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) AllowExc.3 1.5 96/03/25 19:55:47 +'\" RCS: @(#) $Id: AllowExc.3,v 1.1.2.1 1998/09/24 23:58:19 stanton Exp $ '\" .so man.macros .TH Tcl_AllowExceptions 3 7.4 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/AppInit.3 ================================================================== --- doc/AppInit.3 +++ doc/AppInit.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) AppInit.3 1.10 96/08/26 12:59:40 +'\" RCS: @(#) $Id: AppInit.3,v 1.1.2.1 1998/09/24 23:58:19 stanton Exp $ '\" .so man.macros .TH Tcl_AppInit 3 7.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/AssocData.3 ================================================================== --- doc/AssocData.3 +++ doc/AssocData.3 @@ -3,11 +3,11 @@ '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" '\" -'\" SCCS: @(#) AssocData.3 1.8 96/03/25 19:56:17 +'\" RCS: @(#) $Id: AssocData.3,v 1.1.2.2 1999/04/09 21:01:29 surles Exp $ .so man.macros .TH Tcl_SetAssocData 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Tcl_GetAssocData, Tcl_SetAssocData, Tcl_DeleteAssocData \- manage @@ -82,8 +82,8 @@ 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. It does not call the deletion procedure. +the given interpreter. Then it calls the deletion procedure. .SH KEYWORDS association, data, deletion procedure, interpreter, key Index: doc/Async.3 ================================================================== --- doc/Async.3 +++ doc/Async.3 @@ -3,17 +3,17 @@ '\" 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. '\" -'\" SCCS: @(#) Async.3 1.14 96/08/26 12:59:41 +'\" RCS: @(#) $Id: Async.3,v 1.1.2.2 1999/04/14 00:30:35 surles Exp $ '\" .so man.macros .TH Tcl_AsyncCreate 3 7.0 Tcl "Tcl Library Procedures" .BS .SH NAME -Tcl_AsyncCreate, Tcl_AsyncMark, Tcl_AsyncInvoke, Tcl_AsyncDelete \- handle asynchronous events +Tcl_AsyncCreate, Tcl_AsyncMark, Tcl_AsyncInvoke, Tcl_AsyncDelete, Tcl_AsyncReady \- handle asynchronous events .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_AsyncHandler Index: doc/BackgdErr.3 ================================================================== --- doc/BackgdErr.3 +++ doc/BackgdErr.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) BackgdErr.3 1.3 96/03/25 19:56:51 +'\" RCS: @(#) $Id: BackgdErr.3,v 1.1.2.1 1998/09/24 23:58:19 stanton Exp $ '\" .so man.macros .TH Tcl_BackgroundError 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/Backslash.3 ================================================================== --- doc/Backslash.3 +++ doc/Backslash.3 @@ -3,14 +3,14 @@ '\" 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. '\" -'\" SCCS: @(#) Backslash.3 1.16 96/03/25 19:57:09 +'\" RCS: @(#) $Id: Backslash.3,v 1.1.2.2 1998/09/24 23:58:20 stanton Exp $ '\" .so man.macros -.TH Tcl_Backslash 3 "" Tcl "Tcl Library Procedures" +.TH Tcl_Backslash 3 "8.1" Tcl "Tcl Library Procedures" .BS .SH NAME Tcl_Backslash \- parse a backslash sequence .SH SYNOPSIS .nf @@ -28,18 +28,26 @@ the backslash character. .BE .SH DESCRIPTION .PP -This is a utility procedure used by several of the Tcl -commands. It parses a backslash sequence and returns -the single character corresponding to the sequence. -\fBTcl_Backslash\fR modifies \fI*countPtr\fR to contain the number -of characters in the backslash sequence. +.VS 8.1 +The use of \fBTcl_Backslash\fR is deprecated in favor of +\fBTcl_UtfBackslash\fR. +.PP +This is a utility procedure provided for backwards compatibilty with +non-internationalized Tcl extensions. It parses a backslash sequence and +returns the low byte of the Unicode character corresponding to the sequence. +.VE +\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. +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. +.VS 8.1 br +.SH "SEE ALSO" +Tcl(n), Tcl_UtfBackslash(3) +.VE .SH KEYWORDS backslash, parse Index: doc/BoolObj.3 ================================================================== --- doc/BoolObj.3 +++ doc/BoolObj.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) @(#) BoolObj.3 1.7 97/05/08 19:50:57 +'\" RCS: @(#) $Id: BoolObj.3,v 1.1.2.1 1998/09/24 23:58:20 stanton Exp $ '\" .so man.macros .TH Tcl_BooleanObj 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME ADDED doc/ByteArrObj.3 Index: doc/ByteArrObj.3 ================================================================== --- /dev/null +++ doc/ByteArrObj.3 @@ -0,0 +1,91 @@ +'\" +'\" 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. +'\" +'\" RCS: @(#) $Id: ByteArrObj.3,v 1.1.2.2 1998/10/21 20:21:31 stanton Exp $ +'\" +.so man.macros +.TH Tcl_ByteArrayObj 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_NewByteArrayObj, Tcl_SetByteArrayObj, Tcl_GetByteArrayFromObj, Tcl_SetByteArrayLength \- manipulate Tcl objects 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 "unsigned char" *lengthPtr in/out +.AP "unsigned char" *bytes in +The array of bytes used to initialize or set a byte-array object. +.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 object to be converted to +byte-array type. For \fBTcl_GetByteArrayFromObj\fR and +\fBTcl_SetByteArrayLength\fR, this points to the object from which to get +the byte-array value; if \fIobjPtr\fR does not already point to a byte-array +object, it will be converted to one. +.AP int *lengthPtr out +If non-NULL, filled with the length of the array of bytes in the object. +.BE + +.SH DESCRIPTION +.PP +These procedures are used to create, modify, and read Tcl byte-array objects +from C code. Byte-array objects 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. +Accesser functions are provided to get the string representation of a +byte-array or to convert an arbitrary object to a byte-array. Obtaining the +string representation of a byte-array object (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 object of byte-array type or modify an existing object to have a +byte-array type. Both of these procedures set the object's type to be +byte-array and set the object'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 object with a reference count of zero. +\fBTcl_SetByteArrayObj\fR invalidates any old string representation and, if +the object is not already a byte-array object, frees any old internal +representation. +.PP +\fBTcl_GetByteArrayFromObj\fR converts a Tcl object to byte-array type and +returns a pointer to the object'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 object and should not be freed. The contents of the array may be +modified by the caller only if the object is not shared and the caller +invalidates the string representation. +.PP +\fBTcl_SetByteArrayLength\fR converts the Tcl object to byte-array type +and changes the length of the object'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 object's new array of bytes. + +.SH "SEE ALSO" +Tcl_GetStringFromObj, Tcl_NewObj, Tcl_IncrRefCount, Tcl_DecrRefCount + +.SH KEYWORDS +object, byte array, utf, unicode, internationalization Index: doc/CallDel.3 ================================================================== --- doc/CallDel.3 +++ doc/CallDel.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) CallDel.3 1.11 96/03/25 19:57:25 +'\" RCS: @(#) $Id: CallDel.3,v 1.1.2.1 1998/09/24 23:58:20 stanton Exp $ '\" .so man.macros .TH Tcl_CallWhenDeleted 3 7.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/CmdCmplt.3 ================================================================== --- doc/CmdCmplt.3 +++ doc/CmdCmplt.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) CmdCmplt.3 1.6 96/03/25 19:57:46 +'\" RCS: @(#) $Id: CmdCmplt.3,v 1.1.2.1 1998/09/24 23:58:20 stanton Exp $ '\" .so man.macros .TH Tcl_CommandComplete 3 "" Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/Concat.3 ================================================================== --- doc/Concat.3 +++ doc/Concat.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) Concat.3 1.12 97/06/11 17:54:12 +'\" RCS: @(#) $Id: Concat.3,v 1.1.2.1 1998/09/24 23:58:20 stanton Exp $ '\" .so man.macros .TH Tcl_Concat 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/CrtChannel.3 ================================================================== --- doc/CrtChannel.3 +++ doc/CrtChannel.3 @@ -2,17 +2,17 @@ '\" 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. '\" -'\" SCCS: @(#) CrtChannel.3 1.29 97/06/20 13:37:45 +'\" RCS: @(#) $Id: CrtChannel.3,v 1.1.2.3 1999/04/13 00:01:57 surles Exp $ .so man.macros .TH Tcl_CreateChannel 3 8.0 Tcl "Tcl Library Procedures" .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_SetDefaultTranslation, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption \- procedures for creating and manipulating channels +Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelHandle, Tcl_GetChannelMode, Tcl_GetChannelBufferSize, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption \- procedures for creating and manipulating channels .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Channel @@ -30,15 +30,10 @@ .sp int \fBTcl_GetChannelHandle\fR(\fIchannel, direction, handlePtr\fR) .VE .sp -int -\fBTcl_GetChannelFlags\fR(\fIchannel\fR) -.sp -\fBTcl_SetDefaultTranslation\fR(\fIchannel, transMode\fR) -.sp int \fBTcl_GetChannelBufferSize\fR(\fIchannel\fR) .sp \fBTcl_SetChannelBufferSize\fR(\fIchannel, size\fR) .sp @@ -168,17 +163,11 @@ .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_SetDefaultTranslation\fR sets the default end of line translation -mode. This mode will be installed as the translation mode for the channel -if an attempt is made to output on the channel while it is still in -\fBTCL_TRANSLATE_AUTO\fR mode. For a description of end of line translation -modes, see the manual entry for \fBfconfigure\fR. -.PP -\fBTcl_GetChannelBufferSize\fR returns the size, in bytes, of buffers + \fBTcl_GetChannelBufferSize\fR returns the size, in bytes, of buffers allocated to store input or output in \fIchan\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 @@ -219,20 +208,23 @@ 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_ChannelType; .CE .VE .PP The driver must provide implementations for all functions except -\fIblockModeProc\fR, \fIseekProc\fR, \fIsetOptionProc\fR, and -\fIgetOptionProc\fR, which may be specified as NULL to indicate that the -channel does not support seeking. Other functions that can not be -implemented for this type of device should return \fBEINVAL\fR when invoked -to indicate that they are not implemented. +\fIblockModeProc\fR, \fIseekProc\fR, \fIsetOptionProc\fR, +.VS +\fIgetOptionProc\fR, and \fIclose2Proc\fR, which may be specified as +.VE +NULL. Other functions that can not be implemented for this type of +device should return \fBEINVAL\fR when invoked to indicate that they +are not implemented. .SH TYPENAME .PP The \fItypeName\fR field contains a null-terminated string that identifies the type of the device implemented by this driver, e.g. @@ -262,11 +254,11 @@ 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. -.SH CLOSEPROC +.SH 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 @@ -284,10 +276,39 @@ 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 \fIinterp->result\fR. +.PP +.VS +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 Tcl_DriverClose2Proc( + 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 \fIinterp->result\fR. +.VE .SH 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 @@ -380,11 +401,11 @@ 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_SeekChannel\fR +\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. Index: doc/CrtChnlHdlr.3 ================================================================== --- doc/CrtChnlHdlr.3 +++ doc/CrtChnlHdlr.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) CrtChnlHdlr.3 1.10 96/03/14 10:54:43 +'\" RCS: @(#) $Id: CrtChnlHdlr.3,v 1.1.2.1 1998/09/24 23:58:20 stanton Exp $ .so man.macros .TH Tcl_CreateChannelHandler 3 7.5 Tcl "Tcl Library Procedures" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/CrtCloseHdlr.3 ================================================================== --- doc/CrtCloseHdlr.3 +++ doc/CrtCloseHdlr.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) CrtCloseHdlr.3 1.7 96/04/15 13:08:19 +'\" RCS: @(#) $Id: CrtCloseHdlr.3,v 1.1.2.1 1998/09/24 23:58:21 stanton Exp $ .so man.macros .TH Tcl_CreateCloseHandler 3 7.5 Tcl "Tcl Library Procedures" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/CrtCommand.3 ================================================================== --- doc/CrtCommand.3 +++ doc/CrtCommand.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) CrtCommand.3 1.29 97/06/04 17:23:53 +'\" RCS: @(#) $Id: CrtCommand.3,v 1.1.2.2 1998/10/06 02:59:03 stanton Exp $ '\" .so man.macros .TH Tcl_CreateCommand 3 "" Tcl "Tcl Library Procedures" .BS .SH NAME @@ -92,11 +92,16 @@ 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. +last value is NULL. +.VS +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. +.VE .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, \fIproc\fR must set Index: doc/CrtFileHdlr.3 ================================================================== --- doc/CrtFileHdlr.3 +++ doc/CrtFileHdlr.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) CrtFileHdlr.3 1.7 97/04/23 16:11:17 +'\" RCS: @(#) $Id: CrtFileHdlr.3,v 1.1.2.1 1998/09/24 23:58:21 stanton Exp $ '\" .so man.macros .TH Tcl_CreateFileHandler 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/CrtInterp.3 ================================================================== --- doc/CrtInterp.3 +++ doc/CrtInterp.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) CrtInterp.3 1.17 97/10/31 13:05:51 +'\" RCS: @(#) $Id: CrtInterp.3,v 1.1.2.1 1998/09/24 23:58:21 stanton Exp $ '\" .so man.macros .TH Tcl_CreateInterp 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/CrtMathFnc.3 ================================================================== --- doc/CrtMathFnc.3 +++ doc/CrtMathFnc.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) CrtMathFnc.3 1.9 96/08/26 12:59:43 +'\" RCS: @(#) $Id: CrtMathFnc.3,v 1.1.2.1 1998/09/24 23:58:21 stanton Exp $ '\" .so man.macros .TH Tcl_CreateMathFunc 3 7.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/CrtObjCmd.3 ================================================================== --- doc/CrtObjCmd.3 +++ doc/CrtObjCmd.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) @(#) CrtObjCmd.3 1.10 97/07/31 14:10:38 +'\" RCS: @(#) $Id: CrtObjCmd.3,v 1.1.2.3 1999/04/13 00:01:57 surles Exp $ '\" .so man.macros .TH Tcl_CreateObjCommand 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME @@ -60,12 +60,14 @@ 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_EvalObj\fR) the Tcl interpreter will call \fIproc\fR to process the command. .PP -\fBTcl_CreateObjCommand\fR will delete any command \fIname\fR -already associated with the interpreter. +\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. @@ -99,11 +101,11 @@ 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 object argument. For instance, the user may call -\fBTcl_GetIntFromObject\fR on \fIobjv\fR[\fB2\fR] to obtain the integer +\fBTcl_GetIntFromObj\fR on \fIobjv\fR[\fB2\fR] to obtain the integer representation of that object; that call may change the type of the object that \fIobjv\fR[\fB2\fR] points at, but will not change where \fIobjv\fR[\fB2\fR] points. .VE .PP @@ -126,10 +128,21 @@ 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 Index: doc/CrtSlave.3 ================================================================== --- doc/CrtSlave.3 +++ doc/CrtSlave.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) CrtSlave.3 1.26 97/07/31 18:00:14 +'\" RCS: @(#) $Id: CrtSlave.3,v 1.1.2.1 1998/09/24 23:58:22 stanton Exp $ '\" .so man.macros .TH Tcl_CreateSlave 3 7.6 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/CrtTimerHdlr.3 ================================================================== --- doc/CrtTimerHdlr.3 +++ doc/CrtTimerHdlr.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) CrtTimerHdlr.3 1.4 96/09/17 10:54:58 +'\" RCS: @(#) $Id: CrtTimerHdlr.3,v 1.1.2.1 1998/09/24 23:58:22 stanton Exp $ '\" .so man.macros .TH Tcl_CreateTimerHandler 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/CrtTrace.3 ================================================================== --- doc/CrtTrace.3 +++ doc/CrtTrace.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) CrtTrace.3 1.14 96/03/25 20:01:10 +'\" RCS: @(#) $Id: CrtTrace.3,v 1.1.2.1 1998/09/24 23:58:22 stanton Exp $ '\" .so man.macros .TH Tcl_CreateTrace 3 "" Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/DString.3 ================================================================== --- doc/DString.3 +++ doc/DString.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) DString.3 1.20 96/08/26 12:59:44 +'\" RCS: @(#) $Id: DString.3,v 1.1.2.1 1998/09/24 23:58:22 stanton Exp $ '\" .so man.macros .TH Tcl_DString 3 7.4 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/DetachPids.3 ================================================================== --- doc/DetachPids.3 +++ doc/DetachPids.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) DetachPids.3 1.15 96/08/26 12:59:44 +'\" RCS: @(#) $Id: DetachPids.3,v 1.1.2.1 1998/09/24 23:58:22 stanton Exp $ '\" .so man.macros .TH Tcl_DetachPids 3 "" Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/DoOneEvent.3 ================================================================== --- doc/DoOneEvent.3 +++ doc/DoOneEvent.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) DoOneEvent.3 1.6 97/05/09 18:12:05 +'\" RCS: @(#) $Id: DoOneEvent.3,v 1.1.2.1 1998/09/24 23:58:22 stanton Exp $ '\" .so man.macros .TH Tcl_DoOneEvent 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/DoWhenIdle.3 ================================================================== --- doc/DoWhenIdle.3 +++ doc/DoWhenIdle.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) DoWhenIdle.3 1.6 97/05/09 18:18:33 +'\" RCS: @(#) $Id: DoWhenIdle.3,v 1.1.2.1 1998/09/24 23:58:23 stanton Exp $ '\" .so man.macros .TH Tcl_DoWhenIdle 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/DoubleObj.3 ================================================================== --- doc/DoubleObj.3 +++ doc/DoubleObj.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) @(#) DoubleObj.3 1.6 97/05/08 19:50:07 +'\" RCS: @(#) $Id: DoubleObj.3,v 1.1.2.1 1998/09/24 23:58:23 stanton Exp $ '\" .so man.macros .TH Tcl_DoubleObj 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME ADDED doc/Encoding.3 Index: doc/Encoding.3 ================================================================== --- /dev/null +++ doc/Encoding.3 @@ -0,0 +1,484 @@ +'\" +'\" 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. +'\" +'\" RCS: @(#) $Id: Encoding.3,v 1.1.2.5 1999/04/13 00:01:57 surles Exp $ +'\" +.so man.macros +.TH Tcl_GetEncoding 3 "8.1" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_ExternalToUtfDString, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternal, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNames, Tcl_CreateEncoding, 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 +void +\fBTcl_ExternalToUtfDString\fR(\fIencoding, src, srcLen, dstPtr\fR) +.sp +int +\fBTcl_ExternalToUtf\fR(\fIinterp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, + dstCharsPtr\fR) +.sp +void +\fBTcl_UtfToExternalDString\fR(\fIencoding, src, srcLen, dstPtr\fR) +.sp +int +\fBTcl_UtfToExternal\fR(\fIinterp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, + dstCharsPtr\fR) +.sp +char * +\fBTcl_GetEncodingName\fR(\fIencoding\fR) +.sp +int +\fBTcl_SetSystemEncoding\fR(\fIinterp, name\fR) +.sp +void +\fBTcl_GetEncodingNames\fR(\fIinterp\fR) +.sp +Tcl_Encoding +\fBTcl_CreateEncoding\fR(\fItypePtr\fR) + +.sp +char * +\fBTcl_GetDefaultEncodingDir\fR(\fIvoid\fR) +.sp +void +\fBTcl_SetDefaultEncodingDir\fR(\fIpath\fR) + + +.SH ARGUMENTS +.AS Tcl_EncodingState *dstWrotePtr +.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 "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 functions, an array of UTF-8 characters to be +converted to the specified encoding. +.AP int srcLen in +Length of \fIsrc\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. +TCL_ENCODING_START 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. TCL_ENCODING_END 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. +TCL_ENCODING_STOPONERROR signifies that the conversion routine should +return immediately upon reading a source character that doesn't 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_EncodingType *typePtr in +Structure that defines a new type of encoding. +.AP 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 builtin 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_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. +.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 fews 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 TCL_ENCODING_STOPONERROR 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. +.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_GetEncodingName\fR is roughly the inverse of \fBTk_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, TCL_ERROR 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 +TCL_OK. +.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; +} Tcl_EncodingType; +.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 Tcl_EncodingConvertProc( + ClientData \fIclientData\fR, + CONST char *\fIsrc\fR, + int \fIsrcLen\fR, + int \fIflags\fR, + Tcl_Encoding *\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: +.CS +typedef void Tcl_EncodingFreeProc( + 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_GetDefaultEncodingDir\fR and \fBTcl_SetDefaultEncodingDir\fR +access and set the directory to use when locating the default encoding +files. If this value is not NULL, the \fBTclpInitLibraryPath\fR routine +appends the path to the head of the search path, and uses this path as +the first place to look into when trying to locate the encoding file. + +.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 ``#'' 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 a 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): +.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 doesn't 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: +.CS +.ta 1.5i +# Encoding file: iso2022-jp, escape-driven +E +init {} +final {} +iso8859-1 \\x1b(B +jis0201 \\x1b(J +jis0208 \\x1b$@ +jis0208 \\x1b$B +jis0212 \\x1b$(D +gb2312 \\x1b$A +ksc5601 \\x1b$(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, ``\fB{}\fR'' represents the empty string and +``\fB\\x1b\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 specified in the +library path \fB$tcl_libPath\fR. If the encoding file exists, but is +malformed, an error message will be left in \fIinterp\fR. +.SH KEYWORDS +utf, encoding, convert + + + Index: doc/Eval.3 ================================================================== --- doc/Eval.3 +++ doc/Eval.3 @@ -3,112 +3,194 @@ '\" 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. '\" -'\" SCCS: @(#) Eval.3 1.21 97/01/22 14:22:03 +'\" RCS: @(#) $Id: Eval.3,v 1.1.2.5 1999/03/10 06:49:10 stanton Exp $ '\" .so man.macros -.TH Tcl_Eval 3 7.0 Tcl "Tcl Library Procedures" +.TH Tcl_Eval 3 8.1 Tcl "Tcl Library Procedures" .BS .SH NAME -Tcl_Eval, Tcl_VarEval, Tcl_EvalFile, Tcl_GlobalEval \- execute Tcl commands +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 +.VS int -\fBTcl_Eval\fR(\fIinterp, cmd\fR) -.sp -int -\fBTcl_VarEval\fR(\fIinterp, string, string, ... \fB(char *) NULL\fR) +\fBTcl_EvalObjEx\fR(\fIinterp, objPtr, flags\fR) .sp int \fBTcl_EvalFile\fR(\fIinterp, fileName\fR) .sp int -\fBTcl_GlobalEval\fR(\fIinterp, cmd\fR) +\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, flags\fR) +.sp +int +\fBTcl_VarEval\fR(\fIinterp, string, string, ... \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 command. -A string result will be stored in \fIinterp->result\fR. -.AP char *cmd in -Command (or sequence of commands) to execute. Must be in writable -memory (\fBTcl_Eval\fR makes temporary modifications to the command). -.AP char *string in -String forming part of Tcl command. +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 object 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 char *fileName in -Name of file containing Tcl command string. +Name of a file containing a Tcl script. +.AP int *objc in +The number of objects 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 objects; each object 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 char *script in +Points to first byte of script to execute. This script must be in +writable memory: temporary modifications are made to it during +parsing. +.AP char *string in +String forming part of a Tcl script. +.AP va_list argList in +An argument list which must have been initialised using +\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR. .BE .SH DESCRIPTION .PP -All four of these procedures execute Tcl commands. -\fBTcl_Eval\fR is the core procedure and is used by all the others. -It executes the commands in the script held by \fIcmd\fR -until either an error occurs or it reaches the end of the script. -.PP -Note that \fBTcl_Eval\fR and \fBTcl_GlobalEval\fR -have been largely replaced by the -object-based procedures \fBTcl_EvalObj\fR and \fBTcl_GlobalEvalObj\fR. -Those object-based procedures evaluate a script held in a Tcl object -instead of a string. -The object argument can retain the bytecode instructions for the script -and so avoid reparsing the script each time it is executed. -\fBTcl_Eval\fR is implemented using \fBTcl_EvalObj\fR -but is slower because it must reparse the script each time -since there is no object to retain the bytecode instructions. -.PP -The return value from \fBTcl_Eval\fR is one of the Tcl return codes -\fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or -\fBTCL_CONTINUE\fR, and \fIinterp->result\fR will point to -a string with additional information (a result value or error message). -If an error occurs during compilation, this return information -describes the error. -Otherwise, this return information corresponds to the last command -executed from \fIcmd\fR. +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 object 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. +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 couldn't be read then a Tcl error is returned to describe +why the file couldn't be read. +.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 object in +\fIobjv\fR. \fBTcl_EvalObjv\fR evaluates the command and returns +a completion code and result just like \fBTcl_EvalObjEx\fR. +.PP +\fBTcl_Eval\fR is similar to \fBTcl_EvalObjEx\fR except that +the script to be executed is supplied as a string instead of an +object and no compilation occurs. 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 object result in \fIinterp\fR to \fIinterp->result\fR +where it can be accessed directly. This makes \fBTcl_Eval\fR somewhat +slower than \fBTcl_EvalEx\fR, which doesn't 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 usual fashion for Tcl commands. +\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. +of arguments. \fBTcl_VarEval\fR is now deprecated. .PP -\fBTcl_EvalFile\fR reads the file given by \fIfileName\fR and evaluates -its contents as a Tcl command by calling \fBTcl_Eval\fR. It returns -a standard Tcl result that reflects the result of evaluating the file. -If the file couldn't be read then a Tcl error is returned to describe -why the file couldn't be read. +\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" +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 an object are going to change immediately, so the +bytecodes won't be reused in a future execution. In this case, +it's 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 at 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_Eval\fR invocation, +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_Eval\fR keeps track of how many nested \fBTcl_Eval\fR +\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_Eval\fR +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->result\fR -to point to an error message indicating that +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_Eval\fR other then \fBTCL_OK\fR or \fBTCL_ERROR\fR. - -.SH "SEE ALSO" -Tcl_EvalObj, Tcl_GlobalEvalObj +from \fBTcl_EvalObjEx\fR other then \fBTCL_OK\fR or \fBTCL_ERROR\fR. +.VE .SH KEYWORDS -command, execute, file, global, object, object result, variable +execute, file, global, object, result, script DELETED doc/EvalObj.3 Index: doc/EvalObj.3 ================================================================== --- doc/EvalObj.3 +++ /dev/null @@ -1,91 +0,0 @@ -'\" -'\" 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. -'\" -'\" SCCS: @(#) EvalObj.3 1.4 97/01/22 15:18:44 -'\" -.so man.macros -.TH Tcl_EvalObj 3 8.0 Tcl "Tcl Library Procedures" -.BS -.SH NAME -Tcl_EvalObj, Tcl_GlobalEvalObj \- execute Tcl commands -.SH SYNOPSIS -.nf -\fB#include \fR -.sp -int -\fBTcl_EvalObj\fR(\fIinterp, objPtr\fR) -.sp -int -\fBTcl_GlobalEvalObj\fR(\fIinterp, objPtr\fR) -.SH ARGUMENTS -.AS Tcl_Interp **termPtr; -.AP Tcl_Interp *interp in -Interpreter in which to execute the command. -The command's result will be stored in the interpreter's result object -and can be retrieved using \fBTcl_GetObjResult\fR. -.AP Tcl_Obj *objPtr in -A Tcl object containing a command string -(or sequence of commands in a string) to execute. -.BE - -.SH DESCRIPTION -.PP -These two procedures execute Tcl commands. -\fBTcl_EvalObj\fR is the core procedure -and is used by \fBTcl_GlobalEvalObj\fR. -It executes the commands in the script held by \fIobjPtr\fR -until either an error occurs or it reaches the end of the script. -If this is the first time \fIobjPtr\fR has been executed, -its commands are compiled into bytecode instructions -that are then executed if there are no compilation errors. -.PP -The return value from \fBTcl_EvalObj\fR is one of the Tcl return codes -\fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or -\fBTCL_CONTINUE\fR, -and a result object containing additional information -(a result value or error message) -that can be retrieved using \fBTcl_GetObjResult\fR. -If an error occurs during compilation, this return information -describes the error. -Otherwise, this return information corresponds to the last command -executed from \fIobjPtr\fR. -.PP -\fBTcl_GlobalEvalObj\fR is similar to \fBTcl_EvalObj\fR except that it -processes the command at global level. -This means that the variable context for the command consists of -global variables only (it ignores any Tcl procedure that is active). -This produces an effect similar to the Tcl command ``\fBuplevel 0\fR''. -.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_EvalObj\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_EvalObj\fR keeps track of how many nested \fBTcl_EvalObj\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_EvalObj\fR -invocation for \fIinterp\fR, -it converts the return code to \fBTCL_ERROR\fR -and sets the interpreter's result object -to point 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_EvalObj\fR other then \fBTCL_OK\fR or \fBTCL_ERROR\fR. - -.SH "SEE ALSO" -Tcl_GetObjResult, Tcl_SetObjResult - -.SH KEYWORDS -command, execute, file, global, object, object result, variable Index: doc/Exit.3 ================================================================== --- doc/Exit.3 +++ doc/Exit.3 @@ -2,17 +2,17 @@ '\" 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. '\" -'\" SCCS: @(#) Exit.3 1.8 96/12/10 07:37:23 +'\" RCS: @(#) $Id: Exit.3,v 1.1.2.2 1998/09/24 23:58:23 stanton Exp $ '\" .so man.macros -.TH Tcl_Exit 3 7.7 Tcl "Tcl Library Procedures" +.TH Tcl_Exit 3 8.1 Tcl "Tcl Library Procedures" .BS .SH NAME -Tcl_Exit, Tcl_Finalize, Tcl_CreateExitHandler, Tcl_DeleteExitHandler \- end the application (and invoke exit handlers) +Tcl_Exit, Tcl_Finalize, Tcl_FinalizeThread, Tcl_CreateExitHandler, Tcl_DeleteExitHandler, Tcl_CreateThreadExitHandler, Tcl_DeleteThreadExitHandler \- end the application or thread (and invoke exit handlers) .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_Exit\fR(\fIstatus\fR) @@ -20,14 +20,23 @@ \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) .SH ARGUMENTS .AS Tcl_ExitProc clientData .AP int status in -Provides information about why application exited. Exact meaning may +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. .AP ClientData clientData in @@ -49,11 +58,10 @@ 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. .PP -.VS \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. @@ -62,32 +70,44 @@ not necessary for the caller to explicitly call \fBTcl_Finalize\fR. However, to ensure portability, your code should always invoke \fBTcl_Finalize\fR when \fBTcl\fR is being unloaded, to ensure that the code will work on all platforms. \fBTcl_Finalize\fR can be safely called more than once. +.PP +.VS +\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. .VE .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: .CS typedef void Tcl_ExitProc(ClientData \fIclientData\fR); .CE The \fIclientData\fR parameter to \fIproc\fR is a copy of the \fIclientData\fR argument given to -\fBTcl_CreateExitHandler\fR when the callback +\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 may be called to delete a +\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 does nothing. +\fBTcl_DeleteExitHandler\fR or \fBTcl_DeleteThreadExitHandler\fR does nothing. .PP .VS .PP \fBTcl_Finalize\fR and \fBTcl_Exit\fR execute all registered exit handlers, in reverse order from the order in which they were registered. @@ -96,8 +116,16 @@ 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. .VE +.VS +.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. +.VE .SH KEYWORDS -callback, cleanup, dynamic loading, end application, exit, unloading +callback, cleanup, dynamic loading, end application, exit, unloading, thread Index: doc/ExprLong.3 ================================================================== --- doc/ExprLong.3 +++ doc/ExprLong.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) ExprLong.3 1.26 97/06/26 13:42:47 +'\" RCS: @(#) $Id: ExprLong.3,v 1.1.2.1 1998/09/24 23:58:23 stanton Exp $ '\" .so man.macros .TH Tcl_ExprLong 3 7.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/ExprLongObj.3 ================================================================== --- doc/ExprLongObj.3 +++ doc/ExprLongObj.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) ExprLongObj.3 1.6 97/06/26 13:41:12 +'\" RCS: @(#) $Id: ExprLongObj.3,v 1.1.2.1 1998/09/24 23:58:23 stanton Exp $ '\" .so man.macros .TH Tcl_ExprLongObj 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/FindExec.3 ================================================================== --- doc/FindExec.3 +++ doc/FindExec.3 @@ -2,35 +2,38 @@ '\" 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. '\" -'\" SCCS: @(#) FindExec.3 1.4 96/10/09 08:29:29 +'\" RCS: @(#) $Id: FindExec.3,v 1.1.2.1 1998/09/24 23:58:23 stanton Exp $ '\" .so man.macros .TH Tcl_FindExecutable 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME -Tcl_FindExecutable \- identify the binary file containing the application +Tcl_FindExecutable, Tcl_GetNameOfExecutable \- identify or return the name of the binary file containing the application .SH SYNOPSIS .nf \fB#include \fR .sp char * \fBTcl_FindExecutable\fR(\fIargv0\fR) +.sp +CONST char * +\fBTcl_GetNameOfExecutable\fR() .SH ARGUMENTS .AS char *argv0 in .AP char *argv0 in The first command-line argument to the program, which gives the application's name. .BE .SH DESCRIPTION .PP -This 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 \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 @@ -39,8 +42,15 @@ \fIargv[0]\fR as its argument. \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 +\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 ADDED doc/GetCwd.3 Index: doc/GetCwd.3 ================================================================== --- /dev/null +++ doc/GetCwd.3 @@ -0,0 +1,54 @@ +'\" +'\" Copyright (c) 1998-1999 Scriptics Corportation +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +'\" RCS: @(#) $Id: GetCwd.3,v 1.1.2.2 1999/04/06 02:56:07 rjohnson Exp $ +'\" +.so man.macros +.TH Tcl_GetCwd 3 8.1 Tcl "Tcl Library Procedures" +.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 +.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 interp'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 Index: doc/GetIndex.3 ================================================================== --- doc/GetIndex.3 +++ doc/GetIndex.3 @@ -2,23 +2,30 @@ '\" 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. '\" -'\" SCCS: @(#) @(#) GetIndex.3 1.3 97/07/30 16:21:05 +'\" RCS: @(#) $Id: GetIndex.3,v 1.1.2.2 1998/09/24 23:58:24 stanton Exp $ '\" .so man.macros -.TH Tcl_GetIndexFromObj 3 8.0 Tcl "Tcl Library Procedures" +.TH Tcl_GetIndexFromObj 3 8.1 Tcl "Tcl Library Procedures" .BS .SH NAME Tcl_GetIndexFromObj \- lookup string in table of keywords .SH SYNOPSIS .nf \fB#include \fR .sp int -\fBTcl_GetIndexFromObj\fR(\fIinterp, objPtr, tablePtr, msg, flags, indexPtr\fR) +\fBTcl_GetIndexFromObj\fR(\fIinterp, objPtr, tablePtr, msg, flags, +indexPtr\fR) +.VS +.sp +int +\fBTcl_GetIndexFromObjStruct\fR(\fIinterp, objPtr, tablePtr, offset, +msg, flags, indexPtr\fR) +.VE .SH ARGUMENTS .AS Tcl_Interp **tablePtr .AP Tcl_Interp *interp in Interpreter to use for error reporting; if NULL, then no message is provided on errors. @@ -27,10 +34,15 @@ The internal representation is modified to hold the index of the matching table entry. .AP char **tablePtr in An array of null-terminated strings. The end of the array is marked by a NULL string pointer. +.VS +.AP int offset in +The offset to add to tablePtr to get to the next string in the +list. The end of the array is marked by a NULL string pointer. +.VE .AP 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 @@ -66,12 +78,23 @@ 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. +in \fItablePtr\fR are static: they must not change between +invocations. +.VS +.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 the +first in a series of string ptrs that are spaced apart by \fIoffset\fR +bytes. 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. +.VE .SH "SEE ALSO" Tcl_WrongNumArgs .SH KEYWORDS index, object, table lookup Index: doc/GetInt.3 ================================================================== --- doc/GetInt.3 +++ doc/GetInt.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) GetInt.3 1.12 96/03/25 20:03:44 +'\" RCS: @(#) $Id: GetInt.3,v 1.1.2.1 1998/09/24 23:58:24 stanton Exp $ '\" .so man.macros .TH Tcl_GetInt 3 "" Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/GetOpnFl.3 ================================================================== --- doc/GetOpnFl.3 +++ doc/GetOpnFl.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) GetOpnFl.3 1.3 97/04/23 16:14:43 +'\" RCS: @(#) $Id: GetOpnFl.3,v 1.1.2.1 1998/09/24 23:58:24 stanton Exp $ .so man.macros .TH Tcl_GetOpenFile 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME Tcl_GetOpenFile \- Get a standard IO File * handle from a channel. (Unix only) Index: doc/GetStdChan.3 ================================================================== --- doc/GetStdChan.3 +++ doc/GetStdChan.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" @(#) GetStdChan.3 1.2 96/03/08 13:59:57 +'\" RCS: @(#) $Id: GetStdChan.3,v 1.1.2.1 1998/09/24 23:58:24 stanton Exp $ '\" .so man.macros .TH Tcl_GetStdChannel 3 7.5 Tcl "Tcl Library Procedures" .BS '\" Note: do not modify the .SH NAME line immediately below! ADDED doc/GetVersion.3 Index: doc/GetVersion.3 ================================================================== --- /dev/null +++ doc/GetVersion.3 @@ -0,0 +1,49 @@ +'\" +'\" 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. +'\" +'\" RCS: @(#) $Id: GetVersion.3,v 1.1.2.1 1999/04/07 03:21:21 stanton Exp $ +'\" +.so man.macros +.TH Tcl_GetVersion 3 7.5 Tcl "Tcl Library Procedures" +.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 +.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 +If may pass a 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 + Index: doc/Hash.3 ================================================================== --- doc/Hash.3 +++ doc/Hash.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) Hash.3 1.15 96/03/25 20:04:01 +'\" RCS: @(#) $Id: Hash.3,v 1.1.2.1 1998/09/24 23:58:24 stanton Exp $ '\" .so man.macros .TH Tcl_Hash 3 "" Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/IntObj.3 ================================================================== --- doc/IntObj.3 +++ doc/IntObj.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) @(#) IntObj.3 1.7 97/05/08 19:49:22 +'\" RCS: @(#) $Id: IntObj.3,v 1.1.2.1 1998/09/24 23:58:24 stanton Exp $ '\" .so man.macros .TH Tcl_IntObj 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/Interp.3 ================================================================== --- doc/Interp.3 +++ doc/Interp.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) Interp.3 1.16 96/06/06 13:48:02 +'\" RCS: @(#) $Id: Interp.3,v 1.1.2.1 1998/09/24 23:58:24 stanton Exp $ '\" .so man.macros .TH Tcl_Interp 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/LinkVar.3 ================================================================== --- doc/LinkVar.3 +++ doc/LinkVar.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) LinkVar.3 1.15 96/09/05 17:16:57 +'\" RCS: @(#) $Id: LinkVar.3,v 1.1.2.1 1998/09/24 23:58:24 stanton Exp $ '\" .so man.macros .TH Tcl_LinkVar 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/ListObj.3 ================================================================== --- doc/ListObj.3 +++ doc/ListObj.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) @(#) ListObj.3 1.10 97/10/08 11:36:58 +'\" RCS: @(#) $Id: ListObj.3,v 1.1.2.1 1998/09/24 23:58:24 stanton Exp $ '\" .so man.macros .TH Tcl_ListObj 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/Notifier.3 ================================================================== --- doc/Notifier.3 +++ doc/Notifier.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) Notifier.3 1.16 97/05/17 17:03:17 +'\" RCS: @(#) $Id: Notifier.3,v 1.1.2.1 1998/09/24 23:58:25 stanton Exp $ '\" .so man.macros .TH Notifier 3 8.0 Tcl "Tcl Library Procedures" .BS .VS DELETED doc/ObjSetVar.3 Index: doc/ObjSetVar.3 ================================================================== --- doc/ObjSetVar.3 +++ /dev/null @@ -1,162 +0,0 @@ -'\" -'\" 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. -'\" -'\" SCCS: @(#) ObjSetVar.3 1.6 97/05/19 17:35:44 -'\" -.so man.macros -.TH Tcl_ObjSetVar2 3 8.0 Tcl "Tcl Library Procedures" -.BS -.SH NAME -Tcl_ObjSetVar2, Tcl_ObjGetVar2 \- manipulate Tcl variables -.SH SYNOPSIS -.nf -\fB#include \fR -.sp -Tcl_Obj * -\fBTcl_ObjSetVar2\fR(\fIinterp, part1Ptr, part2Ptr, newValuePtr, flags\fR) -.sp -Tcl_Obj * -\fBTcl_ObjGetVar2\fR(\fIinterp, part1Ptr, part2Ptr, flags\fR) -.SH ARGUMENTS -.AS Tcl_Interp *newValuePtr -.AP Tcl_Interp *interp in -Interpreter containing variable. -.AP Tcl_Obj *part1Ptr in -Points to a Tcl object 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 an object containing the name of an element -within an array and \fIpart1Ptr\fR must refer to an array variable. -.AP Tcl_Obj *newValuePtr in -Points to a Tcl object containing the new value for the variable. -.AP int flags in -OR-ed combination of bits providing additional information for -operation. See below for valid values. -.BE - -.SH DESCRIPTION -.PP -These two procedures may be used to read and modify -Tcl variables from C code. -\fBTcl_ObjSetVar2\fR will create a new variable or modify an existing one. -It sets the specified variable to -the object referenced by \fInewValuePtr\fR -and returns a pointer to the object which is the variable's new value. -The returned object may not be the same one -referenced by \fInewValuePtr\fR; -this might happen because variable traces may modify the variable's value. -The reference count for the variable's old value is decremented -and the reference count for its new value is incremented. -If the new value for the variable -is not the same one referenced by \fInewValuePtr\fR -(perhaps as a result of a variable trace), -then \fInewValuePtr\fR's reference count is left unchanged. -The reference count for the returned object is not incremented -to reflect the returned reference. -If the caller needs to keep a reference to the object, -say in a data structure, -it must increment its reference count using \fBTcl_IncrRefCount\fR. -If an error occurs in setting the variable -(e.g. an array variable is referenced -without giving an index into the array), -then NULL is returned. -.PP -The variable name specified to \fBTcl_ObjSetVar2\fR consists of two parts. -\fIpart1Ptr\fR contains the name of a scalar or array variable. -If \fIpart2Ptr\fR is NULL, the variable must be a scalar. -If \fIpart2Ptr\fR is not NULL, -it contains the name of an element in the array named by \fIpart2Ptr\fR. -As a special case, if the flag TCL_PARSE_PART1 is specified, -\fIpart1Ptr\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 the flag TCL_PARSE_PART1 is given, -\fIpart2Ptr\fR should be NULL since the array and element names -are taken from \fIpart2Ptr\fR. -.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 any 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, -a variable is looked up at the current level of procedure call. -Otherwise, a 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 -Under normal circumstances the procedures look up variables as follows: -If a procedure call is active in \fIinterp\fR, -a variable is looked up at the current level of procedure call. -Otherwise, a 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 current namespace -even if there is a procedure call active. -.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 isn't 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 is appended to the current -value, instead of replacing it. -If the variable is currently undefined, then this bit is ignored. -.TP -\fBTCL_LIST_ELEMENT\fR -If this bit is set, then \fInewValuePtr\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 ``{'', or ends in `` }''). -.TP -\fBTCL_PARSE_PART1\fR -If this bit is set, -then \fBTcl_ObjGetVar2\fR and \fBTcl_ObjSetVar2\fR -will parse \fIpart1Ptr\fR -to obtain both an array name and an element name. -If the name in \fIpart1Ptr\fR contains an open parenthesis -and ends with a close parenthesis, -the name is treated as the name of an element of an array; -otherwise, the name in \fIpart1Ptr\fR -is interpreted as the name of a scalar variable. -When this bit is set, -\fIpart2Ptr\fR is ignored. -.PP -\fBTcl_ObjGetVar2\fR returns the value of the specified variable. -Its arguments are treated the same way as those for \fBTcl_ObjSetVar2\fR. -It returns a pointer to the object which is the variable's value. -The reference count for the returned object is not incremented. -If the caller needs to keep a reference to the object, -say in a data structure, -it must increment the reference count using \fBTcl_IncrRefCount\fR. -If an error occurs in setting the variable -(e.g. an array variable is referenced -without giving an index into the array), -then NULL is returned. - -.SH "SEE ALSO" -Tcl_GetObjResult, Tcl_GetStringResult, Tcl_GetVar, Tcl_GetVar2, Tcl_SetVar, Tcl_SetVar2, Tcl_TraceVar, Tcl_UnsetVar, Tcl_UnsetVar2 - -.SH KEYWORDS -array, interpreter, object, scalar, set, unset, variable Index: doc/Object.3 ================================================================== --- doc/Object.3 +++ doc/Object.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) @(#) Object.3 1.10 97/07/22 11:40:10 +'\" RCS: @(#) $Id: Object.3,v 1.1.2.4 1999/04/14 00:30:36 surles Exp $ '\" .so man.macros .TH Tcl_Obj 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME @@ -83,11 +83,11 @@ when the object'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. +procedures like \fBTcl_GetStringFromObj\fR and \fBTcl_GetString\fR. .PP Objects are allocated on the heap and are referenced using a pointer to their \fBTcl_Obj\fR structure. Objects are shared as much as possible. This significantly reduces storage requirements @@ -136,11 +136,11 @@ The \fIlength\fR member gives the number of bytes. The byte array must always have a null after the last byte, at offset \fIlength\fR; this allows string representations that do not contain nulls to be treated as conventional null-terminated C strings. -C programs use \fBTcl_GetStringFromObj\fR to get +C programs use \fBTcl_GetStringFromObj\fR and \fBTcl_GetString\fR to get an object's string representation. If \fIbytes\fR is NULL, the string representation is invalid. .PP An object's type manages its internal representation. @@ -175,21 +175,22 @@ A key property of Tcl objects is that they hold two representations. An object typically starts out containing only a string representation: it is untyped and has a NULL \fItypePtr\fR. An object containing an empty string or a copy of a specified string is created using \fBTcl_NewObj\fR or \fBTcl_NewStringObj\fR respectively. -An object's string value is gotten with \fBTcl_GetStringFromObj\fR +An object's string value is gotten with +\fBTcl_GetStringFromObj\fR or \fBTcl_GetString\fR and changed with \fBTcl_SetStringObj\fR. If the object is later passed to a procedure like \fBTcl_GetIntFromObj\fR that requires a specific internal representation, the procedure will create one and set the object's \fItypePtr\fR. The internal representation is computed from the string representation. An object's two representations are duals of each other: changes made to one are reflected in the other. For example, \fBTcl_ListObjReplace\fR will modify an object's internal representation and the next call to \fBTcl_GetStringFromObj\fR -will reflect that change. +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. @@ -206,11 +207,11 @@ free any storage associated with the old string representation. .PP Objects usually remain one type over their life, but occasionally an object must be converted from one type to another. For example, a C program might build up a string in an object -with repeated calls to \fBTcl_StringObjAppend\fR, +with repeated calls to \fBTcl_AppendToObj\fR, and then call \fBTcl_ListObjIndex\fR to extract a list element from the object. The same object holding the same string value can have several different internal representations at different times. Index: doc/ObjectType.3 ================================================================== --- doc/ObjectType.3 +++ doc/ObjectType.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) ObjectType.3 1.8 97/04/30 15:42:29 +'\" RCS: @(#) $Id: ObjectType.3,v 1.1.2.1 1998/09/24 23:58:25 stanton Exp $ '\" .so man.macros .TH Tcl_ObjType 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/OpenFileChnl.3 ================================================================== --- doc/OpenFileChnl.3 +++ doc/OpenFileChnl.3 @@ -2,17 +2,17 @@ '\" 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. '\" -'\" SCCS: @(#) OpenFileChnl.3 1.40 97/09/29 11:22:49 +'\" RCS: @(#) $Id: OpenFileChnl.3,v 1.1.2.2 1998/09/24 23:58:25 stanton Exp $ .so man.macros -.TH Tcl_OpenFileChannel 3 8.0 Tcl "Tcl Library Procedures" +.TH Tcl_OpenFileChannel 3 8.1 Tcl "Tcl Library Procedures" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME -Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_Close, Tcl_Read, Tcl_Gets, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_GetChannelOption, Tcl_SetChannelOption \- buffered I/O facilities using channels +Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_Close, Tcl_ReadChars, Tcl_Read, Tcl_GetsObj, Tcl_Gets, Tcl_WriteObj, Tcl_WriteChars, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_GetChannelOption, Tcl_SetChannelOption, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, \- buffered I/O facilities using channels .SH SYNOPSIS .nf \fB#include \fR .sp typedef ... Tcl_Channel; @@ -20,11 +20,11 @@ Tcl_Channel \fBTcl_OpenFileChannel\fR(\fIinterp, fileName, mode, permissions\fR) .sp Tcl_Channel \fBTcl_OpenCommandChannel\fR(\fIinterp, argc, argv, flags\fR) -.VS +.VS 8.0 .sp Tcl_Channel \fBTcl_MakeFileChannel\fR(\fIhandle, readOrWrite\fR) .VE .sp @@ -38,21 +38,32 @@ \fBTcl_UnregisterChannel\fR(\fIinterp, channel\fR) .sp int \fBTcl_Close\fR(\fIinterp, channel\fR) .sp +.VS 8.1 int -\fBTcl_Read\fR(\fIchannel, buf, toRead\fR) +\fBTcl_ReadChars\fR(\fIchannel, readObjPtr, charsToRead, appendFlag\fR) .sp int -\fBTcl_Gets\fR(\fIchannel, lineRead\fR) +\fBTcl_Read\fR(\fIchannel, byteBuf, bytesToRead\fR) .sp int \fBTcl_GetsObj\fR(\fIchannel, lineObjPtr\fR) .sp int -\fBTcl_Write\fR(\fIchannel, buf, toWrite\fR) +\fBTcl_Gets\fR(\fIchannel, lineRead\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) +.VE .sp int \fBTcl_Flush\fR(\fIchannel\fR) .sp int @@ -81,69 +92,82 @@ .AP Tcl_Interp *interp in Used for error reporting and to look up a channel registered in it. .AP char *fileName in The name of a local or network file. .AP 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. -For \fBTcl_OpenCommandChannel\fR, may be NULL. +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. For +\fBTcl_OpenCommandChannel\fR, may be NULL. .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. +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 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. +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. -.VS +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. +.VS 8.0 .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 char *channelName in +The name of the channel. .VE .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 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 char *buf in -An array of bytes in which to store channel input, or from which -to read channel output. -.AP int len in -The length of the input or output. -.AP int atEnd in -If nonzero, store the input at the end of the input queue, otherwise store -it at the head of the input queue. -.AP int toRead in -The number of bytes to read from the channel. -.AP Tcl_DString *lineRead in -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 Tcl_Obj *linePtrObj in +.VS 8.1 br +.AP Tcl_Obj *readObjPtr in/out +A pointer to a Tcl Object 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 object. +Otherwise, the data will replace the existing contents of the object. +.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 object in which to store the line read from the channel. The line read will be appended to the current value of the object. -.AP int toWrite in -The number of bytes to read from \fIbuf\fR and output to the channel. +.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 Tcl_Obj *writeObjPtr in +A pointer to a Tcl Object whose contents will be output to the channel. +.AP "CONST char" *charBuf in +A buffer containing the characters to output to the channel. +.AP 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. +.VE .AP int 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 @@ -167,11 +191,11 @@ 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 modelled after +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 @@ -180,19 +204,19 @@ .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 modelled after the \fBfopen\fR procedure of +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->result\fR after any error. +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, described below. If one of the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was previously closed, the act of creating the new channel also assigns it as a @@ -308,97 +332,140 @@ closing of the channel and \fIinterp\fR is not NULL, an error message is left in \fIinterp->result\fR. .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_READ -.PP -\fBTcl_Read\fR consumes up to \fItoRead\fR bytes of data from -\fIchannel\fR and stores it at \fIbuf\fR. -The return value of \fBTcl_Read\fR is the number of characters written -at \fIbuf\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. -If an error occurs, the return value is -1 and \fBTcl_Read\fR records -a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. -.PP -The return value may be smaller than the value of \fItoRead\fR, indicating -that less data than requested was available, also 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_Read\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_Read\fR translates platform-specific 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. - -.SH TCL_GETS AND TCL_GETSOBJ -.PP -\fBTcl_Gets\fR reads a line of input from a channel and appends all of -the characters of the line except for the terminating end-of-line character(s) -to the dynamic string given by \fIdsPtr\fR. -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 it indicates the number of characters stored -in the dynamic string. -If an error occurs, \fBTcl_Gets\fR returns -1 and records a POSIX error -code that can be retrieved with \fBTcl_GetErrno\fR. -\fBTcl_Gets\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_GetsObj\fR is the same as \fBTcl_Gets\fR except the resulting -characters are appended to a Tcl object \fBlineObjPtr\fR rather than a -dynamic string. -.SH TCL_WRITE -.PP -\fBTcl_Write\fR accepts \fItoWrite\fR bytes of data at \fIbuf\fR for output -on \fIchannel\fR. This data may not appear on the output device -immediately. If the data should appear immediately, call \fBTcl_Flush\fR -after the call to \fBTcl_Write\fR, or set the \fB-buffering\fR option on -the channel to \fBnone\fR. If you wish the data to appear as soon as an end -of line is accepted for output, set the \fB\-buffering\fR option on the -channel to \fBline\fR mode. -.PP -The \fItoWrite\fR argument specifies how many bytes of data are provided in -the \fIbuf\fR argument. If it is negative, \fBTcl_Write\fR expects the data +\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. + +.VS 8.1 br +.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 \fIobjPtr\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 +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 object. The string representation of this object 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 doesn't 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 +\fIbuf\fR, performing end-of-line translations on the way. The return value +of \fBTcl_Read\fR is the number of bytes, up to \fItoRead\fR, written in +\fIbuf\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. + +.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 appended to the dynamic string given by +\fIdsPtr\fR rather than a Tcl object. + +.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 -The return value of \fBTcl_Write\fR is a count of how many -characters were accepted for output to the channel. This is either equal to -\fItoWrite\fR or -1 to indicate that an error occurred. -If an error occurs, \fBTcl_Write\fR also records a POSIX error code -that may be retrieved with \fBTcl_GetErrno\fR. +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. +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 object 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 object are written to the channel. The byte-array representation +of the object 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 doesn't 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. +.VE .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. @@ -417,18 +484,18 @@ \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 +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. +value is \-1 if the channel does not support seeking. .SH TCL_GETCHANNELOPTION .PP \fBTcl_GetChannelOption\fR retrieves, in \fIdsPtr\fR, the value of one of the options currently in effect for a channel, or a list of all options and @@ -475,11 +542,11 @@ .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. -.VS +.VS 8.0 .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 Index: doc/OpenTcp.3 ================================================================== --- doc/OpenTcp.3 +++ doc/OpenTcp.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) OpenTcp.3 1.19 97/06/25 14:44:00 +'\" RCS: @(#) $Id: OpenTcp.3,v 1.1.2.1 1998/09/24 23:58:25 stanton Exp $ .so man.macros .TH Tcl_OpenTcpClient 3 8.0 Tcl "Tcl Library Procedures" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME ADDED doc/ParseCmd.3 Index: doc/ParseCmd.3 ================================================================== --- /dev/null +++ doc/ParseCmd.3 @@ -0,0 +1,426 @@ +'\" +'\" 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. +'\" +'\" RCS: @(#) $Id: ParseCmd.3,v 1.1.2.2 1998/10/21 20:21:31 stanton Exp $ +'\" +.so man.macros +.TH Tcl_ParseCommand 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_ParseCommand, Tcl_ParseExpr, Tcl_ParseBraces, Tcl_ParseQuotedString, Tcl_ParseVarName, Tcl_FreeParse, Tcl_EvalTokens \- parse Tcl scripts and expressions +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTcl_ParseCommand\fR(\fIinterp, string, numBytes, nested, parsePtr\fR) +.sp +int +\fBTcl_ParseExpr\fR(\fIinterp, string, numBytes, parsePtr\fR) +.sp +int +\fBTcl_ParseBraces\fR(\fIinterp, string, numBytes, parsePtr, append, termPtr\fR) +.sp +int +\fBTcl_ParseQuotedString\fR(\fIinterp, string, numBytes, parsePtr, append, termPtr\fR) +.sp +int +\fBTcl_ParseVarName\fR(\fIinterp, string, numBytes, parsePtr, append\fR) +.sp +\fBTcl_FreeParse\fR(\fIusedParsePtr\fR) +.sp +Tcl_Obj * +\fBTcl_EvalTokens\fR(\fIinterp, tokenPtr, numTokens\fR) +.SH ARGUMENTS +.AS Tcl_Interp *usedParsePtr +.AP Tcl_Interp *interp out +For procedures other than \fBTcl_FreeParse\fR and \fBTcl_EvalTokens\fR, +used only for error reporting; +if NULL, then no error messages are left after errors. +For \fBTcl_EvalTokens\fR, determines the context for evaluating the +script and also is used for error reporting; must not be NULL. +.AP char *string in +Pointer to first character in string to parse. +.AP int numBytes in +Number of bytes in \fIstring\fR, not including any terminating null +character. If less than 0 then the script consists of all characters +in \fIstring\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 char **termPtr out +If not NULL, points to a location where +\fBTcl_ParseBraces\fR and \fBTcl_ParseQuotedString\fR +will store a pointer to the character +just after the terminating close-brace or 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's\fR 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_ParseCommand\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 \\t with \\t tabs}\fR +from the beginning of its argument \fIstring\fR. +The first character of \fIstring\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 occurrs 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 \fIstring\fR. +The first character of \fIstring\fR must be \fB"\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"\fR +in the location given by \fI*termPtr\fR. +If an error occurrs 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 +\fIstring\fR argument. +The first character of \fIstring\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 +occurrs while parsing the command then \fBTCL_ERROR\fR is returned, an +error message is left in \fIinterp\fR's result (if \fIinterp\fR isn't +NULL), and no information is left at \fI*parsePtr\fR. +.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_EvalTokens\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_EvalTokens\fR performs the +substitutions requested by the tokens, concatenates the +resulting values, and returns the result in a new Tcl_Obj. The +reference count of the object returned as result has been +incremented, so the caller must +invoke \fBTcl_DecrRefCount\fR when it is finished with the object. +If an error 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. + +.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: +.CS +typedef struct Tcl_Parse { + char *\fIcommentStart\fR; + int \fIcommentSize\fR; + char *\fIcommandStart\fR; + int \fIcommandSize\fR; + int \fInumWords\fR; + Tcl_Token *\fItokenPtr\fR; + int \fInumTokens\fR; + ... +} Tcl_Parse; + +typedef struct Tcl_Token { + int \fItype\fR; + char *\fIstart\fR; + int \fIsize\fR; + int \fInumComponents\fR; +} Tcl_Token; +.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_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 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. +An \fBTCL_TOKEN_OPERATOR\fR token is always preceeded 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. 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 +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 \fIstring\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 \fIstring\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 Index: doc/PkgRequire.3 ================================================================== --- doc/PkgRequire.3 +++ doc/PkgRequire.3 @@ -2,28 +2,40 @@ '\" 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. '\" -'\" SCCS: @(#) PkgRequire.3 1.4 96/02/15 20:03:16 +'\" RCS: @(#) $Id: PkgRequire.3,v 1.1.2.2 1999/03/10 06:49:10 stanton Exp $ '\" .so man.macros .TH Tcl_PkgRequire 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME -Tcl_PkgRequire, Tcl_PkgProvide \- package version control +Tcl_PkgRequire, Tcl_PkgRequireEx, Tcl_PkgPresent, Tcl_PkgPresentEx, Tcl_PkgProvide, Tcl_PkgProvideEx \- package version control .SH SYNOPSIS .nf \fB#include \fR .sp char * \fBTcl_PkgRequire\fR(\fIinterp, name, version, exact\fR) .sp +char * +\fBTcl_PkgRequireEx\fR(\fIinterp, name, version, exact, clientDataPtr\fR) +.sp +char * +\fBTcl_PkgPresent\fR(\fIinterp, name, version, exact\fR) +.sp +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 Tcl_FreeProc clientData +.AS Tcl_FreeProc clientDataPtr .AP Tcl_Interp *interp in Interpreter where package is needed or available. .AP char *name in Name of package. .AP char *version in @@ -33,27 +45,43 @@ 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 ClientData clientData in +Arbitrary value to be associated with the package. +.AP ClientData *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. .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. -If \fBTcl_PkgRequire\fR completes successfully it returns 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 it returns NULL and leaves an error message in -\fIinterp->result\fR. +.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 \fIinterp->result\fR. +.PP \fBTcl_PkgProvide\fR returns TCL_OK if it completes successfully; if an error occurs it returns TCL_ERROR and leaves an error message in \fIinterp->result\fR. +.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. .SH KEYWORDS -package, provide, require, version +package, present, provide, require, version Index: doc/Preserve.3 ================================================================== --- doc/Preserve.3 +++ doc/Preserve.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) Preserve.3 1.13 96/05/28 09:26:12 +'\" RCS: @(#) $Id: Preserve.3,v 1.1.2.1 1998/09/24 23:58:25 stanton Exp $ '\" .so man.macros .TH Tcl_Preserve 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/PrintDbl.3 ================================================================== --- doc/PrintDbl.3 +++ doc/PrintDbl.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) PrintDbl.3 1.9 97/08/22 13:30:22 +'\" RCS: @(#) $Id: PrintDbl.3,v 1.1.2.1 1998/09/24 23:58:26 stanton Exp $ '\" .so man.macros .TH Tcl_PrintDouble 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/RecEvalObj.3 ================================================================== --- doc/RecEvalObj.3 +++ doc/RecEvalObj.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: SCCS: @(#) RecEvalObj.3 1.1 97/07/29 18:31:21 +'\" RCS: @(#) $Id: RecEvalObj.3,v 1.1.2.1 1998/09/24 23:58:26 stanton Exp $ '\" .so man.macros .TH Tcl_RecordAndEvalObj 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/RecordEval.3 ================================================================== --- doc/RecordEval.3 +++ doc/RecordEval.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) RecordEval.3 1.18 97/07/29 18:25:13 +'\" RCS: @(#) $Id: RecordEval.3,v 1.1.2.1 1998/09/24 23:58:26 stanton Exp $ '\" .so man.macros .TH Tcl_RecordAndEval 3 7.4 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/RegExp.3 ================================================================== --- doc/RegExp.3 +++ doc/RegExp.3 @@ -1,23 +1,27 @@ '\" '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" Copyright (c) 1998-1999 Scriptics Corportation '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" SCCS: @(#) RegExp.3 1.9 96/08/26 12:59:48 +'\" RCS: @(#) $Id: RegExp.3,v 1.1.2.2 1999/04/05 22:20:26 rjohnson Exp $ '\" .so man.macros .TH Tcl_RegExpMatch 3 7.4 Tcl "Tcl Library Procedures" .BS .SH NAME -Tcl_RegExpMatch, Tcl_RegExpCompile, Tcl_RegExpExec, Tcl_RegExpRange \- Pattern matching with regular expressions +Tcl_GetRegExpFromObj, Tcl_RegExpMatch, Tcl_RegExpCompile, Tcl_RegExpExec, Tcl_RegExpRange \- Pattern matching with regular expressions .SH SYNOPSIS .nf \fB#include \fR .sp +Tcl_RegExp +\fBTcl_GetRegExpFromObj\fR(\fIinterp\fR, \fIpatObj\fR, \fIflags\fR) +.sp int \fBTcl_RegExpMatch\fR(\fIinterp\fR, \fIstring\fR, \fIpattern\fR) .sp Tcl_RegExp \fBTcl_RegExpCompile\fR(\fIinterp\fR, \fIpattern\fR) @@ -32,13 +36,17 @@ Tcl interpreter to use for error reporting. .AP char *string in String to check for a match with a regular expression. .AP char *pattern in String in the form of a regular expression pattern. +.AP Tcl_Obj *patObj in +Refers to the object from which to get a compiled regular expression. +.AP int flags in +Various flags to control regular expression compile options. .AP Tcl_RegExp regexp in Compiled regular expression. Must have been returned previously -by \fBTcl_RegExpCompile\fR. +by \fBTcl_GetRegExpFromObj\fR. .AP char *start in If \fIstring\fR is just a portion of some other string, this argument identifies the beginning of the larger string. If it isn't the same as \fIstring\fR, then no \fB^\fR matches will be allowed. @@ -53,10 +61,17 @@ The address of the character just after the last one in the range is stored here, or NULL if there is no such range. .BE .SH DESCRIPTION +.PP +\fBTcl_GetRegExpFromObj\fR attepts to return a compiled regular +expression from the Tcl obj \fIpatObj\fR. If the object does not +already contain a compiled regular expression it will attempt to +create one from the string in the Tcl obj and assign it to the +internal representation of the \fIpatObj\fR. The return value +of this function is of type \fBTcl_RegExp\fR. .PP \fBTcl_RegExpMatch\fR determines whether its \fIpattern\fR argument matches \fIregexp\fR, where \fIregexp\fR is interpreted as a regular expression using the same rules as for the \fBregexp\fR Tcl command. ADDED doc/SaveResult.3 Index: doc/SaveResult.3 ================================================================== --- /dev/null +++ doc/SaveResult.3 @@ -0,0 +1,65 @@ +'\" +'\" 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. +'\" +'\" RCS: @(#) $Id: SaveResult.3,v 1.1.2.2 1998/10/21 20:21:31 stanton Exp $ +'\" +.so man.macros +.TH Tcl_SaveResult 3 8.1 Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_SaveResult, Tcl_RestoreResult, Tcl_DiscardResult \- save and restore an interpreter's result +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fBTcl_SaveResult(\fIinterp, statePtr\fB)\fR +.sp +\fBTcl_RestoreResult(\fIinterp, statePtr\fB)\fR +.sp +\fBTcl_DiscardResult(\fIstatePtr\fB)\fR +.SH ARGUMENTS +.AS Tcl_SavedResult statePtr +.AP Tcl_Interp *interp in +Interpreter for which state should be saved. +.AP Tcl_SavedResult *statePtr 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 +interpreter result so that it can be restored after a call +to \fBTcl_Eval\fR or some other routine that modifies the interpreter +result. These routines are passed a pointer to a structure that is +used to store enough information to restore the interpreter result +state. 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 \fBerrorCode\fR or +\fBerrorInfo\fR variables). +.PP +\fBTcl_SaveResult\fR moves the string and object 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 object 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 Index: doc/SetErrno.3 ================================================================== --- doc/SetErrno.3 +++ doc/SetErrno.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) SetErrno.3 1.5 96/02/15 20:01:31 +'\" RCS: @(#) $Id: SetErrno.3,v 1.1.2.1 1998/09/24 23:58:26 stanton Exp $ .so man.macros .TH Tcl_SetErrno 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Tcl_SetErrno, Tcl_GetErrno \- manipulate errno to store and retrieve error codes Index: doc/SetRecLmt.3 ================================================================== --- doc/SetRecLmt.3 +++ doc/SetRecLmt.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) SetRecLmt.3 1.6 96/03/25 20:06:36 +'\" RCS: @(#) $Id: SetRecLmt.3,v 1.1.2.2 1999/04/13 00:01:59 surles Exp $ '\" .so man.macros .TH Tcl_SetRecursionLimit 3 7.0 Tcl "Tcl Library Procedures" .BS .SH NAME @@ -39,11 +39,11 @@ \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_SetRecursionDepth\fR with \fIdepth\fR equal to 0. +\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 Index: doc/SetResult.3 ================================================================== --- doc/SetResult.3 +++ doc/SetResult.3 @@ -3,17 +3,17 @@ '\" 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. '\" -'\" SCCS: @(#) SetResult.3 1.23 97/06/26 14:05:57 +'\" RCS: @(#) $Id: SetResult.3,v 1.1.2.2 1999/03/10 06:49:10 stanton Exp $ '\" .so man.macros .TH Tcl_SetResult 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME -Tcl_SetObjResult, Tcl_GetObjResult, Tcl_SetResult, Tcl_GetStringResult, Tcl_AppendResult, Tcl_AppendElement, Tcl_ResetResult \- manipulate Tcl result +Tcl_SetObjResult, Tcl_GetObjResult, Tcl_SetResult, Tcl_GetStringResult, Tcl_AppendResult, Tcl_AppendResultVA, Tcl_AppendElement, Tcl_ResetResult \- manipulate Tcl result .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_SetObjResult\fR(\fIinterp, objPtr\fR) @@ -25,10 +25,12 @@ .sp char * \fBTcl_GetStringResult\fR(\fIinterp\fR) .sp \fBTcl_AppendResult\fR(\fIinterp, string, string, ... , \fB(char *) NULL\fR) +.sp +\fBTcl_AppendResultVA\fR(\fIinterp, argList\fR) .sp \fBTcl_AppendElement\fR(\fIinterp, string\fR) .sp \fBTcl_ResetResult\fR(\fIinterp\fR) .sp @@ -44,10 +46,13 @@ appended to the existing result. .AP Tcl_FreeProc *freeProc in Address of procedure to call to release storage at \fIstring\fR, or \fBTCL_STATIC\fR, \fBTCL_DYNAMIC\fR, or \fBTCL_VOLATILE\fR. +.AP va_list argList in +An argument list which must have been initialised using +\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR. .BE .SH DESCRIPTION .PP The procedures described here are utilities for manipulating the @@ -135,10 +140,13 @@ It also converts the current interpreter result from an object to a string, if necessary, before appending the argument strings. Any number of \fIstring\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 \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 \fIstring\fR argument and it appends that argument to the current result as a proper Tcl list element. Index: doc/SetVar.3 ================================================================== --- doc/SetVar.3 +++ doc/SetVar.3 @@ -3,137 +3,207 @@ '\" 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. '\" -'\" SCCS: @(#) SetVar.3 1.30 97/10/10 16:10:36 +'\" RCS: @(#) $Id: SetVar.3,v 1.1.2.3 1999/02/10 23:31:11 stanton Exp $ '\" .so man.macros -.TH Tcl_SetVar 3 7.4 Tcl "Tcl Library Procedures" +.TH Tcl_SetVar 3 8.1 Tcl "Tcl Library Procedures" .BS .SH NAME -Tcl_SetVar, Tcl_SetVar2, Tcl_GetVar, Tcl_GetVar2, Tcl_UnsetVar, Tcl_UnsetVar2 \- manipulate Tcl variables +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 +.VS 8.1 +Tcl_Obj * +\fBTcl_SetVar2Ex\fR(\fIinterp, name1, name2, newValuePtr, flags\fR) +.VE .sp char * \fBTcl_SetVar\fR(\fIinterp, varName, newValue, flags\fR) .sp char * \fBTcl_SetVar2\fR(\fIinterp, name1, name2, newValue, flags\fR) +.sp +Tcl_Obj * +\fBTcl_ObjSetVar2\fR(\fIinterp, part1Ptr, part2Ptr, newValuePtr, flags\fR) +.sp +.VS 8.1 +Tcl_Obj * +\fBTcl_GetVar2Ex\fR(\fIinterp, name1, name2, flags\fR) +.VE .sp char * \fBTcl_GetVar\fR(\fIinterp, varName, flags\fR) .sp 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 *newValue +.AS Tcl_Interp *newValuePtr .AP Tcl_Interp *interp in Interpreter containing variable. +.AP 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 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 +.VS 8.1 +Points to a Tcl object containing the new value for the variable. +.VE +.AP int flags in +OR-ed combination of bits providing additional information. See below +for valid values. .AP char *varName in Name of variable. -May include a series of \fB::\fR namespace qualifiers +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 variable. -If the name references an element of an array, then it +an array. +If the name references an element of an array, then the name must be in writable memory: Tcl will make temporary modifications to it while looking up the name. .AP char *newValue in -New value for variable. -.AP int flags in -OR-ed combination of bits providing additional information for -operation. See below for valid values. -.AP char *name1 in -Name of scalar variable, or name of array variable if \fIname2\fR -is non-NULL. -May include a series of \fB::\fR namespace qualifiers +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 object containing the variable's name. +The name may include a series of \fB::\fR namespace qualifiers to specify a variable in a particular namespace. -.AP char *name2 in -If non-NULL, gives name of element within array and \fIname1\fR -must refer to an array variable. +May refer to a scalar variable or an element of an array variable. +.AP Tcl_Obj *part2Ptr in +If non-NULL, points to an object containing the name of an element +within an array and \fIpart1Ptr\fR must refer to an array variable. .BE .SH DESCRIPTION .PP -These procedures may be used to create, modify, read, and delete +These procedures are used to create, modify, read, and delete Tcl variables from C code. .PP -Note that \fBTcl_GetVar\fR and \fBTcl_SetVar\fR -have been largely replaced by the -object-based procedures \fBTcl_ObjGetVar2\fR and \fBTcl_ObjSetVar2\fR. -Those object-based procedures read, modify, and create -a variable whose name is held in a Tcl object instead of a string. -They also return a pointer to the object -which is the variable's value instead of returning a string. -Operations on objects can be faster since objects -hold an internal representation that can be manipulated more efficiently. -.PP -\fBTcl_SetVar\fR and \fBTcl_SetVar2\fR +.VS 8.1 +\fBTcl_SetVar2Ex\fR, \fBTcl_SetVar\fR, \fBTcl_SetVar2\fR, and +\fBTcl_ObjSetVar2\fR will create a new variable or modify an existing one. -Both of these procedures set the given variable to the value -given by \fInewValue\fR, and they return a pointer to a -copy of the variable's new value, which is stored in Tcl's +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. -Tcl keeps a private copy of the variable's value, so the caller -may change \fInewValue\fR after these procedures return without -affecting the value of the variable. +\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 +.VE +\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), -they return NULL. +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 +.VS 8.1 +\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. +.VE +If an error occurs while reading the variable (e.g. the variable +doesn't 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 TCL_OK is returned. +If the variable cannot be removed because it doesn't exist then +TCL_ERROR 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 the variable may be specified to -\fBTcl_SetVar\fR and \fBTcl_SetVar2\fR in either of two ways. -If \fBTcl_SetVar\fR is called, the variable name is given as +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 doesn't have parentheses as described above, then the entire string is treated as the name of a scalar variable. -If \fBTcl_SetVar2\fR is called, then the array name and index -have been separated by the caller into two separate strings, -\fIname1\fR and \fIname2\fR respectively; if \fIname2\fR is -zero it means that a scalar variable is being referenced. +.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. +.VS 8.1 +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). +.VE .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. -Note that the flag bit TCL_PARSE_PART1 is only meaningful -for the procedures Tcl_SetVar2 and Tcl_GetVar2. .TP \fBTCL_GLOBAL_ONLY\fR -Under normal circumstances the procedures look up variables as follows: +Under normal circumstances the procedures look up variables as follows. If a procedure call is active in \fIinterp\fR, -a variable is looked up at the current level of procedure call. -Otherwise, a variable is looked up first in the current namespace, +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 -Under normal circumstances the procedures look up variables as follows: -If a procedure call is active in \fIinterp\fR, -a variable is looked up at the current level of procedure call. -Otherwise, a 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 current namespace -even if there is a procedure call active. +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 @@ -140,33 +210,22 @@ or \fBTcl_GetStringResult\fR. If this flag bit isn't 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 \fInewValue\fR is appended to the current -value, instead of replacing it. -If the variable is currently undefined, then this bit is ignored. +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 ``{'', or ends in `` }''). -.TP -\fBTCL_PARSE_PART1\fR -If this bit is set when calling \fITcl_SetVar2\fR and \fITcl_GetVar2\fR, -\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 the flag TCL_PARSE_PART1 is given, -\fIname2\fR should be NULL since the array and element names -are taken from \fIname1\fR. .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. @@ -176,12 +235,10 @@ or \fBTcl_SetVar2\fR). \fBTcl_GetVar\fR and \fBTcl_GetVar2\fR use the flag bits TCL_GLOBAL_ONLY and TCL_LEAVE_ERR_MSG, both of which have the same meaning as for \fBTcl_SetVar\fR. -In addition, \fBTcl_GetVar2\fR uses the bit TCL_PARSE_PART1, -which has the same meaning as for \fBTcl_SetVar2\fR. If an error occurs in reading the variable (e.g. the variable doesn't 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 @@ -196,9 +253,9 @@ 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_ObjGetVar2, Tcl_ObjSetVar2, Tcl_TraceVar +Tcl_GetObjResult, Tcl_GetStringResult, Tcl_TraceVar .SH KEYWORDS -array, interpreter, object, scalar, set, unset, variable +array, get variable, interpreter, object, scalar, set, unset, variable Index: doc/Sleep.3 ================================================================== --- doc/Sleep.3 +++ doc/Sleep.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) Sleep.3 1.3 96/03/25 20:07:21 +'\" RCS: @(#) $Id: Sleep.3,v 1.1.2.1 1998/09/24 23:58:26 stanton Exp $ '\" .so man.macros .TH Tcl_Sleep 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/SplitList.3 ================================================================== --- doc/SplitList.3 +++ doc/SplitList.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) SplitList.3 1.21 97/04/29 14:07:10 +'\" RCS: @(#) $Id: SplitList.3,v 1.1.2.1 1998/09/24 23:58:27 stanton Exp $ '\" .so man.macros .TH Tcl_SplitList 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/SplitPath.3 ================================================================== --- doc/SplitPath.3 +++ doc/SplitPath.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) SplitPath.3 1.4 96/08/19 14:59:35 +'\" RCS: @(#) $Id: SplitPath.3,v 1.1.2.1 1998/09/24 23:58:27 stanton Exp $ '\" .so man.macros .TH Tcl_SplitPath 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/StaticPkg.3 ================================================================== --- doc/StaticPkg.3 +++ doc/StaticPkg.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) StaticPkg.3 1.4 96/09/04 11:21:26 +'\" RCS: @(#) $Id: StaticPkg.3,v 1.1.2.1 1998/09/24 23:58:27 stanton Exp $ '\" .so man.macros .TH Tcl_StaticPackage 3 7.5 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/StrMatch.3 ================================================================== --- doc/StrMatch.3 +++ doc/StrMatch.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) StrMatch.3 1.11 96/03/25 20:08:06 +'\" RCS: @(#) $Id: StrMatch.3,v 1.1.2.1 1998/09/24 23:58:27 stanton Exp $ '\" .so man.macros .TH Tcl_StringMatch 3 "" Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/StringObj.3 ================================================================== --- doc/StringObj.3 +++ doc/StringObj.3 @@ -2,17 +2,17 @@ '\" 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. '\" -'\" SCCS: @(#) @(#) StringObj.3 1.13 97/06/25 13:40:25 +'\" RCS: @(#) $Id: StringObj.3,v 1.1.2.3 1999/03/10 06:49:10 stanton Exp $ '\" .so man.macros -.TH Tcl_StringObj 3 8.0 Tcl "Tcl Library Procedures" +.TH Tcl_StringObj 3 8.1 Tcl "Tcl Library Procedures" .BS .SH NAME -Tcl_NewStringObj, Tcl_SetStringObj, Tcl_GetStringFromObj, Tcl_AppendToObj, Tcl_AppendStringsToObj, Tcl_SetObjLength, TclConcatObj \- manipulate Tcl objects as strings +Tcl_NewStringObj, Tcl_SetStringObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_AppendToObj, Tcl_AppendStringsToObj, Tcl_AppendStringsToObjVA, Tcl_AppendObjToObj, Tcl_SetObjLength, Tcl_ConcatObj \- manipulate Tcl objects as strings .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * @@ -21,20 +21,29 @@ \fBTcl_SetStringObj\fR(\fIobjPtr, bytes, length\fR) .sp char * \fBTcl_GetStringFromObj\fR(\fIobjPtr, lengthPtr\fR) .sp +char * +\fBTcl_GetString\fR(\fIobjPtr\fR) +.sp \fBTcl_AppendToObj\fR(\fIobjPtr, bytes, length\fR) +.VS +.sp +\fBTcl_AppendObjToObj\fR(\fIobjPtr, appendObjPtr\fR) +.VE .sp \fBTcl_AppendStringsToObj\fR(\fIobjPtr, string, string, ... \fB(char *) NULL\fR) +.sp +\fBTcl_AppendStringsToObjVA\fR(\fIobjPtr, argList\fR) .sp \fBTcl_SetObjLength\fR(\fIobjPtr, newLength\fR) .sp Tcl_Obj * \fBTcl_ConcatObj\fR(\fIobjc, objv\fR) .SH ARGUMENTS -.AS Tcl_Interp *lengthPtr out +.AS Tcl_Interp *appendObjPtr in/out .AP char *bytes in Points to the first byte of an array of bytes used to set or append to a string object. This byte array may contain embedded null bytes unless \fIlength\fR is negative. @@ -42,15 +51,22 @@ The number of bytes to copy from \fIbytes\fR when initializing, setting, or appending to a string object. If negative, all bytes up to the first null are used. .AP Tcl_Obj *objPtr in/out Points to an object to manipulate. +.VS +.AP Tcl_Obj *appendObjPtr in +The object to append to \fIobjPtr\fR in \fBTcl_AppendObjToObj\fR. +.VE .AP int *lengthPtr out If non-NULL, the location where \fBTcl_GetStringFromObj\fR will store the the length of an object's string representation. .AP char *string in Null-terminated string value to append to \fIobjPtr\fR. +.AP va_list argList in +An argument list which must have been initialised using +\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR. .AP int newLength in New length for the string value of \fIobjPtr\fR, not including the final NULL character. .AP int objc in The number of elements to concatenate. @@ -74,32 +90,45 @@ with reference count zero. Both procedures set the object to hold a copy of the specified string. \fBTcl_SetStringObj\fR frees any old string representation as well as any old internal representation of the object. .PP -\fBTcl_GetStringFromObj\fR returns an object's string representation. +\fBTcl_GetStringFromObj\fR and \fBTcl_GetString\fR +return an object's string representation. This is given by the returned byte pointer -and length, which is stored in \fIlengthPtr\fR if it is non-NULL. +and (for \fBTcl_GetStringFromObj\fR) length, +which is stored in \fIlengthPtr\fR if it is non-NULL. If the object's string representation is invalid (its byte pointer is NULL), the string representation is regenerated from the object's internal representation. The storage referenced by the returned byte pointer is owned by the object manager and should not be modified by the caller. +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_AppendToObj\fR appends the data given by \fIbytes\fR and \fIlength\fR to the object specified by \fIobjPtr\fR. It does this in a way that handles repeated calls relatively efficiently (it overallocates the string space to avoid repeated reallocations and copies of object's string value). +.VS +.PP +\fBTcl_AppendObjToObj\fR is similar to \fBTcl_AppendToObj\fR, but it +appends the string value of \fIappendObjPtr\fR to \fIobjPtr\fR. +.VE .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 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 object's string, then the string space is reallocated and the old value Index: doc/Tcl.n ================================================================== --- doc/Tcl.n +++ doc/Tcl.n @@ -3,14 +3,14 @@ '\" 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. '\" -'\" SCCS: @(#) Tcl.n 1.128 96/08/26 12:59:50 -' +'\" RCS: @(#) $Id: Tcl.n,v 1.1.2.2 1998/09/24 23:58:27 stanton Exp $ +'\" .so man.macros -.TH Tcl n "" Tcl "Tcl Built-In Commands" +.TH Tcl n "8.1" Tcl "Tcl Built-In Commands" .BS .SH NAME Tcl \- Summary of Tcl language syntax. .BE @@ -109,51 +109,65 @@ 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 6 +.TP 7 \e\fBa\fR Audible alert (bell) (0x7). -.TP 6 +.TP 7 \e\fBb\fR Backspace (0x8). -.TP 6 +.TP 7 \e\fBf\fR Form feed (0xc). -.TP 6 +.TP 7 \e\fBn\fR Newline (0xa). -.TP 6 +.TP 7 \e\fBr\fR Carriage-return (0xd). -.TP 6 +.TP 7 \e\fBt\fR Tab (0x9). -.TP 6 +.TP 7 \e\fBv\fR Vertical tab (0xb). -.TP 6 +.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 isn't in braces or quotes. -.TP 6 +. +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 isn't +in braces or quotes. +.TP 7 \e\e Backslash (``\e''). -.TP 6 -\e\fIooo\fR -The digits \fIooo\fR (one, two, or three of them) give the octal value of -the character. -.TP 6 -\e\fBx\fIhh\fR -The hexadecimal digits \fIhh\fR give the hexadecimal value of -the character. Any number of digits may be present. +.VS 8.1 br +.TP 7 +\e\fIooo\fR +. +The digits \fIooo\fR (one, two, or three of them) give an eight-bit octal +value for the Unicode character that will be inserted. The upper bits of the +Unicode character will be 0. +.TP 7 +\e\fBx\fIhh\fR +. +The hexadecimal digits \fIhh\fR give an eight-bit hexadecimal value for the +Unicode character that will be inserted. Any number of hexadecimal digits +may be present; however, all but the last two are ignored (the result is +always a one-byte quantity). The upper bits of the Unicode character will +be 0. +.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. +.VE .LP Backslash substitution is not performed on words enclosed in braces, except for backslash-newline as described above. .RE .IP [9] Index: doc/Tcl_Main.3 ================================================================== --- doc/Tcl_Main.3 +++ doc/Tcl_Main.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) Tcl_Main.3 1.8 96/03/25 20:08:33 +'\" RCS: @(#) $Id: Tcl_Main.3,v 1.1.2.1 1998/09/24 23:58:27 stanton Exp $ '\" .so man.macros .TH Tcl_Main 3 7.4 Tcl "Tcl Library Procedures" .BS .SH NAME ADDED doc/Thread.3 Index: doc/Thread.3 ================================================================== --- /dev/null +++ doc/Thread.3 @@ -0,0 +1,100 @@ +'\" +'\" 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. +'\" +'\" RCS: @(#) $Id: Thread.3,v 1.1.2.3 1999/03/25 19:43:34 stanton Exp $ +'\" +.so man.macros +.TH Tcl_ConditionNotify 3 "8.1" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_ConditionNotify, Tcl_ConditionWait, Tcl_GetThreadData, Tcl_MutexLock, Tcl_MutexUnlock \- thread synchronization 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_GetThreadData\fR(\fIkeyPtr, size\fR) +.sp +void +\fBTcl_MutexLock\fR(\fImutexPtr\fR) +.sp +void +\fBTcl_MutexUnlock\fR(\fImutexPtr\fR) +.SH ARGUMENTS +.AS Tcl_ThreadDataKey *keyPtr +.AP Tcl_Condition *condPtr in +A condition variable, which must be associated with a mutex lock. +.AP Tcl_Condition *mutexPtr in +A mutex lock. +.AP Tcl_Time *timePtr in +A time limit on the condition wait. NULL to wait forever. +Note that a polling value of 0 seconds doesn't 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. +.BE + +.SH DESCRIPTION +.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. +.VS +The result of locking a mutex twice from the same thread is undefined. +On some platforms it will result in a deadlock. +.VE +\fBTcl_MutexLock\fR and \fBTcl_MutexUnlock\fR +procedures are defined as empty macros if not compiling with 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 +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 +.SH INITIALIZATION +.PP +.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 +cleaned up by process exit handlers. Thread local storage is +reclaimed during \fBTcl_FinalizeThread\fR. +.SH CREATING THREADS +The API to create threads is not finalized at this time. +There are private facilities to create threads that contain a new +Tcl interpreter, and to send scripts among threads. +Dive into tclThreadTest.c and tclThread.c for examples. +.SH KEYWORDS +thread, mutex, condition variable, thread local storage ADDED doc/ToUpper.3 Index: doc/ToUpper.3 ================================================================== --- /dev/null +++ doc/ToUpper.3 @@ -0,0 +1,90 @@ +'\" +'\" 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. +'\" +'\" RCS: @(#) $Id: ToUpper.3,v 1.1.2.2 1998/10/21 20:21:31 stanton Exp $ +'\" +.so man.macros +.TH Tcl_UtfToUpper 3 "8.1" Tcl "Tcl Library Procedures" +.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 Index: doc/TraceVar.3 ================================================================== --- doc/TraceVar.3 +++ doc/TraceVar.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) TraceVar.3 1.27 97/10/10 15:05:37 +'\" RCS: @(#) $Id: TraceVar.3,v 1.1.2.2 1998/09/24 23:58:27 stanton Exp $ '\" .so man.macros .TH Tcl_TraceVar 3 7.4 Tcl "Tcl Library Procedures" .BS .SH NAME @@ -42,11 +42,11 @@ If the name references an element of an array, then it must be in writable memory: Tcl will make temporary modifications to it while looking up the name. .AP int flags in OR-ed combination of the values TCL_TRACE_READS, TCL_TRACE_WRITES, and -TCL_TRACE_UNSETS, TCL_PARSE_PART1, and TCL_GLOBAL_ONLY. +TCL_TRACE_UNSETS, TCL_TRACE_ARRAY, and TCL_GLOBAL_ONLY. 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 @@ -94,10 +94,16 @@ 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. .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: @@ -118,11 +124,12 @@ \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 TCL_TRACE_READS, TCL_TRACE_WRITES, or TCL_TRACE_UNSETS +One of the bits TCL_TRACE_READS, TCL_TRACE_WRITES, TCL_TRACE_ARRAY, +or TCL_TRACE_UNSETS will be set in \fIflags\fR to indicate which operation is being performed on the variable. The bit TCL_GLOBAL_ONLY 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 @@ -173,28 +180,30 @@ \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. -If \fIname2\fR is NULL 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). -As a special case, if the flag TCL_PARSE_PART1 is specified, +.VS 8.1 +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 the flag TCL_PARSE_PART1 is given, -\fIname2\fR should be NULL since the array and element names -are taken from \fIname1\fR. +If \fIname2\fR is NULL and \fIname1\fR does not refer +to an array element +.VE +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 and write traces, the +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 @@ -242,10 +251,16 @@ 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. @@ -341,8 +356,11 @@ .SH BUGS .PP Tcl doesn't do any error checking to prevent trace procedures from misusing the interpreter during traces with TCL_INTERP_DESTROYED set. +.PP +Array traces are not yet integrated with the Tcl "info exists" command, +nor is there Tcl-level access to array traces. .SH KEYWORDS clientData, trace, variable Index: doc/Translate.3 ================================================================== --- doc/Translate.3 +++ doc/Translate.3 @@ -1,16 +1,16 @@ '\" '\" Copyright (c) 1989-1993 The Regents of the University of California. -'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" 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. '\" -'\" SCCS: @(#) Translate.3 1.22 96/08/26 12:59:51 +'\" RCS: @(#) $Id: Translate.3,v 1.1.2.2 1998/09/24 23:58:28 stanton Exp $ '\" .so man.macros -.TH Tcl_TranslateFileName 3 7.5 Tcl "Tcl Library Procedures" +.TH Tcl_TranslateFileName 3 8.1 Tcl "Tcl Library Procedures" .BS .SH NAME Tcl_TranslateFileName \- convert file name to native form and replace tilde with home directory .SH SYNOPSIS .nf @@ -24,11 +24,11 @@ Interpreter in which to report an error, if any. .AP char *name in File name, which may start with a ``~''. .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 empty. The +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 Index: doc/UpVar.3 ================================================================== --- doc/UpVar.3 +++ doc/UpVar.3 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) UpVar.3 1.6 96/03/25 20:09:19 +'\" RCS: @(#) $Id: UpVar.3,v 1.1.2.1 1998/09/24 23:58:28 stanton Exp $ '\" .so man.macros .TH Tcl_UpVar 3 7.4 Tcl "Tcl Library Procedures" .BS .SH NAME ADDED doc/Utf.3 Index: doc/Utf.3 ================================================================== --- /dev/null +++ doc/Utf.3 @@ -0,0 +1,160 @@ +'\" +'\" 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. +'\" +'\" RCS: @(#) $Id: Utf.3,v 1.1.2.2 1998/10/21 20:21:32 stanton Exp $ +'\" +.so man.macros +.TH Utf 3 "8.1" Tcl "Tcl Library Procedures" +.BS +.SH NAME +Tcl_UniChar, Tcl_UniCharToUtf, Tcl_UtfToUniChar, 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 ... Tcl_UniChar; +.sp +int +\fBTcl_UniCharToUtf\fR(\fIch, buf\fR) +.sp +int +\fBTcl_UtfToUniChar\fR(\fIsrc, chPtr\fR) +.sp +int +\fBTcl_UtfCharComplete\fR(\fIsrc, len\fR) +.sp +int +\fBTcl_NumUtfChars\fR(\fIsrc, len\fR) +.sp +char * +\fBTcl_UtfFindFirst\fR(\fIsrc, ch\fR) +.sp +char * +\fBTcl_UtfFindLast\fR(\fIsrc, ch\fR) +.sp +char * +\fBTcl_UtfNext\fR(\fIsrc\fR) +.sp +char * +\fBTcl_UtfPrev\fR(\fIsrc, start\fR) +.sp +Tcl_UniChar +\fBTcl_UniCharAtIndex\fR(\fIsrc, index\fR) +.sp +char * +\fBTcl_UtfAtIndex\fR(\fIsrc, index\fR) +.sp +int +\fBTcl_UtfBackslash\fR(\fIsrc, readPtr, dst\fR) +.SH ARGUMENTS +.AS "CONST char" *chPtr out +.AP char *buf out +Buffer in which the UTF-8 representation of the Tcl_UniChar is stored. At most +TCL_UTF_MAX 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 int len 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 "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 TCL_UTF_MAX bytes are stored in the buffer. +.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 TCL_UTF_MAX 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_UtfCharComplete\fR returns 1 if the source UTF-8 string \fIsrc\fR +of length \fIlen\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 \fIlen\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 occurance 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 occurance 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. +.PP +Given \fIsrc\fR, a pointer to some location in a UTF-8 string, +\fBTcl_UtfPrev\fR returns a pointer to the previous UTF-8 character in the +string. 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. +.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. +.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 TCL_UTF_MAX 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 Index: doc/WrongNumArgs.3 ================================================================== --- doc/WrongNumArgs.3 +++ doc/WrongNumArgs.3 @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) @(#) WrongNumArgs.3 1.5 97/07/30 16:20:07 +'\" RCS: @(#) $Id: WrongNumArgs.3,v 1.1.2.1 1998/09/24 23:58:28 stanton Exp $ '\" .so man.macros .TH Tcl_WrongNumArgs 3 8.0 Tcl "Tcl Library Procedures" .BS .SH NAME Index: doc/after.n ================================================================== --- doc/after.n +++ doc/after.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) after.n 1.4 96/03/25 20:09:33 +'\" RCS: @(#) $Id: after.n,v 1.1.2.1 1998/09/24 23:58:28 stanton Exp $ '\" .so man.macros .TH after n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/append.n ================================================================== --- doc/append.n +++ doc/append.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) append.n 1.6 96/03/25 20:09:44 +'\" RCS: @(#) $Id: append.n,v 1.1.2.1 1998/09/24 23:58:28 stanton Exp $ '\" .so man.macros .TH append n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/array.n ================================================================== --- doc/array.n +++ doc/array.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) array.n 1.9 97/10/29 14:10:13 +'\" RCS: @(#) $Id: array.n,v 1.1.2.1 1998/09/24 23:58:28 stanton Exp $ '\" .so man.macros .TH array n 7.4 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/bgerror.n ================================================================== --- doc/bgerror.n +++ doc/bgerror.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) bgerror.n 1.5 97/08/04 17:49:35 +'\" RCS: @(#) $Id: bgerror.n,v 1.1.2.1 1998/09/24 23:58:28 stanton Exp $ '\" .so man.macros .TH bgerror n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/binary.n ================================================================== --- doc/binary.n +++ doc/binary.n @@ -2,11 +2,11 @@ '\" Copyright (c) 1997 by Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" SCCS: @(#) binary.n 1.7 97/11/11 19:08:47 +'\" RCS: @(#) $Id: binary.n,v 1.1.2.3 1999/04/09 19:11:26 surles Exp $ '\" .so man.macros .TH binary n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -117,20 +117,20 @@ remaining bits of the last byte will be zeros. For example, .RS .CS \fBbinary format h3h* AB def\fR .CE -will return a string equivalent to \fB\\xba\\xed\\x0f\fR. +will return a string equivalent to \fB\\xba\\x00\\xed\\x0f\fR. .RE .IP \fBH\fR 5 This form is the same as \fBh\fR except that the digits are stored in high-to-low order within each byte. For example, .RS .CS \fBbinary format H3H* ab DEF\fR .CE -will return a string equivalent to \fB\\xab\\xde\\xf0\fR. +will return a string equivalent to \fB\\xab\\x00\\xde\\xf0\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; otherwise \fIarg\fR must consist of a list containing at least @@ -140,14 +140,14 @@ the number of elements in the list is fewer than \fIcount\fR, then an error is generated. 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 c3cc* {3 -3 128 1} 257 {2 5}\fR +\fBbinary format c3cc* {3 -3 128 1} 260 {2 5}\fR .CE will return a string equivalent to -\fB\\x03\\xfd\\x80\\x01\\x02\\x05\fR, whereas +\fB\\x03\\xfd\\x80\\x04\\x02\\x05\fR, whereas .CS \fBbinary format c {2 5}\fR .CE will generate an error. .RE @@ -184,11 +184,11 @@ .RS .CS \fBbinary format i3 {3 -3 65536 1}\fR .CE will return a string equivalent to -\fB\\x03\\x00\\x00\\x00\\xfd\\xff\\xff\\xff\\x00\\x00\\x10\\x00\fR. +\fB\\x03\\x00\\x00\\x00\\xfd\\xff\\xff\\xff\\x00\\x00\\x01\\x00\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, @@ -195,11 +195,11 @@ .RS .CS \fBbinary format I3 {3 -3 65536 1}\fR .CE will return a string equivalent to -\fB\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xfd\\x00\\x10\\x00\\x00\fR. +\fB\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xfd\\x00\\x01\\x00\\x00\fR .RE .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 in the machine's native representation in the output string. This representation is not @@ -316,11 +316,11 @@ .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 "abc efghi \\000" a* var1\fR +\fBbinary scan "abc efghi \\000" A* var1\fR .CE will return \fB1\fR with \fBabc efghi\fR stored in \fBvar1\fR. .RE .IP \fBb\fR 5 The data is turned into a string of \fIcount\fR binary digits in @@ -336,15 +336,15 @@ .CE will return \fB2\fR with \fB11100\fR stored in \fBvar1\fR and \fB1110000110100000\fR stored in \fBvar2\fR. .RE .IP \fBB\fR 5 -This form is the same as \fBB\fR, except the bits are taken in +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 \\x70\\x87\\x05 b5b* var1 var2\fR +\fBbinary scan \\x70\\x87\\x05 B5B* var1 var2\fR .CE will return \fB2\fR with \fB01110\fR stored in \fBvar1\fR and \fB1000011100000101\fR stored in \fBvar2\fR. .RE .IP \fBh\fR 5 @@ -363,11 +363,11 @@ will return \fB2\fR with \fB706\fR stored in \fBvar1\fR and \fB50\fR stored in \fBvar2\fR. .RE .IP \fBH\fR 5 This form is the same as \fBh\fR, except the digits are taken in -low-to-high order within each byte. For example, +high-to-low order within each byte. For example, .RS .CS \fBbinary scan \\x07\\x86\\x05 H3H* var1 var2\fR .CE will return \fB2\fR with \fB078\fR stored in \fBvar1\fR and Index: doc/break.n ================================================================== --- doc/break.n +++ doc/break.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) break.n 1.7 96/10/09 08:29:26 +'\" RCS: @(#) $Id: break.n,v 1.1.2.1 1998/09/24 23:58:28 stanton Exp $ '\" .so man.macros .TH break n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/case.n ================================================================== --- doc/case.n +++ doc/case.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) case.n 1.8 96/03/25 20:10:49 +'\" RCS: @(#) $Id: case.n,v 1.1.2.1 1998/09/24 23:58:29 stanton Exp $ '\" .so man.macros .TH case n 7.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/catch.n ================================================================== --- doc/catch.n +++ doc/catch.n @@ -3,14 +3,14 @@ '\" 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. '\" -'\" SCCS: @(#) catch.n 1.6 96/03/25 20:11:08 +'\" RCS: @(#) $Id: catch.n,v 1.1.2.3 1999/04/13 00:01:59 surles Exp $ '\" .so man.macros -.TH catch n "" Tcl "Tcl Built-In Commands" +.TH catch n "8.0" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME catch \- Evaluate script and trap exceptional returns .SH SYNOPSIS @@ -17,24 +17,54 @@ \fBcatch\fI script \fR?\fIvarName\fR? .BE .SH DESCRIPTION .PP -The \fBcatch\fR command may be used to prevent errors from aborting -command interpretation. \fBCatch\fR calls the Tcl interpreter recursively -to execute \fIscript\fR, and always returns a TCL_OK code, regardless of -any errors that might occur while executing \fIscript\fR. The return -value from \fBcatch\fR is a decimal string giving the -code returned by the Tcl interpreter after executing \fIscript\fR. -This will be \fB0\fR (TCL_OK) if there were no errors in \fIscript\fR; -otherwise -it will have a non-zero value corresponding to one of the exceptional -return codes (see tcl.h for the definitions of code values). If the -\fIvarName\fR argument is given, then it gives the name of a variable; -\fBcatch\fR will set the variable to the string returned -from \fIscript\fR (either a result or an error message). +The \fBcatch\fR command may be used to prevent errors from aborting command +interpretation. \fBCatch\fR 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 one of the exceptional return codes (see tcl.h +for the definitions of code values). If the \fIvarName\fR argument is +given, then the variable it names is set to the error message from +interpreting \fIscript\fR. +.PP +If \fIscript\fR does not raise an error, \fBcatch\fR will return 0 +(TCL_OK) and set the variable to the value returned from \fIscript\fR. .PP Note that \fBcatch\fR catches all exceptions, including those -generated by \fBbreak\fR and \fBcontinue\fR as well as errors. +generated by \fBbreak\fR and \fBcontinue\fR as well as errors. The +only errors that are not caught are syntax errors found when the +script is compiled. This is because the catch command only catches +errors during runtime. When the catch statement is compiled, the +script is compiled as well and any syntax errors will generate a Tcl +error. + +.SH EXAMPLES + +The \fBcatch\fR command may be used in an \fBif\fR to branch based on +the success of a script. + +.DS +.CS +if { [catch {open $someFile w} fid] } { + puts stderr "Could not open $someFile for writing\\n$fid" + exit 1 +} +.CE +.DE +The \fBcatch\fR command will not catch compiled syntax errors. The +first time proc \fBfoo\fR is called, the body will be compiled and a +Tcl error will be generated. + +.DS +.CS +proc foo {} { + catch {expr {1 +- }} +} +.CE +.DE .SH KEYWORDS catch, error Index: doc/cd.n ================================================================== --- doc/cd.n +++ doc/cd.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) cd.n 1.6 96/03/28 08:40:52 +'\" RCS: @(#) $Id: cd.n,v 1.1.2.1 1998/09/24 23:58:29 stanton Exp $ '\" .so man.macros .TH cd n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/clock.n ================================================================== --- doc/clock.n +++ doc/clock.n @@ -6,11 +6,11 @@ '\" TclX, by Mark Diekhans and Karl Lehenbauer. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" SCCS: @(#) clock.n 1.18 97/09/10 13:31:23 +'\" RCS: @(#) $Id: clock.n,v 1.1.2.1 1998/09/24 23:58:29 stanton Exp $ '\" .so man.macros .TH clock n 7.4 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/close.n ================================================================== --- doc/close.n +++ doc/close.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) close.n 1.11 97/08/22 18:50:48 +'\" RCS: @(#) $Id: close.n,v 1.1.2.1 1998/09/24 23:58:29 stanton Exp $ '\" .so man.macros .TH close n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/concat.n ================================================================== --- doc/concat.n +++ doc/concat.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) concat.n 1.8 96/08/26 12:59:54 +'\" RCS: @(#) $Id: concat.n,v 1.1.2.1 1998/09/24 23:58:29 stanton Exp $ '\" .so man.macros .TH concat n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/continue.n ================================================================== --- doc/continue.n +++ doc/continue.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) continue.n 1.7 96/10/09 08:29:27 +'\" RCS: @(#) $Id: continue.n,v 1.1.2.1 1998/09/24 23:58:29 stanton Exp $ '\" .so man.macros .TH continue n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! ADDED doc/dde.n Index: doc/dde.n ================================================================== --- /dev/null +++ doc/dde.n @@ -0,0 +1,124 @@ +'\" +'\" 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. +'\" +'\" RCS: @(#) $Id: dde.n,v 1.1.2.1 1999/04/02 23:48:32 redman Exp $ +'\" +.so man.macros +.TH dde n 8.1 Tcl "Tcl Built-In Commands" +.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.0\fR +.sp +\fBdde \fIservername \fR?\fItopic\fR? +.sp +\fBdde ?\-async?\fR \fIcommand service topic \fR?\fIdata\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 +The only option to the \fBdde\fR command is: +.TP +\fB\-async\fR +Requests asynchronous invocation. This is valid only for the +\fBexecute\fR subcommand. Normally, the \fBdde execute\fR subcommand +waits until the command completes, returning appropriate error +messages. When the \fB\-async\fR option is used, the command returns +immediately, and no error information is available. +.SH "DDE COMMANDS" +.PP +The following commands are a subset of the full Dynamic Data Exchange +set of commands. +.TP +\fBdde servername \fR?\fItopic\fR? +\fBdde servername\fR registers the interpreter as a DDE server with +the service name TclEval and the topic name specified byt \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. +.TP +\fBdde execute \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 command returns an error if the script did not +run. If the \fB\-async\fR flag was used, the command +returns immediately with no error. +.TP +\fBdde request \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. +.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 null strings ({}), then all service-topic pairs currently +available on the system are returned. If \fIservice\fR is null and +\fItopic\fR is not, then all services with the specified topic are +returned. If \fIservice\fR is not null and \fItopic\fR is, all topics +for a given service are returned. If both are not null, if that +service-topic pair currently exists, it is returned; otherwise, null +is returned. +.TP +\fBdde eval \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 +"TclEval" service. This command can be used to replace send on Windows. +.SH "DDE AND TCL" +A Tcl interpreter always has a service name of "TclEval". Each +different interp of all running Tcl applications should 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 "$TCLEVAL$EXECUTE$RESULT" +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 the 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 KEYWORDS +application, dde, name, remote execution +.SH "SEE ALSO" +tk, winfo, send + ADDED doc/encoding.n Index: doc/encoding.n ================================================================== --- /dev/null +++ doc/encoding.n @@ -0,0 +1,79 @@ +'\" +'\" 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. +'\" +'\" RCS: @(#) $Id: encoding.n,v 1.1.2.1 1998/10/21 20:39:58 stanton Exp $ +'\" +.so man.macros +.TH encoding n "8.1" Tcl "Tcl Built-In Commands" +.BS +.SH NAME +encoding \- Manipulate encodings +.SH SYNOPSIS +\fBencoding \fIoption\fR ?\fIarg arg ...\fR? +.BE + +.SH INTRODUCTION +.PP +Strings in Tcl are encoded using 16-bit Unicode characters. 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 ?\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 ?\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. If \fIencoding\fR is not specified, the current +system encoding is used. +.TP +\fBencoding names\fR +Returns a list containing the names of all of the encodings that are +currently available. +.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 +ISO8859-1 encoding, Tcl will treat each byte in the file 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, +.CS + set s [encoding convertfrom euc-jp "\\xA4\\xCF"] +.CE +would return the Unicode string "\\u306F", which is the Hiragana +letter HA. + +.SH "SEE ALSO" +Tcl_GetEncoding + +.SH KEYWORDS +encoding Index: doc/eof.n ================================================================== --- doc/eof.n +++ doc/eof.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) eof.n 1.8 96/02/15 20:01:59 +'\" RCS: @(#) $Id: eof.n,v 1.1.2.1 1998/09/24 23:58:29 stanton Exp $ '\" .so man.macros .TH eof n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/error.n ================================================================== --- doc/error.n +++ doc/error.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) error.n 1.7 96/03/25 20:12:35 +'\" RCS: @(#) $Id: error.n,v 1.1.2.1 1998/09/24 23:58:29 stanton Exp $ '\" .so man.macros .TH error n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/eval.n ================================================================== --- doc/eval.n +++ doc/eval.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) eval.n 1.5 96/03/25 20:12:53 +'\" RCS: @(#) $Id: eval.n,v 1.1.2.1 1998/09/24 23:58:30 stanton Exp $ '\" .so man.macros .TH eval n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/exec.n ================================================================== --- doc/exec.n +++ doc/exec.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) exec.n 1.17 96/09/18 15:21:17 +'\" RCS: @(#) $Id: exec.n,v 1.1.2.2 1998/09/24 23:58:30 stanton Exp $ '\" .so man.macros .TH exec n 7.6 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -200,14 +200,15 @@ instead of ``applbakery.default''). .sp 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 -directory \fB/system\fR on the machine \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. +\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. .TP \fBWindows NT\fR . 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 @@ -262,11 +263,11 @@ the caller must prepend ``\fBcommand.com /c\0\fR'' to the desired command. .sp Once a 16-bit DOS application has read standard input from a console and then quit, all subsequently run 16-bit DOS applications will see the standard input as already closed. 32-bit applications do not have this -problem and will run correctly even after a 16-bit DOS application thinks +problem and will run correctly, even after a 16-bit DOS application thinks that standard input is closed. There is no known workaround for this bug at this time. .sp Redirection between the \fBNUL:\fR device and a 16-bit application does not always work. When redirecting from \fBNUL:\fR, some applications may hang, @@ -280,12 +281,12 @@ a pipe to a 16-bit DOS application is collected into a temporary file; the other end of the pipe must be closed before the 16-bit DOS application begins executing. All standard output or error from a 16-bit DOS application to a pipe is collected into temporary files; the application must terminate before the temporary files are redirected to the next stage -of the pipeline. This is due to a workaround for a Windows 95 bug in the -implementation of pipes, and is how the Windows 95 command line interpreter +of the pipeline. This is due to a workaround for a Windows 95 bug in the +implementation of pipes, and is how the standard Windows 95 DOS shell handles pipes itself. .sp Certain applications, such as \fBcommand.com\fR, should not be executed interactively. Applications which directly access the console window, rather than reading from their standard input and writing to their standard Index: doc/exit.n ================================================================== --- doc/exit.n +++ doc/exit.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) exit.n 1.6 96/03/25 20:13:32 +'\" RCS: @(#) $Id: exit.n,v 1.1.2.1 1998/09/24 23:58:30 stanton Exp $ '\" .so man.macros .TH exit n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/expr.n ================================================================== --- doc/expr.n +++ doc/expr.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) expr.n 1.28 97/09/18 18:21:30 +'\" RCS: @(#) $Id: expr.n,v 1.1.2.1 1998/09/24 23:58:30 stanton Exp $ '\" .so man.macros .TH expr n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/fblocked.n ================================================================== --- doc/fblocked.n +++ doc/fblocked.n @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) fblocked.n 1.6 96/02/23 13:46:30 +'\" RCS: @(#) $Id: fblocked.n,v 1.1.2.1 1998/09/24 23:58:30 stanton Exp $ .so man.macros .TH fblocked n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Index: doc/fconfigure.n ================================================================== --- doc/fconfigure.n +++ doc/fconfigure.n @@ -2,14 +2,14 @@ '\" 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. '\" -'\" SCCS: @(#) fconfigure.n 1.23 96/04/16 08:20:07 +'\" RCS: @(#) $Id: fconfigure.n,v 1.1.2.2 1998/09/24 23:58:30 stanton Exp $ '\" .so man.macros -.TH fconfigure n 7.5 Tcl "Tcl Built-In Commands" +.TH fconfigure n 8.1 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fconfigure \- Set and get options on a channel .SH SYNOPSIS @@ -49,130 +49,152 @@ 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. +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. .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 ten and one million, allowing buffers of ten to one million bytes in size. +.VS 8.1 br +.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. +.PP +The default encoding for newly opened channels is the same platform- and +locale-dependent system encoding used for interfacing with the operating +system. +.RE +.VE .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. +. +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. .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\fP and \fBread\fP) -the Tcl I/O system automatically translates the external end-of-line -representation into newline characters. -Upon output (i.e., with \fBputs\fP), -the I/O system translates newlines to the external -end-of-line representation. -The default translation mode, \fBauto\fP, handles all the common -cases automatically, but the \fB\-translation\fR option provides -explicit control over the end of line translations. +\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\fP +and \fBread\fP) the Tcl I/O system automatically translates the external +end-of-line representation into newline characters. Upon output (i.e., +with \fBputs\fP), the I/O system translates newlines to the external +end-of-line representation. The default translation mode, \fBauto\fP, +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: +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\fP), -carriage return (\fBcr\fP), or carriage return followed by a newline (\fBcrlf\fP) -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, for the +. +As the input translation mode, \fBauto\fR treats any of newline +(\fBlf\fP), carriage return (\fBcr\fP), or carriage return followed by a +newline (\fBcrlf\fP) 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, for the Macintosh platform it chooses \fBcr\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. +Windows it chooses \fBcrlf\fR. The default setting for +\fB\-translation\fR is \fBauto\fR for both input and output. +.VS 8.1 br .TP -\fBbinary\fR +\fBbinary\fR +. No end-of-line translations are performed. This is nearly identical to \fBlf\fP mode, except that in addition \fBbinary\fP mode also sets the -end of file character to the empty string, which disables it. -See the description of -\fB\-eofchar\fP for more information. +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. +.VE .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\fP mode converts carriage returns -to newline characters. -As the output translation mode, \fBcr\fP mode -translates newline characters to carriage returns. -This mode is typically used on Macintosh platforms. +. +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\fP mode converts carriage returns to newline characters. As the +output translation mode, \fBcr\fP mode translates newline characters to +carriage returns. This mode is typically used on Macintosh platforms. .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\fP mode converts -carriage-return-linefeed sequences -to newline characters. -As the output translation mode, \fBcrlf\fP mode -translates newline characters to -carriage-return-linefeed sequences. -This mode is typically used on Windows platforms and for network -connections. +. +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\fP mode converts carriage-return-linefeed +sequences to newline characters. As the output translation mode, +\fBcrlf\fP 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. +. +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 "SEE ALSO" close(n), flush(n), gets(n), puts(n), read(n), socket(n) .SH KEYWORDS blocking, buffering, carriage return, end of line, flushing, linemode, -newline, nonblocking, platform, translation +newline, nonblocking, platform, translation, encoding, filter, byte array, +binary Index: doc/fcopy.n ================================================================== --- doc/fcopy.n +++ doc/fcopy.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) fcopy.n 1.4 97/06/19 11:10:07 +'\" RCS: @(#) $Id: fcopy.n,v 1.1.2.1 1998/09/24 23:58:30 stanton Exp $ '\" .so man.macros .TH fcopy n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/file.n ================================================================== --- doc/file.n +++ doc/file.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) file.n 1.23 97/04/30 11:37:10 +'\" RCS: @(#) $Id: file.n,v 1.1.2.1 1998/09/24 23:58:30 stanton Exp $ '\" .so man.macros .TH file n 7.6 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/fileevent.n ================================================================== --- doc/fileevent.n +++ doc/fileevent.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) fileevent.n 1.6 96/02/23 13:46:29 +'\" RCS: @(#) $Id: fileevent.n,v 1.1.2.1 1998/09/24 23:58:31 stanton Exp $ '\" .so man.macros .TH fileevent n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/filename.n ================================================================== --- doc/filename.n +++ doc/filename.n @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) filename.n 1.7 96/04/11 17:03:14 +'\" RCS: @(#) $Id: filename.n,v 1.1.2.1 1998/09/24 23:58:31 stanton Exp $ '\" .so man.macros .TH filename n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/flush.n ================================================================== --- doc/flush.n +++ doc/flush.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) flush.n 1.10 96/08/26 12:59:57 +'\" RCS: @(#) $Id: flush.n,v 1.1.2.1 1998/09/24 23:58:31 stanton Exp $ '\" .so man.macros .TH flush n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/for.n ================================================================== --- doc/for.n +++ doc/for.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) for.n 1.6 97/04/08 17:13:49 +'\" RCS: @(#) $Id: for.n,v 1.1.2.1 1998/09/24 23:58:31 stanton Exp $ '\" .so man.macros .TH for n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/foreach.n ================================================================== --- doc/foreach.n +++ doc/foreach.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) foreach.n 1.6 96/03/25 20:15:14 +'\" RCS: @(#) $Id: foreach.n,v 1.1.2.1 1998/09/24 23:58:31 stanton Exp $ '\" .so man.macros .TH foreach n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/format.n ================================================================== --- doc/format.n +++ doc/format.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) format.n 1.11 96/08/26 12:59:57 +'\" RCS: @(#) $Id: format.n,v 1.1.2.2 1999/02/10 23:31:11 stanton Exp $ '\" .so man.macros .TH format n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -152,13 +152,15 @@ Convert integer to unsigned octal string. .TP 10 \fBx\fR or \fBX\fR Convert integer to unsigned hexadecimal string, using digits ``0123456789abcdef'' for \fBx\fR and ``0123456789ABCDEF'' for \fBX\fR). +.VS .TP 10 \fBc\fR -Convert integer to the 8-bit character it represents. +Convert integer to the Unicode character it represents. +.VE .TP 10 \fBs\fR No conversion; just insert string. .TP 10 \fBf\fR Index: doc/gets.n ================================================================== --- doc/gets.n +++ doc/gets.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) gets.n 1.13 96/08/26 12:59:58 +'\" RCS: @(#) $Id: gets.n,v 1.1.2.1 1998/09/24 23:58:31 stanton Exp $ '\" .so man.macros .TH gets n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/glob.n ================================================================== --- doc/glob.n +++ doc/glob.n @@ -3,14 +3,14 @@ '\" 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. '\" -'\" SCCS: @(#) glob.n 1.11 96/08/26 12:59:59 +'\" RCS: @(#) $Id: glob.n,v 1.1.2.2 1998/09/24 23:58:31 stanton Exp $ '\" .so man.macros -.TH glob n 7.5 Tcl "Tcl Built-In Commands" +.TH glob n 8.1 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME glob \- Return names of files that match patterns .SH SYNOPSIS @@ -74,11 +74,20 @@ .SH PORTABILITY ISSUES .PP Unlike other Tcl commands that will accept both network and native style names (see the \fBfilename\fR manual entry for details on how native and network names are specified), the \fBglob\fR command only -accepts native names. Also, for Windows UNC names, the servername and -sharename components of the path may not contain ?, *, or [] -constructs. +accepts native names. +.VS 8.1 +.TP +\fBWindows\fR +. +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 ``\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. +.VE .SH KEYWORDS exist, file, glob, pattern Index: doc/global.n ================================================================== --- doc/global.n +++ doc/global.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) global.n 1.6 97/05/18 15:23:09 +'\" RCS: @(#) $Id: global.n,v 1.1.2.1 1998/09/24 23:58:32 stanton Exp $ '\" .so man.macros .TH global n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/history.n ================================================================== --- doc/history.n +++ doc/history.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) history.n 1.11 97/08/07 16:44:49 +'\" RCS: @(#) $Id: history.n,v 1.1.2.1 1998/09/24 23:58:32 stanton Exp $ '\" .so man.macros .TH history n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/http.n ================================================================== --- doc/http.n +++ doc/http.n @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) http.n 1.11 97/08/07 16:45:02 +'\" RCS: @(#) $Id: http.n,v 1.1.2.2 1998/12/10 21:21:28 stanton Exp $ '\" .so man.macros .TH "Http" n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -248,11 +248,13 @@ 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: .CS upvar #0 $token state .CE -The following elements of the array are supported: +Once the data associated with the url is no longer needed, the state +array should be unset to free up storage. 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\fP command. Index: doc/if.n ================================================================== --- doc/if.n +++ doc/if.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) if.n 1.7 96/08/26 13:00:00 +'\" RCS: @(#) $Id: if.n,v 1.1.2.1 1998/09/24 23:58:32 stanton Exp $ '\" .so man.macros .TH if n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/incr.n ================================================================== --- doc/incr.n +++ doc/incr.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) incr.n 1.5 96/03/25 20:16:58 +'\" RCS: @(#) $Id: incr.n,v 1.1.2.1 1998/09/24 23:58:32 stanton Exp $ '\" .so man.macros .TH incr n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/info.n ================================================================== --- doc/info.n +++ doc/info.n @@ -4,11 +4,11 @@ '\" Copyright (c) 1993-1997 Bell Labs Innovations for Lucent Technologies '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" SCCS: @(#) info.n 1.17 97/05/19 14:48:52 +'\" RCS: @(#) $Id: info.n,v 1.1.2.1 1998/09/24 23:58:32 stanton Exp $ '\" .so man.macros .TH info n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/interp.n ================================================================== --- doc/interp.n +++ doc/interp.n @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) interp.n 1.37 97/10/31 12:51:11 +'\" RCS: @(#) $Id: interp.n,v 1.1.2.1 1998/09/24 23:58:32 stanton Exp $ '\" .so man.macros .TH interp n 7.6 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -196,11 +196,11 @@ .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 ?\fB-global\fR \fIhiddenCmdName\fR ?\fIarg ...\fR? +\fBinterp\fR \fBinvokehidden\fR \fIpath\fR ?\fB-global\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. 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 Index: doc/join.n ================================================================== --- doc/join.n +++ doc/join.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) join.n 1.5 96/03/25 20:17:46 +'\" RCS: @(#) $Id: join.n,v 1.1.2.1 1998/09/24 23:58:32 stanton Exp $ '\" .so man.macros .TH join n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/lappend.n ================================================================== --- doc/lappend.n +++ doc/lappend.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) lappend.n 1.6 96/03/25 20:18:03 +'\" RCS: @(#) $Id: lappend.n,v 1.1.2.1 1998/09/24 23:58:33 stanton Exp $ '\" .so man.macros .TH lappend n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/library.n ================================================================== --- doc/library.n +++ doc/library.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) library.n 1.23 96/11/20 14:07:04 +'\" RCS: @(#) $Id: library.n,v 1.1.2.3 1999/04/09 21:01:30 surles Exp $ .so man.macros .TH library n "8.0" Tcl "Tcl Built-In Commands" .BS .SH NAME library \- standard library of Tcl procedures @@ -14,11 +14,13 @@ .SH SYNOPSIS .nf \fBauto_execok \fIcmd\fR \fBauto_load \fIcmd\fR \fBauto_mkindex \fIdir pattern pattern ...\fR +\fBauto_mkindex_old \fIdir pattern pattern ...\fR \fBauto_reset\fR +\fBtcl_findLibrary \fIbasename version patch initScript enVarName varName\fR \fBparray \fIarrayName\fR .VS \fBtcl_endOfWord \fIstr start\fR \fBtcl_startOfNextWord \fIstr start\fR \fBtcl_startOfPreviousWord \fIstr start\fR @@ -56,20 +58,22 @@ .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 by the name \fIcmd\fR. -This command examines the directories in the current search path -(given by the PATH environment variable) to see if there is an -executable file named \fIcmd\fR in any of those directories. -If so, it returns 1; if not it returns 0. \fBAuto_exec\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. +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_exec\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_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 @@ -119,11 +123,19 @@ .CE .LP 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 in a relatively +\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 init.tcl to see how this works. +.PP +\fBAuto_mkindex_old\fR parses the Tcl scripts in a relatively unsophisticated way: if any line contains the word \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 don't appear in this way (e.g. they @@ -136,10 +148,30 @@ 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're used. +.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\fP +(e.g., tk8.0), but it might be "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\fP. +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\fP; +relative to the Tcl library directory; +relative to the executable file in the standard installation +bin or bin/\fIarch\fP 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 Prints on standard output the names and values of all the elements in the array \fIarrayName\fR. \fBArrayName\fR must be an array accessible to the caller of \fBparray\fR. @@ -206,21 +238,28 @@ any commands. .TP \fBauto_path\fR If set, then it must contain a valid Tcl list giving directories to search during auto-load operations. +This variable is initialized during startup to contain, in order: +the directories listed in the TCLLIBPATH environment variable, +the directory named by the $tcl_library variable, +the parent directory of $tcl_library, +the directories listed in the $tcl_pkgPath variable. .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 returned by +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 isn't 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. -This variable is only used if \fBauto_path\fR is not defined. +This variable is only used when +initializing the \fBauto_path\fR variable. .TP \fBtcl_nonwordchars\fR .VS This variable contains a regular expression that is used by routines like \fBtcl_endOfWord\fR to identify whether a character is part of a Index: doc/lindex.n ================================================================== --- doc/lindex.n +++ doc/lindex.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) lindex.n 1.8 96/08/26 13:00:02 +'\" RCS: @(#) $Id: lindex.n,v 1.1.2.1 1998/09/24 23:58:33 stanton Exp $ '\" .so man.macros .TH lindex n 7.4 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/linsert.n ================================================================== --- doc/linsert.n +++ doc/linsert.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) linsert.n 1.8 96/08/26 13:00:03 +'\" RCS: @(#) $Id: linsert.n,v 1.1.2.1 1998/09/24 23:58:33 stanton Exp $ '\" .so man.macros .TH linsert n 7.4 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/list.n ================================================================== --- doc/list.n +++ doc/list.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) list.n 1.9 96/08/26 13:00:04 +'\" RCS: @(#) $Id: list.n,v 1.1.2.1 1998/09/24 23:58:33 stanton Exp $ '\" .so man.macros .TH list n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/llength.n ================================================================== --- doc/llength.n +++ doc/llength.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) llength.n 1.5 96/03/25 20:19:25 +'\" RCS: @(#) $Id: llength.n,v 1.1.2.1 1998/09/24 23:58:33 stanton Exp $ '\" .so man.macros .TH llength n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/load.n ================================================================== --- doc/load.n +++ doc/load.n @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) load.n 1.9 97/08/22 18:51:18 +'\" RCS: @(#) $Id: load.n,v 1.1.2.1 1998/09/24 23:58:33 stanton Exp $ '\" .so man.macros .TH load n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/lrange.n ================================================================== --- doc/lrange.n +++ doc/lrange.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) lrange.n 1.9 96/08/26 13:00:05 +'\" RCS: @(#) $Id: lrange.n,v 1.1.2.1 1998/09/24 23:58:33 stanton Exp $ '\" .so man.macros .TH lrange n 7.4 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/lreplace.n ================================================================== --- doc/lreplace.n +++ doc/lreplace.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) lreplace.n 1.9 96/08/26 13:00:07 +'\" RCS: @(#) $Id: lreplace.n,v 1.1.2.1 1998/09/24 23:58:33 stanton Exp $ '\" .so man.macros .TH lreplace n 7.4 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/lsearch.n ================================================================== --- doc/lsearch.n +++ doc/lsearch.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) lsearch.n 1.7 96/08/26 13:00:05 +'\" RCS: @(#) $Id: lsearch.n,v 1.1.2.1 1998/09/24 23:58:34 stanton Exp $ '\" .so man.macros .TH lsearch n 7.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/lsort.n ================================================================== --- doc/lsort.n +++ doc/lsort.n @@ -1,13 +1,14 @@ '\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 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. '\" -'\" SCCS: @(#) lsort.n 1.10 97/08/22 18:50:53 +'\" RCS: @(#) $Id: lsort.n,v 1.1.2.2 1999/01/29 00:20:43 stanton Exp $ '\" .so man.macros .TH lsort n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -18,15 +19,18 @@ .BE .SH DESCRIPTION .PP This command sorts the elements of \fIlist\fR, returning a new -list in sorted order. 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): +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 20 \fB\-ascii\fR Use string comparison with ASCII collation order. This is the default. .VS 8.0 br Index: doc/man.macros ================================================================== --- doc/man.macros +++ doc/man.macros @@ -57,11 +57,11 @@ '\" the option's class in the option database. '\" '\" .UL arg1 arg2 '\" Print arg1 underlined, then print arg2 normally. '\" -'\" SCCS: @(#) man.macros 1.9 97/08/22 18:50:59 +'\" RCS: @(#) $Id: man.macros,v 1.1.2.2 1998/09/24 23:58:34 stanton Exp $ '\" '\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. .if t .wh -1.3i ^B .nr ^l \n(.l .ad b @@ -70,12 +70,12 @@ .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} -.ie !"\\$3"" \{\ .ta \\n()Au \\n()Bu +.ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br ADDED doc/msgcat.n Index: doc/msgcat.n ================================================================== --- /dev/null +++ doc/msgcat.n @@ -0,0 +1,207 @@ +'\" +'\" 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. +'\" +'\" SCCS: @(#) msgcat.n +'\" +.so man.macros +.TH "msgcat" n 8.1 Tcl "Tcl Built-In Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +msgcat \- Tcl message catalog +.SH SYNOPSIS +\fB::msgcat::mc src-string\fR +.sp +\fB::msgcat::mclocale \fR?\fInewLocale\fR? +.sp +\fB::msgcat::mcpreferences\fR +.sp +\fB::msgcat::mcload \fIdirname\fR +.sp +\fB::msgcat::mcset \fIlocale src-string \fR?\fItranslate-string\fR? +.sp +\fB::msgcat::mcunknown \fIlocale src-string\fR +.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 ``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 are provided by adding a new file to +the message catalog. +.PP +Use of the message catalog is optional by any application +or package, but is encouraged if the application or package +wishes to be enabled for multi-lingual applications. + +.SH COMMANDS +.TP +\fB::msgcat::mc src-string\fR +Returns a translation of \fIsrc-string\fR according to the +user's current locale. 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 +applicaton 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. +.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 new locale +is returned. The initial locale defaults to the locale specified in +the user's environment. See \fBLOCALE AND SUBLOCALE SPECIFICATION\fR +below for a description of the locale string format. +.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. If the user has specified LANG=en_US_funky, +this procedure would return {en_US_funky en_US en}. +.TP +\fB::msgcat::mcload \fIdirname\fR +Searches the specified directory for files that match +the language specifications returned by \fB::msgcat::mcpreferences\fR. +Each file located is sourced. The file extension is ``.msg''. +The number of message files which matched the specification +and were loaded is returned. +.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. If \fItranslate-string\fR is not +specified, \fIsrc-string\fR is used for both. The function +return \fItranslate-string\fR. +.TP +\fB::msgcat::mcunknown \fIlocale src-string\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. This procedure can be redefined by the +application, for example to log error messages for each unknown +string. The \fB::msgcat::mcunknown\fB procedure is invoked at the +same stack context as the call to \fB::msgcat::mc\fR. The return vaue +of \fB::msgcat::mcunknown\fB is used as the return vaue for the call +to \fB::msgcat::mc\fR. + +.SH "LOCALE AND SUBLOCALE SPECIFICATION" +.PP +The locale is specified by a locale string. +The locale string consists of +a language code, an optional country code, and an optional +system-specific code, each separated by ``_''. The country and language +codes are specified in standards ISO-639 and ISO-3166. +For example, the locale ``en'' specifies English and + ``en_US'' specifes U.S. English. +.PP +The locale defaults to the value in \fBenv(LANG)\fR at the time the +\fBmsgcat\fR package is loaded. If \fBenv(LANG)\fR is not defined, then the +locale defaults to ``C''. +.PP +When a locale is specified by the user, a ``best match'' search is +performed during string translation. For example, if a user specifies +en_UK_Funky, the locales ``en_UK_Funky'', ``en_UK'', and ``en'' are +searched in order until a matching translation string is found. If no +translation string is available, then \fB::msgcat::unknown\fR 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 +.CS +mcset en hello "hello from ::" +namespace eval foo {mcset en hello "hello from ::foo"} +puts [mc hello] +namespace eval foo {puts [mc hello]} +.CE +will print +.CS +hello from :: +hello from ::foo +.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 locale specifier followed +by ``.msg''. For example: +.CS +es.msg -- spanish +en_UK.msg -- UK English +.CE +.IP [3] +The file contains a series of calls to mcset, setting the +necessary translation strings for the language. For example: +.CS +::msgcat::mcset es "Free Beer!" "Cerveza Gracias!" +.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: +.CS +# load language files, stored in msgs subdirectory +::msgcat::mcload [file join [file dirname [info script]] msgs] +.CE + +.SH "POSTITIONAL 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. +.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: +.CS +format "We produced %1\\\\$d units in location %2\\\\$s" $num $city +format "In location %2\\\\$s we produced %1\\\\$d units" $num $city +.CE +.PP +Similarly, positional parameters can be used with \fBscan\fR to +extract values from internationalized strings. + +.SH "SEE ALSO" +format(n), scan(n), namespace(n), package(n) + +.SH CREDITS +.PP +The message catalog code was developed by Mark Harrison. +.SH KEYWORDS +internationalization, i18n, localization, l10n, message, text, translation Index: doc/namespace.n ================================================================== --- doc/namespace.n +++ doc/namespace.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) namespace.n 1.9 97/08/13 17:08:25 +'\" RCS: @(#) $Id: namespace.n,v 1.1.2.2 1999/04/09 18:42:02 surles Exp $ '\" .so man.macros .TH namespace n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -243,25 +243,25 @@ The global namespace holds all global variables and commands. The \fBnamespace eval\fR command lets you create new namespaces. For example, .CS \fBnamespace eval Counter { - namespace export Bump + namespace export bump variable num 0 - proc Bump {} { + proc bump {} { variable num incr num } }\fR .CE creates a new namespace containing the variable \fBnum\fR and -the procedure \fBBump\fR. +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 +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, @@ -274,11 +274,11 @@ For example, the following series of commands has the same effect as the namespace definition shown above: .CS \fBnamespace eval Counter { variable num 0 - proc Bump {} { + proc bump {} { variable num return [incr num] } } namespace eval Counter { @@ -320,24 +320,24 @@ 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: .CS -\fBCounter::Bump 5 +\fBCounter::bump 5 Counter::Reset\fR .CE We could access the current count like this: .CS \fBputs "count = $Counter::num"\fR .CE 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 +you could invoke its \fBbump\fR procedure from the global namespace like this: .CS -\fBFoo::Counter::Bump 3\fR +\fBFoo::Counter::bump 3\fR .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: @@ -515,40 +515,40 @@ .SH "EXPORTING COMMANDS" You can export commands from a namespace like this: .CS \fBnamespace eval Counter { - namespace export 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} { + namespace export 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!" } } }\fR .CE -The procedures \fBBump\fR and \fBReset\fR are exported, +The procedures \fBbump\fR and \fBreset\fR are exported, so they are included when you import from the \fBCounter\fR namespace, like this: .CS \fBnamespace import Counter::*\fR .CE -However, the \fBcheck\fR procedure is not exported, +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 Index: doc/open.n ================================================================== --- doc/open.n +++ doc/open.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) open.n 1.16 97/01/14 18:00:35 +'\" RCS: @(#) $Id: open.n,v 1.1.2.1 1998/09/24 23:58:34 stanton Exp $ '\" .so man.macros .TH open n 7.6 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/package.n ================================================================== --- doc/package.n +++ doc/package.n @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) package.n 1.5 96/03/18 14:17:31 +'\" RCS: @(#) $Id: package.n,v 1.1.2.2 1999/03/10 06:49:11 stanton Exp $ '\" .so man.macros .TH package n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -15,10 +15,11 @@ .SH SYNOPSIS .nf \fBpackage forget \fIpackage\fR \fBpackage ifneeded \fIpackage version\fR ?\fIscript\fR? \fBpackage names\fR +\fBpackage present \fR?\fB\-exact\fR? \fIpackage \fR?\fIversion\fR? \fBpackage provide \fIpackage \fR?\fIversion\fR? \fBpackage require \fR?\fB\-exact\fR? \fIpackage \fR?\fIversion\fR? \fBpackage unknown \fR?\fIcommand\fR? \fBpackage vcompare \fIversion1 version2\fR \fBpackage versions \fIpackage\fR @@ -72,10 +73,14 @@ 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?\fIversion\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, Index: doc/pid.n ================================================================== --- doc/pid.n +++ doc/pid.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) pid.n 1.5 96/03/25 20:20:57 +'\" RCS: @(#) $Id: pid.n,v 1.1.2.1 1998/09/24 23:58:34 stanton Exp $ '\" .so man.macros .TH pid n 7.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/pkgMkIndex.n ================================================================== --- doc/pkgMkIndex.n +++ doc/pkgMkIndex.n @@ -2,21 +2,23 @@ '\" 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. '\" -'\" SCCS: @(#) pkgMkIndex.n 1.8 97/10/31 12:51:13 +'\" RCS: @(#) $Id: pkgMkIndex.n,v 1.1.2.4 1998/12/02 20:08:03 welch Exp $ '\" .so man.macros -.TH pkg_mkIndex n 7.6 Tcl "Tcl Built-In Commands" +.TH pkg_mkIndex n 8.0 Tcl "Tcl Built-In Commands" .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 \fIdir\fR \fIpattern \fR?\fIpattern pattern ...\fR? +.VS 8.0.3 +\fBpkg_mkIndex ?\fI-direct\fR? ?\fI-load pkgPat\fR? ?\fI-verbose\fR? \fIdir\fR ?\fIpattern pattern ...\fR? +.VE .fi .BE .SH DESCRIPTION .PP @@ -37,18 +39,28 @@ .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. +.VS 8.0.3 +The default pattern is \fB*.tcl\fR and \fB*.[info sharedlibextension]\fR. +.VE +.sp 1 \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 and seeing what packages +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). -.VS "" br +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\fP option +or adjust the order in which \fBpkg_mkIndex\fR processes +the files. See COMPLEX CASES below. + .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 @@ -58,26 +70,23 @@ 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 -.LP +.sp 1 If you install the package anywhere else, then you must ensure that -the directory contaiingn the package is in the \fBauto_path\fR global variable +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. -.VE 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 @@ -88,10 +97,31 @@ 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 manage to load the package immediately upon \fBpackage require\fR +instead of delaying loading until actual use of one of the commands. +.TP 15 +\fB\-load \fIpkgPat\fR +The index process will pre-load any packages that exist in the +current interpreter and match \fIpkgPat\fP into the slave interpreter used to +generate the index. The pattern match uses string match rules. +See COMPLEX CASES below. +.TP 15 +\fB\-verbose\fR +Generate output during the indexing process. Output is via +the \fBtclLog\fP procedure, which by default prints to stderr. +.TP 15 +\fB\-\-\fR +End of the flags, in case \fIdir\fP 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 @@ -122,14 +152,89 @@ 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. -A given file of a given version of a given package isn't +.VS 8.0.3 +Unless the \fI-direct\fR flag was provided when the \fBpkgIndex.tcl\fR +was generated, +.VE +a given file of a given version of a given package isn't actually loaded until the first time one of its commands is invoked. -Thus, after invoking \fBpackage require\fR you won't see +Thus, after invoking \fBpackage require\fR you +.VS 8.0.3 +may +.VE +not see the package's commands in the interpreter, but you will be able to invoke the commands and they will be auto-loaded. +.VS 8.0.3 +.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 mode is enabled when generating the package +index by specifying the \fI-direct\fR argument. +.VE + +.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\fP 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\fP 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 API's such as \fBTcl_PkgRequire\fP API +when loading a binary file. +For example, suppose the BLT package requires Tk, and expresses +this with a call to \fBTcl_PkgRequire\fP in its \fBBlt_Init\fP 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\fP and that match \fIpkgPat\fP +into the interpreter used to process files. +In most cases this will satisfy the \fBTcl_PkgRequire\fP 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\fP flag; +it won't 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\fP 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\fP, +then you must specify the scripts first; otherwise the package loaded from +the binary file may mask the package defined by the scripts. + .SH KEYWORDS auto-load, index, package, version Index: doc/proc.n ================================================================== --- doc/proc.n +++ doc/proc.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) proc.n 1.6 97/05/18 15:49:45 +'\" RCS: @(#) $Id: proc.n,v 1.1.2.1 1998/09/24 23:58:34 stanton Exp $ '\" .so man.macros .TH proc n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/puts.n ================================================================== --- doc/puts.n +++ doc/puts.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) puts.n 1.11 96/08/26 13:00:09 +'\" RCS: @(#) $Id: puts.n,v 1.1.2.2 1999/04/09 18:42:02 surles Exp $ '\" .so man.macros .TH puts n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -32,12 +32,12 @@ 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; on Macintoshes newlines are normally replaced with carriage-returns). -See the \fBfconfigure\fR manual entry for a discussion of end-of-line -translations. +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. Index: doc/pwd.n ================================================================== --- doc/pwd.n +++ doc/pwd.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) pwd.n 1.5 96/03/25 20:21:30 +'\" RCS: @(#) $Id: pwd.n,v 1.1.2.1 1998/09/24 23:58:35 stanton Exp $ '\" .so man.macros .TH pwd n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/read.n ================================================================== --- doc/read.n +++ doc/read.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) read.n 1.15 96/08/26 13:00:09 +'\" RCS: @(#) $Id: read.n,v 1.1.2.2 1999/04/09 18:42:03 surles Exp $ '\" .so man.macros .TH read n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -38,13 +38,13 @@ 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 manual entry for \fBfconfigure\fR for details on the -\fB\-translation\fR option. +See the \fBfconfigure\fR manual entry for a discussion on ways in +which \fBfconfigure\fR will alter input. .SH "SEE ALSO" eof(n), fblocked(n), fconfigure(n) .SH KEYWORDS blocking, channel, end of line, end of file, nonblocking, read, translation Index: doc/regexp.n ================================================================== --- doc/regexp.n +++ doc/regexp.n @@ -1,20 +1,20 @@ '\" -'\" Copyright (c) 1993 The Regents of the University of California. -'\" Copyright (c) 1994-1996 Sun Microsystems, Inc. +'\" Copyright (c) 1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" SCCS: @(#) regexp.n 1.12 96/08/26 13:00:10 +'\" RCS: @(#) $Id: regexp.n,v 1.1.2.6 1999/04/09 18:42:03 surles Exp $ '\" .so man.macros -.TH regexp n "" Tcl "Tcl Built-In Commands" +.TH regexp n 8.1 Tcl "Tcl Built-In Commands" .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 @@ -29,117 +29,1020 @@ 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. -.LP +.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 10 +.TP 15 \fB\-nocase\fR Causes upper-case characters in \fIstring\fR to be treated as lower case during the matching process. -.TP 10 +.TP 15 \fB\-indices\fR Changes what is stored in the \fIsubMatchVar\fRs. -Instead of storing the matching characters from \fBstring\fR, +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 10 +.VS 8.1 +.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 METASYNTAX, below). +.TP 15 +\fB\-line\fR +Enables newline-sensitive matching. By default, newline is a +completely ordinary character with no special meaning. With this +flag, `[^' bracket expressions and `.' never match newline, `^' +matches an empty string after any newline in addition to its normal +function, and `$' 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 METASYNTAX, below). +.TP 15 +\fB\-linestop\fR +Changes the behavior of `[^' bracket expressions and `.' so that they +stop at newlines. This is the same as specifying the \fB(?p)\fR +embedded option (see METASYNTAX, below). +.TP 15 +\fB\-lineanchor\fR +Changes the behavior of `^' and `$' (the ``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 METASYNTAX, below). +.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. +.VE 8.1 +.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. -.LP +.PP If there are more \fIsubMatchVar\fR's than parenthesized subexpressions within \fIexp\fR, or if a particular subexpression in \fIexp\fR doesn't match the string (e.g. because it was in a portion of the expression that wasn't matched), then the corresponding \fIsubMatchVar\fR will be set to ``\fB\-1 \-1\fR'' if \fB\-indices\fR has been specified or to an empty string otherwise. -.SH "REGULAR EXPRESSIONS" -.PP -Regular expressions are implemented using Henry Spencer's package -(thanks, Henry!), -and much of the description of regular expressions below is copied verbatim -from his manual entry. -.PP -A regular expression is zero or more \fIbranches\fR, separated by ``|''. -It matches anything that matches one of the branches. -.PP -A branch is zero or more \fIpieces\fR, concatenated. -It matches a match for the first, followed by a match for the second, etc. -.PP -A piece is an \fIatom\fR possibly followed by ``*'', ``+'', or ``?''. -An atom followed by ``*'' matches a sequence of 0 or more matches of the atom. -An atom followed by ``+'' matches a sequence of 1 or more matches of the atom. -An atom followed by ``?'' matches a match of the atom, or the null string. -.PP -An atom is a regular expression in parentheses (matching a match for the -regular expression), a \fIrange\fR (see below), ``.'' -(matching any single character), ``^'' (matching the null string at the -beginning of the input string), ``$'' (matching the null string at the -end of the input string), a ``\e'' followed by a single character (matching -that character), or a single character with no other significance -(matching that character). -.PP -A \fIrange\fR is a sequence of characters enclosed in ``[]''. -It normally matches any single character from the sequence. -If the sequence begins with ``^'', -it matches any single character \fInot\fR from the rest of the sequence. -If two characters in the sequence are separated by ``\-'', this is shorthand -for the full list of ASCII characters between them -(e.g. ``[0-9]'' matches any decimal digit). -To include a literal ``]'' in the sequence, make it the first character -(following a possible ``^''). -To include a literal ``\-'', make it the first or last character. - -.SH "CHOOSING AMONG ALTERNATIVE MATCHES" -.PP -In general there may be more than one way to match a regular expression -to an input string. For example, consider the command -.CS -\fBregexp (a*)b* aabaaabb x y\fR -.CE -Considering only the rules given so far, \fBx\fR and \fBy\fR could -end up with the values \fBaabb\fR and \fBaa\fR, \fBaaab\fR and \fBaaa\fR, -\fBab\fR and \fBa\fR, or any of several other combinations. -To resolve this potential ambiguity \fBregexp\fR chooses among -alternatives using the rule ``first then longest''. -In other words, it considers the possible matches in order working -from left to right across the input string and the pattern, and it -attempts to match longer pieces of the input string before shorter -ones. More specifically, the following rules apply in decreasing -order of priority: -.IP [1] -If a regular expression could match two different parts of an input string -then it will match the one that begins earliest. -.IP [2] -If a regular expression contains \fB|\fR operators then the leftmost -matching sub-expression is chosen. -.IP [3] -In \fB*\fR, \fB+\fR, and \fB?\fR constructs, longer matches are chosen -in preference to shorter ones. -.IP [4] -In sequences of expression components the components are considered -from left to right. -.LP -In the example from above, \fB(a*)b*\fR matches \fBaab\fR: the \fB(a*)\fR -portion of the pattern is matched first and it consumes the leading -\fBaa\fR; then the \fBb*\fR portion of the pattern consumes the -next \fBb\fR. Or, consider the following example: -.CS -\fBregexp (ab|a)(b*)c abc x y z\fR -.CE -After this command \fBx\fR will be \fBabc\fR, \fBy\fR will be -\fBab\fR, and \fBz\fR will be an empty string. -Rule 4 specifies that \fB(ab|a)\fR gets first shot at the input -string and Rule 2 specifies that the \fBab\fR sub-expression -is checked before the \fBa\fR sub-expression. -Thus the \fBb\fR has already been claimed before the \fB(b*)\fR -component is checked and \fB(b*)\fR must match an empty string. - +.SH "DIFFERENT FLAVORS OF REs" +.VS 8.1 +Regular expressions (``RE''s), as defined by POSIX, come in two +flavors: \fIextended\fR REs (``EREs'') and \fIbasic\fR REs (``BREs''). +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 (``AREs''), 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 `\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. +.PP +A quantified atom is an \fIatom\fR possibly followed +by a single \fIquantifier\fR. +Without a quantifier, it matches a 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 MATCHING) +.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. +.PP +An atom is one of: +.RS 2 +.TP 6 +\fB(\fIre\fB)\fR +(where \fIre\fR is any regular expression) +matches a match for +\fIre\fR, with the match noted for possible reporting +.TP +\fB(?:\fIre\fB)\fR +as previous, +but does no reporting +(a ``non-capturing'' set of parentheses) +.TP +\fB()\fR +matches an empty string, +noted for possible reporting +.TP +\fB(?:)\fR +matches an empty string, +without reporting +.TP +\fB[\fIchars\fB]\fR +a \fIbracket expression\fR, +matching any one of the \fIchars\fR (see BRACKET EXPRESSIONS for more detail) +.TP + \fB.\fR +matches any single character +.TP +\fB\e\fIk\fR +(where \fIk\fR is a non-alphanumeric character) +matches that character taken as an ordinary character, +e.g. \e\e matches a backslash character +.TP +\fB\e\fIc\fR +where \fIc\fR is alphanumeric +(possibly followed by other characters), +an \fIescape\fR (AREs only), +see ESCAPES below +.TP +\fB{\fR +when followed by a character other than a digit, +matches the character +`\fB{\fR'; +when followed by a digit, it is the beginning of a +\fIbound\fR (see above) +.TP +\fIx\fR +where \fIx\fR is +a single character with no other significance, matches that character. +.RE +.PP +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 ESCAPES. +.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 +`\fB\e\fR'. + +.SH "BRACKET EXPRESSIONS" +A \fIbracket expression\fR is a list of characters enclosed in +`\fB[\|]\fR'. +It normally matches any single character from the list (but see below). +If the list begins with +`\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 +`\fB\-\fR', +this is shorthand +for the full \fIrange\fR of characters between those two (inclusive) in the +collating sequence, +e.g. +\fB[0\-9]\fR +in ASCII matches any decimal digit. +Two ranges may not share an +endpoint, so e.g. +\fBa\-c\-e\fR +is illegal. +Ranges are very collating-sequence-dependent, +and portable programs should avoid relying on them. +.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 +`\fB^\fR'), +or (AREs only) precede it with +`\fB\e\fR'. +Alternatively, for +`\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 +`\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. +.PP +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 which has +multi-character collating elements +can thus match more than one character. +Most insidiously, if +\fB^\fR +is used, +this can happen even if no multi-character collating +elements appear in the bracket expression! +If the collating sequence includes a +\fBch\fR +multi-character collating element, +then the RE +\fB[[.ch.]]*c\fR +matches the first five characters +of +`\fBchchcc\fR', +and the RE +\fB[^c]b\fR +matches all of +`\fBchb\fR'. +.PP +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 +`\fB[.\fR'\& +and +`\fB.]\fR'.) +For example, if +\fBo\fR +and +\fB\o'o^'\fR +are the members of an equivalence class, +then +`\fB[[=o=]]\fR', +`\fB[[=\o'o^'=]]\fR', +and +`\fB[o\o'o^']\fR'\& +are all synonymous. +An equivalence class may not be an endpoint +of a range. +.PP +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 class names are: +.PP +.RS +.ne 5 +.nf +.ta 3c 6c 9c +\fBalnum digit punct +alpha graph space +blank lower upper +cntrl print xdigit\fR +.fi +.RE +.PP +These stand for the character classes defined in +\fIctype\fR(3). +A locale may provide others. +A character class may not be used as an endpoint of a range. +.PP +There are two special cases of bracket expressions: +the bracket expressions +\fB[[:<:]]\fR +and +\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 +which is neither preceded nor followed by +word characters. +A word character is an +\fIalnum\fR +character (as defined by +\fIctype\fR(3)) +or an underscore +(\fB_\fR). +These special bracket expressions are deprecated; +users of AREs should use constraint escapes instead (see below). +.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.) +.PP +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, aka 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 X 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 +`\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 exactly four hexadecimal digits) +the Unicode character +\fBU+\fIwxyz\fR +in the local byte ordering +.TP +\fB\eU\fIstuvwxyz\fR +(where +\fIstuvwxyz\fR +is exactly eight hexadecimal digits) +reserved for a somewhat-hypothetical Unicode extension to 32 bits +.TP +\fB\ev\fR +vertical tab, as in C +are all available. +.TP +\fB\ex\fIhhh\fR +(where +\fIhhh\fR +is any sequence of hexadecimal digits) +the character whose hexadecimal value is +\fB0x\fIhhh\fR +(a single character no matter how many hexadecimal digits are used). +.TP +\fB\e0\fR +the character whose value is +\fB0\fR +.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 +.TP +\fB\e\fIxyz\fR +(where +\fIxyz\fR +is exactly three octal digits, +and is not a +back reference (see below)) +the character whose octal value is +\fB0\fIxyz\fR +.RE +.PP +Hexadecimal digits are +`\fB0\fR'-`\fB9\fR', +`\fBa\fR'-`\fBf\fR', +and +`\fBA\fR'-`\fBF\fR'. +Octal digits are +`\fB0\fR'-`\fB7\fR'. +.PP +The character-entry escapes are always taken as ordinary characters. +For example, +\fB\e135\fR +is +\fB]\fR +in ASCII, +but +\fB\e135\fR +does not terminate a bracket expression. +Beware, however, that some applications (e.g., C compilers) interpret +such sequences themselves before the regular-expression package +gets to see them, which may require doubling (quadrupling, etc.) the +`\fB\e\fR'. +.PP +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, +`\fB\ed\fR', +`\fB\es\fR', +and +`\fB\ew\fR'\& +lose their outer brackets, +and +`\fB\eD\fR', +`\fB\eS\fR', +and +`\fB\eW\fR'\& +are illegal. +.PP +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 MATCHING, below, for how this differs from +`\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 which is not the beginning or end of a word +.TP +\fB\eZ\fR +matches only at the end of the string +(see MATCHING, below, for how this differs from +`\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 +\fB[[:<:]]\fR +and +\fB[[:>:]]\fR +above. +Constraint escapes are illegal within bracket expressions. +.PP +A back reference (AREs only) matches the same string matched by the parenthesized +subexpression specified by the number, +so that (e.g.) +\fB([bc])\e1\fR +matches +\fBbb\fR +or +\fBcc\fR +but not +`\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 +`\fB***:\fR', +the rest of the RE is an ARE. +If an RE of any flavor begins with +`\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 MATCHING, below) +.TP 3 +\fBm\fR +historical synonym for +\fBn\fR +.TP 3 +\fBn\fR +newline-sensitive matching (see MATCHING, below) +.TP 3 +\fBp\fR +partial newline-sensitive matching (see MATCHING, below) +.TP 3 +\fBq\fR +rest of RE is a literal (``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 (``weird'') matching (see MATCHING, 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: +.RS 2 +.PP +a white-space character or `\fB#\fR' preceded by `\fB\e\fR' is retained +.PP +white space or `\fB#\fR' within a bracket expression is retained +.PP +white space and comments are illegal within multi-character symbols +like the ARE `\fB(?:\fR' or the BRE `\fB\e(\fR' +.RE +.PP +Expanded-syntax +white-space characters are blank, tab, newline, etc. (any character +defined as \fIspace\fR by +\fIctype\fR(3)). +Exactly how a multi-line expanded-syntax RE +can be entered interactively by a user, +if at all, is application-specific; +expanded syntax is primarily a scripting facility. +.PP +Finally, in an ARE, +outside bracket expressions, the sequence +`\fB(?#\fIttt\fB)\fR' +(where +\fIttt\fR +is any text not containing a +`\fB)\fR') +is a comment, +completely ignored. +Again, this is not allowed between the characters of +multi-character symbols like +`\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 +\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 +Note that 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. +.PP +Match lengths are measured in characters, not collating elements. +An empty string is considered longer than no match at all. +For example, +\fBbb*\fR +matches the three middle characters of +`\fBabbbc\fR', +\fB(week|wee)(night|knights)\fR +matches all ten characters of +`\fBweeknights\fR', +when +\fB(.*).*\fR +is matched against +\fBabc\fR +the parenthesized subexpression +matches all three characters, and +when +\fB(a*)*\fR +is matched against +\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 +`\fB[xX]\fR'. +When it appears inside a bracket expression, all case counterparts +of it are added to the bracket expression, so that +\fB[x]\fR +becomes +\fB[xX]\fR +and +\fB[^x]\fR +becomes +`\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 isn't 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 +`\fB\eb\fR', +`\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 don't 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 +(`RREs' for short) and AREs. +In roughly increasing order of significance: +.PP +.RS +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. +.PP +\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. +.PP +In AREs, +\fB\e\fR +remains a special character within +`\fB[\|]\fR', +so a literal +\fB\e\fR +within +\fB[\|]\fR +must be written +`\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. +.PP +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.) +.RE + +.SH "BASIC REGULAR EXPRESSIONS" +BREs differ from EREs in several respects. +`\fB|\fR', +`\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 +`\fB\e}\fR', +with +\fB{\fR +and +\fB}\fR +by themselves ordinary characters. +The parentheses for nested subexpressions are +\fB\e(\fR +and +`\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 +`\fB^\fR'). +Finally, +single-digit back references are available, +and +\fB\e<\fR +and +\fB\e>\fR +are synonyms for +\fB[[:<:]]\fR +and +\fB[[:>:]]\fR +respectively; +no other escapes are available. + +.VE 8.1 .SH KEYWORDS match, regular expression, string Index: doc/registry.n ================================================================== --- doc/registry.n +++ doc/registry.n @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) registry.n 1.5 97/08/11 19:33:27 +'\" RCS: @(#) $Id: registry.n,v 1.1.2.3 1999/04/07 23:53:31 surles Exp $ '\" .so man.macros .TH registry n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -37,12 +37,15 @@ \fIrootname\fR .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, or -\fBHKEY_CURRENT_CONFIG\fR. The \fIkeypath\fR can be one or more +.VS +\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 +.VE registry key names separated by backslash (\fB\e\fR) characters. .PP \fIOption\fR indicates what to do with the registry key name. Any unique abbreviation for \fIoption\fR is acceptable. The valid options are: @@ -107,11 +110,10 @@ .TP 17 \fBbinary\fR . The registry value contains arbitrary binary data. The data is represented exactly in Tcl, including any embedded nulls. -Tcl .TP \fBnone\fR . The registry value contains arbitrary binary data with no defined type. The data is represented exactly in Tcl, including any embedded Index: doc/regsub.n ================================================================== --- doc/regsub.n +++ doc/regsub.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) regsub.n 1.9 96/08/26 13:00:11 +'\" RCS: @(#) $Id: regsub.n,v 1.1.2.1 1998/09/24 23:58:35 stanton Exp $ '\" .so man.macros .TH regsub n 7.4 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/rename.n ================================================================== --- doc/rename.n +++ doc/rename.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) rename.n 1.6 97/07/30 17:37:26 +'\" RCS: @(#) $Id: rename.n,v 1.1.2.1 1998/09/24 23:58:35 stanton Exp $ '\" .so man.macros .TH rename n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/resource.n ================================================================== --- doc/resource.n +++ doc/resource.n @@ -1,11 +1,11 @@ '\" '\" 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. -'\" SCCS: @(#) resource.n 1.4 97/09/10 15:22:18 +'\" RCS: @(#) $Id: resource.n,v 1.1.2.3 1999/01/29 00:20:43 stanton Exp $ '\" .so man.macros .TH resource n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -53,11 +53,11 @@ \fB\-file\fR \fIresourceRef\fR If the \fB-file\fR option is specified then the resource will be deleted from the file pointed to by \fIresourceRef\fR. Otherwise the first resource with the given \fIresourceName\fR and or \fIresourceId\fR which is found on the resource file path will be -deleted. To inspect the file path, use the \fIresource files\fB command. +deleted. To inspect the file path, use the \fIresource files\fR command. .RE .TP \fBresource files ?\fIresourceRef\fR? If \fIresourceRef\fRis not provided, this command returns a Tcl list of the resource references for all the currently open resource files. @@ -73,12 +73,12 @@ resource files currently opened by the application will be searched. A Tcl list of either the resource name's or resource id's of the found resources will be returned. See the RESOURCE IDS section below for more details about what a resource id is. .TP -\fBresource open \fIfileName\fR ?\fIpermissions\fR? -Open the resource for the file \fIfileName\fR. Standard file +\fBresource open \fIfileName\fR ?\fIaccess\fR? +Open the resource for the file \fIfileName\fR. Standard file access permissions may also be specified (see the manual entry for \fBopen\fR for details). A resource reference (\fIresourceRef\fR) is returned that can be used by the other resource commands. An error can occur if the file doesn't exist or the file does not have a resource fork. However, if you open the file with write permissions the file and/or Index: doc/return.n ================================================================== --- doc/return.n +++ doc/return.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) return.n 1.13 96/08/26 13:00:12 +'\" RCS: @(#) $Id: return.n,v 1.1.2.1 1998/09/24 23:58:36 stanton Exp $ '\" .so man.macros .TH return n 7.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/safe.n ================================================================== --- doc/safe.n +++ doc/safe.n @@ -2,20 +2,19 @@ '\" 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. '\" -'\" SCCS: @(#) safe.n 1.11 97/10/31 12:51:13 +'\" RCS: @(#) $Id: safe.n,v 1.1.2.3 1999/04/06 00:43:15 redman Exp $ '\" .so man.macros .TH "Safe Tcl" n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME -Safe Base \- A mechanism for creating and manipulating safe interpreters. +Safe\ Base \- A mechanism for creating and manipulating safe interpreters. .SH SYNOPSIS -.PP \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? @@ -48,11 +47,11 @@ disclosing information stored on the hosting computer or in the hosting application to any party. .PP The Safe Base allows a master interpreter to create safe, restricted interpreters that contain a set of predefined aliases for the \fBsource\fR, -\fBload\fR, \fBfile\fR and \fBexit\fR commands and +\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 @@ -244,10 +243,16 @@ 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 \fBenconding\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 @@ -260,13 +265,13 @@ in general than integrity and privacy attacks that the Safe Base 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 a safe subset of \fBfile\fR. -The safe interpreter can also auto-load code and it can request that -packages be loaded. +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. Index: doc/scan.n ================================================================== --- doc/scan.n +++ doc/scan.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) scan.n 1.12 96/08/26 13:00:13 +'\" RCS: @(#) $Id: scan.n,v 1.1.2.2 1998/11/18 04:15:46 stanton Exp $ '\" .so man.macros .TH scan n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -29,29 +29,45 @@ scanned from \fIstring\fR the result is converted back into a string and assigned to the corresponding variable. .SH "DETAILS ON SCANNING" .PP -\fBScan\fR operates by scanning \fIstring\fR and \fIformatString\fR together. -If the next character in \fIformatString\fR is a blank or tab then it +\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 isn't a \fB%\fR character then it must match the next character of \fIstring\fR. -When a \fB%\fR is encountered in \fIformatString\fR, it indicates +When a \fB%\fR is encountered in \fIformat\fR, it indicates the start of a conversion specifier. -A conversion specifier contains three fields after the \fB%\fR: +A conversion specifier contains up to four fields after the \fB%\fR: a \fB*\fR, which indicates that the converted value is to be discarded -instead of assigned to a variable; a number indicating a maximum field -width; and a conversion character. +.VS 8.1 +instead of assigned to a variable; a XPG3 position specifier; a number +.VE 8.1 +indicating a maximum field width; 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 \fIformatString\fR, it -first skips any white-space characters in \fIstring\fR. +When \fBscan\fR finds a conversion specifier in \fIformat\fR, it +first skips any white-space characters in \fIstring\fR (unless the +specifier 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. +.VS 8.1 +.PP +If the \fB%\fR is followed by a decimal number and a \fB$\fR, as in +``\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. +.VE 8.1 +.PP The following conversion characters are supported: .TP 10 \fBd\fR The input field must be a decimal integer. It is read in and the value is stored in the variable as a decimal string. @@ -61,10 +77,21 @@ value is stored in the variable as a decimal string. .TP 10 \fBx\fR The input field must be a hexadecimal integer. It is read in and the value is stored in the variable as a decimal string. +.VS 8.1 +.TP 10 +\fBu\fR +The input field must be a decimal integer. The value is stored in the +variable as an unsigned decimal integer string. +.TP 10 +\fBi\fR +The input field must be an integer. The base (i.e. decimal, octal, or +hexadecimal) is determined in the same fashion as described in +\fBexpr\fR. The value is stored in the variable as a decimal string. +.VE 8.1 .TP 10 \fBc\fR A single character is read in and its binary value is stored in the variable as a decimal string. Initial white space is not skipped in this case, so the input @@ -90,18 +117,37 @@ \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. +.VS 8.1 +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. +.VE 8.1 .TP 10 \fB[^\fIchars\fB]\fR The input field consists of any number of 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. +.VS 8.1 +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. +.TP 10 +\fBn\fR +No input is consumed from the input string. Instead, the total number +of chacters scanned from the input string so far is stored in the variable. +.VE 8.1 .LP 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). @@ -113,13 +159,15 @@ .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: +.VS 8.1 .IP [1] -\fB%p\fR and \fB%n\fR conversion specifiers are not currently +\fB%p\fR conversion specifier is not currently supported. +.VE 8.1 .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 field width may be specified for this conversion. Index: doc/seek.n ================================================================== --- doc/seek.n +++ doc/seek.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) seek.n 1.10 96/08/26 13:00:14 +'\" RCS: @(#) $Id: seek.n,v 1.1.2.1 1998/09/24 23:58:36 stanton Exp $ '\" .so man.macros .TH seek n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/set.n ================================================================== --- doc/set.n +++ doc/set.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) set.n 1.6 97/05/18 15:56:26 +'\" RCS: @(#) $Id: set.n,v 1.1.2.1 1998/09/24 23:58:36 stanton Exp $ '\" .so man.macros .TH set n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/socket.n ================================================================== --- doc/socket.n +++ doc/socket.n @@ -1,14 +1,15 @@ '\" '\" 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. '\" -'\" SCCS: @(#) socket.n 1.14 97/10/31 12:51:12 +'\" RCS: @(#) $Id: socket.n,v 1.1.2.2 1999/02/10 23:31:12 stanton Exp $ .so man.macros -.TH socket n 7.5 Tcl "Tcl Built-In Commands" +.TH socket n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME socket \- Open a TCP network connection .SH SYNOPSIS @@ -101,10 +102,18 @@ will be accepted. .SH CONFIGURATION OPTIONS The \fBfconfigure\fR command can be used to query several readonly configuration options for socket channels: +.VS 8.0.5 +.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. +.VE 8.0.5 .TP \fB\-sockname\fR 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 Index: doc/source.n ================================================================== --- doc/source.n +++ doc/source.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) source.n 1.8 97/10/31 12:51:10 +'\" RCS: @(#) $Id: source.n,v 1.1.2.1 1998/09/24 23:58:36 stanton Exp $ '\" .so man.macros .TH source n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/split.n ================================================================== --- doc/split.n +++ doc/split.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) split.n 1.6 96/03/25 20:23:53 +'\" RCS: @(#) $Id: split.n,v 1.1.2.1 1998/09/24 23:58:36 stanton Exp $ '\" .so man.macros .TH split n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/string.n ================================================================== --- doc/string.n +++ doc/string.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) string.n 1.9 96/08/26 13:00:14 +'\" RCS: @(#) $Id: string.n,v 1.1.2.2 1998/10/16 01:24:57 stanton Exp $ '\" .so man.macros .TH string n 7.6 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -83,18 +83,26 @@ abbreviation of it) refers to the last character of the string. 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. +.VS .TP \fBstring tolower \fIstring\fR -Returns a value equal to \fIstring\fR except that all upper case -letters have been converted to lower case. +Returns a value equal to \fIstring\fR except that all upper (or title) +case letters have been converted to lower case. +.TP +\fBstring totitle \fIstring\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. .TP -\fBstring toupper \fIstring\fR -Returns a value equal to \fIstring\fR except that all lower case -letters have been converted to upper case. +\fBstring toupper \fIstring\fR +Returns a value equal to \fIstring\fR except that all lower (or title) +case letters have been converted to upper case. +.VE .TP \fBstring trim \fIstring\fR ?\fIchars\fR? Returns a value equal to \fIstring\fR except that any leading or trailing characters from the set given by \fIchars\fR are removed. @@ -112,20 +120,24 @@ Returns a value equal to \fIstring\fR except that any trailing characters from the set given by \fIchars\fR are removed. If \fIchars\fR is not specified then white space is removed (spaces, tabs, newlines, and carriage returns). +.VS .TP \fBstring wordend \fIstring index\fR -Returns the index of the character just after the last one in the -word containing character \fIindex\fR of \fIstring\fR. -A word is considered to be any contiguous range of alphanumeric -or underscore characters, or any single character other than these. +Returns the index of the character just after the last one in the word +containing character \fIindex\fR of \fIstring\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 index\fR -Returns the index of the first character in the -word containing character \fIindex\fR of \fIstring\fR. -A word is considered to be any contiguous range of alphanumeric -or underscore characters, or any single character other than these. +Returns the index of the first character in the word containing +character \fIindex\fR of \fIstring\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. +.VE .SH KEYWORDS case conversion, compare, index, match, pattern, string, word Index: doc/subst.n ================================================================== --- doc/subst.n +++ doc/subst.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) subst.n 1.9 96/03/25 20:24:17 +'\" RCS: @(#) $Id: subst.n,v 1.1.2.1 1998/09/24 23:58:37 stanton Exp $ '\" .so man.macros .TH subst n 7.4 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/switch.n ================================================================== --- doc/switch.n +++ doc/switch.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) switch.n 1.10 97/10/31 13:05:55 +'\" RCS: @(#) $Id: switch.n,v 1.1.2.1 1998/09/24 23:58:37 stanton Exp $ '\" .so man.macros .TH switch n 7.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/tclsh.1 ================================================================== --- doc/tclsh.1 +++ doc/tclsh.1 @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) tclsh.1 1.13 96/08/26 13:00:15 +'\" RCS: @(#) $Id: tclsh.1,v 1.1.2.1 1998/09/24 23:58:37 stanton Exp $ '\" .so man.macros .TH tclsh 1 "" Tcl "Tcl Applications" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/tclvars.n ================================================================== --- doc/tclvars.n +++ doc/tclvars.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) tclvars.n 1.34 97/08/22 18:51:04 +'\" RCS: @(#) $Id: tclvars.n,v 1.1.2.3 1999/03/25 22:03:45 redman Exp $ '\" .so man.macros .TH tclvars n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! @@ -257,20 +257,31 @@ \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 \fBWin32s\fR, \fBWindows NT\fR, \fBMacOS\fR, or \fBSunOS\fR. +such as \fBWindows 95\fR, \fBWindows NT\fR, \fBMacOS\fR, or \fBSunOS\fR. On UNIX machines, this is the value returned by \fBuname -s\fR. +On Windows 95 and Windows 98, the value returned will be \fBWindows +95\fR to provide better backwards compatibility to Windows 95; to +distinguish between the two, check the \fBosVersion\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. +On UNIX machines, this is the value returned by \fBuname -r\fR. On +Windows 95, the version will be 4.0; on Windows 98, the version will +be 4.10. .TP \fBplatform\fR Either \fBwindows\fR, \fBmacintosh\fR, or \fBunix\fR. This identifies the general operating environment of the machine. +.TP +\fBuser\fR +Either \fBwindows\fR, \fBmacintosh\fR, or \fBunix\fR. This identifies the +current user based on the login information available on the platform. +This comes from the USER or LOGNAME environment variable on Unix, +and the value from GetUserName on Windows and Macintosh. .RE .TP \fBtcl_precision\fR .VS This variable controls the number of digits to generate Index: doc/tell.n ================================================================== --- doc/tell.n +++ doc/tell.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) tell.n 1.9 96/08/26 13:00:17 +'\" RCS: @(#) $Id: tell.n,v 1.1.2.1 1998/09/24 23:58:37 stanton Exp $ '\" .so man.macros .TH tell n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/time.n ================================================================== --- doc/time.n +++ doc/time.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) time.n 1.6 96/03/25 20:25:30 +'\" RCS: @(#) $Id: time.n,v 1.1.2.1 1998/09/24 23:58:37 stanton Exp $ '\" .so man.macros .TH time n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/trace.n ================================================================== --- doc/trace.n +++ doc/trace.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) trace.n 1.12 96/08/26 13:00:18 +'\" RCS: @(#) $Id: trace.n,v 1.1.2.1 1998/09/24 23:58:37 stanton Exp $ '\" .so man.macros .TH trace n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/unknown.n ================================================================== --- doc/unknown.n +++ doc/unknown.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) unknown.n 1.8 96/10/09 08:29:28 +'\" RCS: @(#) $Id: unknown.n,v 1.1.2.1 1998/09/24 23:58:38 stanton Exp $ '\" .so man.macros .TH unknown n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/unset.n ================================================================== --- doc/unset.n +++ doc/unset.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) unset.n 1.5 96/03/25 20:26:21 +'\" RCS: @(#) $Id: unset.n,v 1.1.2.1 1998/09/24 23:58:38 stanton Exp $ '\" .so man.macros .TH unset n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/update.n ================================================================== --- doc/update.n +++ doc/update.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) update.n 1.3 96/03/25 20:26:34 +'\" RCS: @(#) $Id: update.n,v 1.1.2.1 1998/09/24 23:58:38 stanton Exp $ '\" .so man.macros .TH update n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/uplevel.n ================================================================== --- doc/uplevel.n +++ doc/uplevel.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) uplevel.n 1.8 97/08/13 13:41:36 +'\" RCS: @(#) $Id: uplevel.n,v 1.1.2.1 1998/09/24 23:58:38 stanton Exp $ '\" .so man.macros .TH uplevel n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/upvar.n ================================================================== --- doc/upvar.n +++ doc/upvar.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) upvar.n 1.16 97/08/13 13:43:34 +'\" RCS: @(#) $Id: upvar.n,v 1.1.2.1 1998/09/24 23:58:38 stanton Exp $ '\" .so man.macros .TH upvar n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/variable.n ================================================================== --- doc/variable.n +++ doc/variable.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) variable.n 1.4 97/08/13 16:57:57 +'\" RCS: @(#) $Id: variable.n,v 1.1.2.1 1998/09/24 23:58:38 stanton Exp $ '\" .so man.macros .TH variable n 8.0 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/vwait.n ================================================================== --- doc/vwait.n +++ doc/vwait.n @@ -2,11 +2,11 @@ '\" 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. '\" -'\" SCCS: @(#) vwait.n 1.4 97/09/29 11:31:18 +'\" RCS: @(#) $Id: vwait.n,v 1.1.2.1 1998/09/24 23:58:38 stanton Exp $ '\" .so man.macros .TH vwait n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: doc/while.n ================================================================== --- doc/while.n +++ doc/while.n @@ -3,11 +3,11 @@ '\" 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. '\" -'\" SCCS: @(#) while.n 1.7 97/04/08 17:13:50 +'\" RCS: @(#) $Id: while.n,v 1.1.2.1 1998/09/24 23:58:39 stanton Exp $ '\" .so man.macros .TH while n "" Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! Index: generic/README ================================================================== --- generic/README +++ generic/README @@ -1,5 +1,5 @@ This directory contains Tcl source files that work on all the platforms where Tcl runs (e.g. UNIX, PCs, and Macintoshes). Platform-specific sources are in the directories ../unix, ../win, and ../mac. -SCCS ID: @(#) README 1.1 95/09/11 14:02:13 +RCS: @(#) $Id: README,v 1.1.2.1 1998/09/24 23:58:39 stanton Exp $ Index: generic/panic.c ================================================================== --- generic/panic.c +++ generic/panic.c @@ -9,11 +9,11 @@ * 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. * - * SCCS: @(#) panic.c 1.15 96/09/12 14:55:25 + * RCS: @(#) $Id: panic.c,v 1.1.2.1 1998/09/24 23:58:39 stanton Exp $ */ #include #ifdef NO_STDLIB_H # include "../compat/stdlib.h" @@ -23,10 +23,13 @@ #define panic panicDummy #include "tcl.h" #undef panic +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT + EXTERN void panic _ANSI_ARGS_((char *format, char *arg1, char *arg2, char *arg3, char *arg4, char *arg5, char *arg6, char *arg7, char *arg8)); /* ADDED generic/regc_color.c Index: generic/regc_color.c ================================================================== --- /dev/null +++ generic/regc_color.c @@ -0,0 +1,742 @@ +/* + * colorings of characters + * This file is #included by regcomp.c. + * + * 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(v, cm) +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(cm) +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(cm, tree, level) +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(cm, c, co) +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(VS(newt->tcolor), VS(t->tcolor), + BYTTAB*sizeof(color)); + else + memcpy(VS(newt->tptr), VS(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(cm) +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(cm) +struct colormap *cm; +{ + struct colordesc *cd; + struct colordesc *new; + 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 { + /* oops, must allocate more */ + n = cm->ncds * 2; + if (cm->cd == cm->cdspace) { + new = (struct colordesc *)MALLOC(n * + sizeof(struct colordesc)); + if (new != NULL) + memcpy(VS(new), VS(cm->cdspace), cm->ncds * + sizeof(struct colordesc)); + } else + new = (struct colordesc *)REALLOC(cm->cd, + n * sizeof(struct colordesc)); + if (new == NULL) { + CERR(REG_ESPACE); + return COLORLESS; + } + cm->cd = new; + 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(cm, co) +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->max >= 0); + while ((size_t)cm->free > cm->max) + cm->free = cm->cd[cm->free].sub; + if (cm->free > 0) { + assert(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(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(cm) +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(cm, c) +struct colormap *cm; +pchr c; +{ + color co; /* current color of c */ + color sco; /* new subcolor */ + + co = GETCOLOR(cm, c); + sco = newsub(cm, co); + if (sco == COLORLESS) { + return 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(cm, co) +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) + 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(v, from, to, lp, rp) +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(v, start, lp, rp) +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 & BYTMASK) == 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(VS(t->tptr), VS(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; i < BYTTAB; i++) + t->tcolor[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(nfa, cm) +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; cd < end; cd++, co++) { + sco = cd->sub; + 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); */ + cd->arcs = a->colorchain; + a->co = sco; + /* colorchain(cm, a); */ + a->colorchain = scd->arcs; + scd->arcs = 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(cm, a) +struct colormap *cm; +struct arc *a; +{ + struct colordesc *cd = &cm->cd[a->co]; + + a->colorchain = cd->arcs; + cd->arcs = a; +} + +/* + - uncolorchain - delete this arc from the color chain of its color + ^ static VOID uncolorchain(struct colormap *, struct arc *); + */ +static VOID +uncolorchain(cm, a) +struct colormap *cm; +struct arc *a; +{ + struct colordesc *cd = &cm->cd[a->co]; + struct arc *aa; + + aa = cd->arcs; + if (aa == a) /* easy case */ + cd->arcs = a->colorchain; + else { + for (; aa != NULL && aa->colorchain != a; aa = aa->colorchain) + continue; + assert(aa != NULL); + aa->colorchain = a->colorchain; + } + a->colorchain = NULL; /* paranoia */ +} + +/* + - singleton - is this character in its own color? + ^ static int singleton(struct colormap *, pchr c); + */ +#if 0 +static int /* predicate */ +singleton(cm, c) +struct colormap *cm; +pchr c; +{ + color co; /* color of c */ + + co = GETCOLOR(cm, c); + if (cm->cd[co].nchrs == 1 && cm->cd[co].sub == NOSUB) + return 1; + return 0; +} +#endif +/* + - 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(nfa, cm, type, but, from, to) +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; cd < end && !CISERR(); cd++, co++) + if (!UNUSEDCOLOR(cd) && cd->sub != 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(nfa, cm, type, of, from, to) +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; cd < end && !CISERR(); cd++, co++) + if (!UNUSEDCOLOR(cd) && !(cd->flags&PSEUDO)) + if (findarc(of, PLAIN, co) == NULL) + newarc(nfa, type, co, from, to); +} + + + +#ifdef REG_DEBUG + +/* + - dumpcolors - debugging output + ^ static VOID dumpcolors(struct colormap *, FILE *); + */ +static VOID +dumpcolors(cm, f) +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; cd < end; cd++, co++) /* skip 0 */ + if (!UNUSEDCOLOR(cd)) { + assert(cd->nchrs > 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); + /* it's hard to do this more efficiently */ + for (c = CHR_MIN; c < CHR_MAX; c++) + if (GETCOLOR(cm, c) == co) + dumpchr(c, f); + assert(c == CHR_MAX); + 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(cm, tree, level, f) +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) + {} + 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(c, f) +pchr c; +FILE *f; +{ + if (c == '\\') + fprintf(f, "\\\\"); + else if (c > ' ' && c <= '~') + putc((char)c, f); + else + fprintf(f, "\\u%04lx", (long)c); +} + +#endif /* ifdef REG_DEBUG */ ADDED generic/regc_cvec.c Index: generic/regc_cvec.c ================================================================== --- /dev/null +++ generic/regc_cvec.c @@ -0,0 +1,170 @@ +/* + * Utility functions for handling cvecs + * This file is #included by regcomp.c. + */ + +/* + - newcvec - allocate a new cvec + ^ static struct cvec *newcvec(int, int, int); + */ +static struct cvec * +newcvec(nchrs, nranges, nmcces) +int nchrs; /* to hold this many chrs... */ +int nranges; /* ... and this many ranges... */ +int nmcces; /* ... and this many MCCEs */ +{ + size_t n; + size_t nc; + struct cvec *cv; + + nc = (size_t)nchrs + (size_t)nmcces*(MAXMCCE+1) + (size_t)nranges*2; + n = sizeof(struct cvec) + (size_t)(nmcces-1)*sizeof(chr *) + + nc*sizeof(chr); + cv = (struct cvec *)MALLOC(n); + if (cv == NULL) + return NULL; + cv->chrspace = nc; + cv->chrs = (chr *)&cv->mcces[nmcces]; /* chrs just after MCCE ptrs */ + cv->mccespace = nmcces; + cv->ranges = cv->chrs + nchrs + nmcces*(MAXMCCE+1); + 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(cv) +struct cvec *cv; +{ + int i; + + assert(cv != NULL); + cv->nchrs = 0; + assert(cv->chrs == (chr *)&cv->mcces[cv->mccespace]); + cv->nmcces = 0; + cv->nmccechrs = 0; + cv->nranges = 0; + for (i = 0; i < cv->mccespace; i++) + cv->mcces[i] = NULL; + + return cv; +} + +/* + - addchr - add a chr to a cvec + ^ static VOID addchr(struct cvec *, pchr); + */ +static VOID +addchr(cv, c) +struct cvec *cv; +pchr c; +{ + assert(cv->nchrs < cv->chrspace - cv->nmccechrs); + cv->chrs[cv->nchrs++] = (chr)c; +} + +/* + - addrange - add a range to a cvec + ^ static VOID addrange(struct cvec *, pchr, pchr); + */ +static VOID +addrange(cv, from, to) +struct cvec *cv; +pchr from; +pchr to; +{ + assert(cv->nranges < cv->rangespace); + cv->ranges[cv->nranges*2] = (chr)from; + cv->ranges[cv->nranges*2 + 1] = (chr)to; + cv->nranges++; +} + +#ifdef USE_MCCE +/* + - addmcce - add an MCCE to a cvec + ^ static VOID addmcce(struct cvec *, chr *, chr *); + */ +static VOID +addmcce(cv, startp, endp) +struct cvec *cv; +chr *startp; /* beginning of text */ +chr *endp; /* just past end of text */ +{ + int n = endp - startp; + int i; + chr *s; + chr *d; + + assert(n > 0); + assert(cv->nchrs + n < cv->chrspace - cv->nmccechrs); + assert(cv->nmcces < cv->mccespace); + d = &cv->chrs[cv->chrspace - cv->nmccechrs - n - 1]; + cv->mcces[cv->nmcces++] = d; + for (s = startp, i = n; i > 0; s++, i--) + *d++ = *s; + *d++ = 0; /* endmarker */ + assert(d == &cv->chrs[cv->chrspace - cv->nmccechrs]); + cv->nmccechrs += n + 1; +} +#endif + +/* + - haschr - does a cvec contain this chr? + ^ static int haschr(struct cvec *, pchr); + */ +static int /* predicate */ +haschr(cv, c) +struct cvec *cv; +pchr c; +{ + int i; + chr *p; + + for (p = cv->chrs, i = cv->nchrs; i > 0; p++, i--) + if (*p == c) + return 1; + for (p = cv->ranges, i = cv->nranges; i > 0; p += 2, i--) + if (*p <= c && c <= *(p+1)) + return 1; + return 0; +} + +/* + - getcvec - get a cvec, remembering it as v->cv + ^ static struct cvec *getcvec(struct vars *, int, int, int); + */ +static struct cvec * +getcvec(v, nchrs, nranges, nmcces) +struct vars *v; +int nchrs; /* to hold this many chrs... */ +int nranges; /* ... and this many ranges... */ +int nmcces; /* ... and this many MCCEs */ +{ + if (v->cv != NULL && nchrs <= v->cv->chrspace && + nranges <= v->cv->rangespace && + nmcces <= v->cv->mccespace) + return clearcvec(v->cv); + + if (v->cv != NULL) + freecvec(v->cv); + v->cv = newcvec(nchrs, nranges, nmcces); + if (v->cv == NULL) + ERR(REG_ESPACE); + + return v->cv; +} + +/* + - freecvec - free a cvec + ^ static VOID freecvec(struct cvec *); + */ +static VOID +freecvec(cv) +struct cvec *cv; +{ + FREE(cv); +} ADDED generic/regc_lex.c Index: generic/regc_lex.c ================================================================== --- /dev/null +++ generic/regc_lex.c @@ -0,0 +1,1010 @@ +/* + * lexical analyzer + * This file is #included by regcomp.c. + */ + +/* 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(v) +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(v) +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 *, chr *, chr *); + */ +static VOID +lexnest(v, beginp, endp) +struct vars *v; +chr *beginp; /* start of interpolation */ +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 chr backd[] = { /* \d */ + CHR('['), CHR('['), CHR(':'), + CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'), + CHR(':'), CHR(']'), CHR(']') +}; +static chr backD[] = { /* \D */ + CHR('['), CHR('^'), CHR('['), CHR(':'), + CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'), + CHR(':'), CHR(']'), CHR(']') +}; +static chr brbackd[] = { /* \d within brackets */ + CHR('['), CHR(':'), + CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'), + CHR(':'), CHR(']') +}; +static chr backs[] = { /* \s */ + CHR('['), CHR('['), CHR(':'), + CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'), + CHR(':'), CHR(']'), CHR(']') +}; +static chr backS[] = { /* \S */ + CHR('['), CHR('^'), CHR('['), CHR(':'), + CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'), + CHR(':'), CHR(']'), CHR(']') +}; +static chr brbacks[] = { /* \s within brackets */ + CHR('['), CHR(':'), + CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'), + CHR(':'), CHR(']') +}; +static chr backw[] = { /* \w */ + CHR('['), CHR('['), CHR(':'), + CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'), + CHR(':'), CHR(']'), CHR('_'), CHR(']') +}; +static chr backW[] = { /* \W */ + CHR('['), CHR('^'), CHR('['), CHR(':'), + CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'), + CHR(':'), CHR(']'), CHR('_'), CHR(']') +}; +static 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(v) +struct vars *v; +{ + lexnest(v, backw, ENDOF(backw)); +} + +/* + - next - get next token + ^ static int next(struct vars *); + */ +static int /* 1 normal, 0 failure */ +next(v) +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; + + /* 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(v) +struct vars *v; +{ + chr c; + static chr alert[] = { + CHR('a'), CHR('l'), CHR('e'), CHR('r'), CHR('t') + }; + static chr esc[] = { + CHR('E'), CHR('S'), CHR('C') + }; + 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 = lexdigits(v, 16, 4, 4); + if (ISERR()) + FAILW(REG_EESCAPE); + RETV(PLAIN, c); + break; + case CHR('U'): + c = lexdigits(v, 16, 8, 8); + if (ISERR()) + FAILW(REG_EESCAPE); + RETV(PLAIN, c); + 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 = lexdigits(v, 16, 1, 255); /* REs >255 long outside spec */ + 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 = 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 <= 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 = lexdigits(v, 8, 1, 3); + if (ISERR()) + FAILW(REG_EESCAPE); + 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 chr lexdigits(struct vars *, int, int, int); + */ +static chr /* chr value; errors signalled via ERR */ +lexdigits(v, base, minlen, maxlen) +struct vars *v; +int base; +int minlen; +int maxlen; +{ + uchr n; /* unsigned to avoid overflow misbehavior */ + int len; + chr c; + int d; + CONST uchr ub = (uchr) base; + + n = 0; + for (len = 0; len < maxlen && !ATEOS(); len++) { + 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 (chr)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(v, pc) +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(v) +struct vars *v; +{ + 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() +{ + 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 *, chr *, chr *, pchr); + */ +static chr +chrnamed(v, startp, endp, lastresort) +struct vars *v; +chr *startp; /* start of name */ +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]; +} ADDED generic/regc_locale.c Index: generic/regc_locale.c ================================================================== --- /dev/null +++ generic/regc_locale.c @@ -0,0 +1,781 @@ +/* + * 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. + * + * RCS: @(#) $Id: regc_locale.c,v 1.1.2.6 1999/04/02 23:44:53 stanton Exp $ + */ + +/* ASCII character-name table */ + +static struct cname { + char *name; + 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 crange { + chr start; + chr end; +} crange; + +static crange alphaTable[] = { + {0X0041, 0X005A}, {0X0061, 0X007A}, {0X00AA, 0X00AA}, {0X00B5, 0X00B5}, + {0X00BA, 0X00BA}, {0X00C0, 0X00D6}, {0X00D8, 0X00F6}, {0X00F8, 0X01F5}, + {0X01FA, 0X0217}, {0X0250, 0X02A8}, {0X02B0, 0X02B8}, {0X02BB, 0X02C1}, + {0X02E0, 0X02E4}, {0X037A, 0X037A}, {0x0386, 0x0386}, {0X0388, 0X038A}, + {0X038C, 0X038C}, {0X038E, 0X03A1}, {0X03A3, 0X03CE}, {0X03D0, 0X03D6}, + {0X03DA, 0X03DA}, {0X03DC, 0X03DC}, {0X03DE, 0X03DE}, {0X03E0, 0X03E0}, + {0X03E2, 0X03F3}, {0X0401, 0X040C}, {0X040E, 0X044F}, {0X0451, 0X045C}, + {0X045E, 0X0481}, {0X0490, 0X04C4}, {0X04C7, 0X04C8}, {0X04CB, 0X04CC}, + {0X04D0, 0X04EB}, {0X04EE, 0X04F5}, {0X04F8, 0X04F9}, {0x0531, 0x0556}, + {0x0559, 0x0559}, {0x0561, 0x0587}, {0X05D0, 0X05EA}, {0X05F0, 0X05F2}, + {0X0621, 0X063A}, {0x0641, 0x0652}, {0X0670, 0X06B7}, {0X06BA, 0X06BE}, + {0X06C0, 0X06CE}, {0X06D0, 0X06D3}, {0X06D5, 0X06DC}, {0X06E1, 0X06E8}, + {0X06ED, 0X06ED}, {0x0901, 0x0903}, {0x0905, 0x0939}, {0X093D, 0X094C}, + {0x0958, 0x0963}, {0x0981, 0x0983}, {0X0985, 0X098C}, {0X098F, 0X0990}, + {0X0993, 0X09A8}, {0X09AA, 0X09B0}, {0X09B2, 0X09B2}, {0X09B6, 0X09B9}, + {0X09BE, 0X09C4}, {0X09C7, 0X09C8}, {0X09CB, 0X09CC}, {0X09D7, 0X09D7}, + {0X09DC, 0X09DD}, {0X09DF, 0X09E3}, {0X09F0, 0X09F1}, {0X0A02, 0X0A02}, + {0X0A05, 0X0A0A}, {0X0A0F, 0X0A10}, {0X0A13, 0X0A28}, {0X0A2A, 0X0A30}, + {0X0A32, 0X0A33}, {0X0A35, 0X0A36}, {0X0A38, 0X0A39}, {0X0A3E, 0X0A42}, + {0X0A47, 0X0A48}, {0X0A4B, 0X0A4C}, {0X0A59, 0X0A5C}, {0X0A5E, 0X0A5E}, + {0X0A70, 0X0A74}, {0X0A81, 0X0A83}, {0X0A85, 0X0A8B}, {0X0A8D, 0X0A8D}, + {0X0A8F, 0X0A91}, {0X0A93, 0X0AA8}, {0X0AAA, 0X0AB0}, {0X0AB2, 0X0AB3}, + {0X0AB5, 0X0AB9}, {0X0ABD, 0X0AC5}, {0X0AC7, 0X0AC9}, {0X0ACB, 0X0ACC}, + {0X0AE0, 0X0AE0}, {0X0B01, 0X0B03}, {0X0B05, 0X0B0C}, {0X0B0F, 0X0B10}, + {0X0B13, 0X0B28}, {0X0B2A, 0X0B30}, {0X0B32, 0X0B33}, {0X0B36, 0X0B39}, + {0X0B3D, 0X0B43}, {0X0B47, 0X0B48}, {0X0B4B, 0X0B4C}, {0X0B56, 0X0B57}, + {0X0B5C, 0X0B5D}, {0X0B5F, 0X0B61}, {0X0B82, 0X0B83}, {0X0B85, 0X0B8A}, + {0X0B8E, 0X0B90}, {0X0B92, 0X0B95}, {0X0B99, 0X0B9A}, {0X0B9C, 0X0B9C}, + {0X0B9E, 0X0B9F}, {0X0BA3, 0X0BA4}, {0X0BA8, 0X0BAA}, {0X0BAE, 0X0BB5}, + {0X0BB7, 0X0BB9}, {0X0BBE, 0X0BC2}, {0X0BC6, 0X0BC8}, {0X0BCA, 0X0BCC}, + {0X0BD7, 0X0BD7}, {0X0C01, 0X0C03}, {0X0C05, 0X0C0C}, {0X0C0E, 0X0C10}, + {0X0C12, 0X0C28}, {0X0C2A, 0X0C33}, {0X0C35, 0X0C39}, {0X0C3E, 0X0C44}, + {0X0C46, 0X0C48}, {0X0C4A, 0X0C4C}, {0X0C55, 0X0C56}, {0X0C60, 0X0C61}, + {0X0C82, 0X0C83}, {0X0C85, 0X0C8C}, {0X0C8E, 0X0C90}, {0X0C92, 0X0CA8}, + {0X0CAA, 0X0CB3}, {0X0CB5, 0X0CB9}, {0X0CBE, 0X0CC4}, {0X0CC6, 0X0CC8}, + {0X0CCA, 0X0CCC}, {0X0CD5, 0X0CD6}, {0X0CDE, 0X0CDE}, {0X0CE0, 0X0CE1}, + {0X0D02, 0X0D03}, {0X0D05, 0X0D0C}, {0X0D0E, 0X0D10}, {0X0D12, 0X0D28}, + {0X0D2A, 0X0D39}, {0X0D3E, 0X0D43}, {0X0D46, 0X0D48}, {0X0D4A, 0X0D4C}, + {0X0D57, 0X0D57}, {0X0D60, 0X0D61}, {0X0E01, 0X0E2E}, {0X0E30, 0X0E3A}, + {0X0E40, 0X0E45}, {0X0E47, 0X0E47}, {0X0E4D, 0X0E4D}, {0X0E81, 0X0E82}, + {0X0E84, 0X0E84}, {0X0E87, 0X0E88}, {0X0E8A, 0X0E8A}, {0X0E8D, 0X0E8D}, + {0X0E94, 0X0E97}, {0X0E99, 0X0E9F}, {0X0EA1, 0X0EA3}, {0X0EA5, 0X0EA5}, + {0X0EA7, 0X0EA7}, {0X0EAA, 0X0EAB}, {0X0EAD, 0X0EAE}, {0X0EB0, 0X0EB9}, + {0X0EBB, 0X0EBD}, {0X0EC0, 0X0EC4}, {0X0ECD, 0X0ECD}, {0X0EDC, 0X0EDD}, + {0X0F40, 0X0F47}, {0X0F49, 0X0F69}, {0X0F71, 0X0F81}, {0X0F90, 0X0F95}, + {0X0F97, 0X0F97}, {0X0F99, 0X0FAD}, {0X0FB1, 0X0FB7}, {0X0FB9, 0X0FB9}, + {0X10A0, 0X10C5}, {0X10D0, 0X10F6}, {0x1100, 0x1159}, {0X115F, 0X11A2}, + {0X11A8, 0X11F9}, {0X1E00, 0X1E9B}, {0X1EA0, 0X1EF9}, {0X1F00, 0X1F15}, + {0X1F18, 0X1F1D}, {0X1F20, 0X1F45}, {0X1F48, 0X1F4D}, {0X1F50, 0X1F57}, + {0X1F59, 0X1F59}, {0X1F5B, 0X1F5B}, {0X1F5D, 0X1F5D}, {0X1F5F, 0X1F7D}, + {0X1F80, 0X1FB4}, {0X1FB6, 0X1FBC}, {0X1FBE, 0X1FBE}, {0X1FC2, 0X1FC4}, + {0X1FC6, 0X1FCC}, {0X1FD0, 0X1FD3}, {0X1FD6, 0X1FDB}, {0X1FE0, 0X1FEC}, + {0X1FF2, 0X1FF4}, {0X1FF6, 0X1FFC}, {0X207F, 0X207F}, {0x2102, 0x2102}, + {0x2107, 0x2107}, {0X210A, 0X2113}, {0x2115, 0x2115}, {0X2118, 0X211D}, + {0x2124, 0x2124}, {0x2126, 0x2126}, {0x2128, 0x2128}, {0X212A, 0X2131}, + {0x2133, 0x2138}, {0x2160, 0x2182}, {0x3041, 0x3094}, {0X30A1, 0X30FA}, + {0X3105, 0X312C}, {0X3131, 0X318E}, {0XAC00, 0XD7A3}, {0XFB00, 0XFB06}, + {0XFB13, 0XFB17}, {0XFB1F, 0XFB28}, {0XFB2A, 0XFB36}, {0XFB38, 0XFB3C}, + {0XFB3E, 0XFB3E}, {0XFB40, 0XFB41}, {0XFB43, 0XFB44}, {0XFB46, 0XFBB1}, + {0XFBD3, 0XFD3D}, {0XFD50, 0XFD8F}, {0XFD92, 0XFDC7}, {0XFDF0, 0XFDFB}, + {0XFE70, 0XFE72}, {0XFE74, 0XFE74}, {0XFE76, 0XFEFC}, {0XFF21, 0XFF3A}, + {0XFF41, 0XFF5A}, {0XFF66, 0XFF6F}, {0XFF71, 0XFF9D}, {0XFFA0, 0XFFBE}, + {0XFFC2, 0XFFC7}, {0XFFCA, 0XFFCF}, {0XFFD2, 0XFFD7}, {0XFFDA, 0XFFDC} +}; + +#define NUM_ALPHA (sizeof(alphaTable)/sizeof(crange)) + +static crange digitTable[] = { + {0x0030, 0x0039} +}; + +#define NUM_DIGIT (sizeof(digitTable)/sizeof(crange)) + +static crange punctTable[] = { + {0x0021, 0x0023}, {0X0025, 0X002A}, {0X002C, 0X002F}, {0X003A, 0X003B}, + {0X003F, 0X0040}, {0X005B, 0X005D}, {0X005F, 0X005F}, {0X007B, 0X007B}, + {0X007D, 0X007D}, {0X00A1, 0X00A1}, {0X00AB, 0X00AB}, {0X00AD, 0X00AD}, + {0X00BB, 0X00BB}, {0X00BF, 0X00BF}, {0X02BC, 0X02BC}, {0x0374, 0x0375}, + {0X037E, 0X037E}, {0x0387, 0x0387}, {0X055A, 0X055F}, {0x0589, 0x0589}, + {0X05BE, 0X05BE}, {0X05C0, 0X05C0}, {0X05C3, 0X05C3}, {0X05F3, 0X05F4}, + {0X060C, 0X060C}, {0X061B, 0X061B}, {0X061F, 0X061F}, {0X066A, 0X066D}, + {0X06D4, 0X06D4}, {0x0964, 0x0965}, {0x0970, 0x0970}, {0X0E2F, 0X0E2F}, + {0X0E5A, 0X0E5B}, {0X0EAF, 0X0EAF}, {0X0F04, 0X0F12}, {0X0F3A, 0X0F3F}, + {0X0F85, 0X0F85}, {0X10FB, 0X10FB}, {0x2010, 0x2027}, {0x2030, 0x2043}, + {0x2045, 0x2046}, {0X207D, 0X207E}, {0X208D, 0X208E}, {0X2329, 0X232A}, + {0x3001, 0x3003}, {0x3006, 0x3006}, {0x3008, 0x3011}, {0X3014, 0X301F}, + {0x3030, 0x3030}, {0X30FB, 0X30FB}, {0XFD3E, 0XFD3F}, {0XFE30, 0XFE44}, + {0XFE49, 0XFE52}, {0XFE54, 0XFE61}, {0XFE63, 0XFE63}, {0XFE68, 0XFE68}, + {0XFE6A, 0XFE6B}, {0XFF01, 0XFF03}, {0XFF05, 0XFF0A}, {0XFF0C, 0XFF0F}, + {0XFF1A, 0XFF1B}, {0XFF1F, 0XFF20}, {0XFF3B, 0XFF3D}, {0XFF3F, 0XFF3F}, + {0XFF5B, 0XFF5B}, {0XFF5D, 0XFF5D}, {0XFF61, 0XFF65} +}; + +#define NUM_PUNCT (sizeof(punctTable)/sizeof(crange)) + +static crange spaceTable[] = { + {0x0000, 0x0000}, {0x0009, 0x000D}, {0x0020, 0x0020}, {0x00A0, 0x00A0}, + {0x2000, 0x200F}, {0x2028, 0x202E}, {0X206A, 0X206F}, {0x3000, 0x3000}, + {0xFEFF, 0xFEFF} +}; + +#define NUM_SPACE (sizeof(spaceTable)/sizeof(crange)) + +static crange upperRangeTable[] = { + {0x0041, 0x005a}, {0x00c0, 0x00d6}, {0x00d8, 0x00de}, {0x0189, 0x018b}, + {0x018e, 0x0191}, {0x0388, 0x038a}, {0x0391, 0x03a1}, {0x03a3, 0x03ab}, + {0x03d2, 0x03d4}, {0x0401, 0x040c}, {0x040e, 0x042f}, {0x0531, 0x0556}, + {0x10a0, 0x10c5}, {0x1f08, 0x1f0f}, {0x1f18, 0x1f1d}, {0x1f28, 0x1f2f}, + {0x1f38, 0x1f3f}, {0x1f48, 0x1f4d}, {0x1f68, 0x1f6f}, {0x1f88, 0x1f8f}, + {0x1f98, 0x1f9f}, {0x1fa8, 0x1faf}, {0x1fb8, 0x1fbc}, {0x1fc8, 0x1fcc}, + {0x1fd8, 0x1fdb}, {0x1fe8, 0x1fec}, {0x1ff8, 0x1ffc}, {0x210b, 0x210d}, + {0x2110, 0x2112}, {0x2118, 0x211d}, {0x212a, 0x212d}, {0x2130, 0x2131}, + {0xff21, 0xff3a} +}; + +#define NUM_UPPER_RANGE (sizeof(upperRangeTable)/sizeof(crange)) + +static chr upperCharTable[] = { + 0x0100, 0x0102, 0x0104, 0x0106, 0x0108, 0x010a, 0x010c, 0x010e, 0x0110, + 0x0112, 0x0114, 0x0116, 0x0118, 0x011a, 0x011c, 0x011e, 0x0120, 0x0122, + 0x0124, 0x0126, 0x0128, 0x012a, 0x012c, 0x012e, 0x0130, 0x0132, 0x0134, + 0x0136, 0x0139, 0x013b, 0x013d, 0x013f, 0x0141, 0x0143, 0x0145, 0x0147, + 0x014a, 0x014c, 0x014e, 0x0150, 0x0152, 0x0154, 0x0156, 0x0158, 0x015a, + 0x015c, 0x015e, 0x0160, 0x0162, 0x0164, 0x0166, 0x0168, 0x016a, 0x016c, + 0x016e, 0x0170, 0x0172, 0x0174, 0x0176, 0x0178, 0x0179, 0x017b, 0x017d, + 0x0181, 0x0182, 0x0184, 0x0186, 0x0187, 0x0193, 0x0194, 0x0196, 0x0197, + 0x0198, 0x019c, 0x019d, 0x019f, 0x01a0, 0x01a2, 0x01a4, 0x01a6, 0x01a7, + 0x01a9, 0x01ac, 0x01ae, 0x01af, 0x01b1, 0x01b2, 0x01b3, 0x01b5, 0x01b7, + 0x01b8, 0x01bc, 0x01c4, 0x01c7, 0x01ca, 0x01cd, 0x01cf, 0x01d1, 0x01d3, + 0x01d5, 0x01d7, 0x01d9, 0x01db, 0x01de, 0x01e0, 0x01e2, 0x01e4, 0x01e6, + 0x01e8, 0x01ea, 0x01ec, 0x01ee, 0x01f1, 0x01f4, 0x01fa, 0x01fc, 0x01fe, + 0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020a, 0x020c, 0x020e, 0x0210, + 0x0212, 0x0214, 0x0216, 0x0386, 0x038c, 0x038e, 0x038f, 0x03da, 0x03dc, + 0x03de, 0x03e0, 0x03e2, 0x03e4, 0x03e6, 0x03e8, 0x03ea, 0x03ec, 0x03ee, + 0x0460, 0x0462, 0x0464, 0x0466, 0x0468, 0x046a, 0x046c, 0x046e, 0x0470, + 0x0472, 0x0474, 0x0476, 0x0478, 0x047a, 0x047c, 0x047e, 0x0480, 0x0490, + 0x0492, 0x0494, 0x0496, 0x0498, 0x049a, 0x049c, 0x049e, 0x04a0, 0x04a2, + 0x04a4, 0x04a6, 0x04a8, 0x04aa, 0x04ac, 0x04ae, 0x04b0, 0x04b2, 0x04b4, + 0x04b6, 0x04b8, 0x04ba, 0x04bc, 0x04be, 0x04c1, 0x04c3, 0x04c7, 0x04cb, + 0x04d0, 0x04d2, 0x04d4, 0x04d6, 0x04d8, 0x04da, 0x04dc, 0x04de, 0x04e0, + 0x04e2, 0x04e4, 0x04e6, 0x04e8, 0x04ea, 0x04ee, 0x04f0, 0x04f2, 0x04f4, + 0x04f8, 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, 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, 0x1f59, 0x1f5b, 0x1f5d, 0x1f5f, 0x1fbe, + 0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x2133 +}; + +#define NUM_UPPER_CHAR (sizeof(upperCharTable)/sizeof(chr)) + +static crange lowerRangeTable[] = { + {0x0061, 0x007a}, {0x00df, 0x00f6}, {0x00f8, 0x00ff}, {0x0199, 0x019b}, + {0x0250, 0x02a8}, {0x03ac, 0x03ce}, {0x03ef, 0x03f2}, {0x0430, 0x044f}, + {0x0451, 0x045c}, {0x0561, 0x0587}, {0x10d0, 0x10f6}, {0x1e95, 0x1e9b}, + {0x1f00, 0x1f07}, {0x1f10, 0x1f15}, {0x1f20, 0x1f27}, {0x1f30, 0x1f37}, + {0x1f40, 0x1f45}, {0x1f50, 0x1f57}, {0x1f60, 0x1f67}, {0x1f70, 0x1f7d}, + {0x1f80, 0x1f87}, {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7}, {0x1fb0, 0x1fb4}, + {0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7}, {0x1ff2, 0x1ff4}, {0xfb00, 0xfb06}, + {0xfb13, 0xfb17}, {0xff41, 0xff5a} +}; + +#define NUM_LOWER_RANGE (sizeof(lowerRangeTable)/sizeof(crange)) + +static chr lowerCharTable[] = { + 0x00aa, 0x00b5, 0x00ba, 0x0101, 0x0103, 0x0105, 0x0107, 0x0109, 0x010b, + 0x010d, 0x010f, 0x0111, 0x0113, 0x0115, 0x0117, 0x0119, 0x011b, 0x011d, + 0x011f, 0x0121, 0x0123, 0x0125, 0x0127, 0x0129, 0x012b, 0x012d, 0x012f, + 0x0131, 0x0133, 0x0135, 0x0138, 0x013a, 0x013c, 0x013e, 0x0140, 0x0142, + 0x0144, 0x0146, 0x0149, 0x014b, 0x014d, 0x014f, 0x0151, 0x0153, 0x0155, + 0x0157, 0x0159, 0x015b, 0x015d, 0x015f, 0x0161, 0x0163, 0x0165, 0x0167, + 0x0169, 0x016b, 0x016d, 0x016f, 0x0171, 0x0173, 0x0175, 0x0177, 0x017a, + 0x017c, 0x017e, 0x017f, 0x0180, 0x0183, 0x0185, 0x0188, 0x018c, 0x018d, + 0x0192, 0x0195, 0x019e, 0x01a1, 0x01a3, 0x01a5, 0x01a8, 0x01ab, 0x01ad, + 0x01b0, 0x01b4, 0x01b6, 0x01b9, 0x01ba, 0x01bd, 0x01c6, 0x01c9, 0x01cc, + 0x01ce, 0x01d0, 0x01d2, 0x01d4, 0x01d6, 0x01d8, 0x01da, 0x01dd, 0x01df, + 0x01e1, 0x01e3, 0x01e5, 0x01e7, 0x01e9, 0x01eb, 0x01ed, 0x01f0, 0x01f3, + 0x01f5, 0x01fb, 0x01fd, 0x01ff, 0x0201, 0x0203, 0x0205, 0x0207, 0x0209, + 0x020b, 0x020d, 0x020f, 0x0211, 0x0213, 0x0215, 0x0217, 0x0390, 0x03d0, + 0x03d1, 0x03d5, 0x03d6, 0x03e3, 0x03e5, 0x03e7, 0x03e9, 0x03eb, 0x03ed, + 0x045e, 0x045f, 0x0461, 0x0463, 0x0465, 0x0467, 0x0469, 0x046b, 0x046d, + 0x046f, 0x0471, 0x0473, 0x0475, 0x0477, 0x0479, 0x047b, 0x047d, 0x047f, + 0x0481, 0x0491, 0x0493, 0x0495, 0x0497, 0x0499, 0x049b, 0x049d, 0x049f, + 0x04a1, 0x04a3, 0x04a5, 0x04a7, 0x04a9, 0x04ab, 0x04ad, 0x04af, 0x04b1, + 0x04b3, 0x04b5, 0x04b7, 0x04b9, 0x04bb, 0x04bd, 0x04bf, 0x04c2, 0x04c4, + 0x04c8, 0x04cc, 0x04d1, 0x04d3, 0x04d5, 0x04d7, 0x04d9, 0x04db, 0x04dd, + 0x04df, 0x04e1, 0x04e3, 0x04e5, 0x04e7, 0x04e9, 0x04eb, 0x04ef, 0x04f1, + 0x04f3, 0x04f5, 0x04f9, 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, 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, 0x1fb6, 0x1fb7, 0x1fc2, 0x1fc3, + 0x1fc4, 0x1fc6, 0x1fc7, 0x1fd6, 0x1fd7, 0x1ff6, 0x1ff7, 0x207f, 0x210a, + 0x210e, 0x210f, 0x2113, 0x212e, 0x212f, 0x2134 +}; + +#define NUM_LOWER_CHAR (sizeof(lowerCharTable)/sizeof(chr)) + +/* + * The graph table includes the set of characters that are neither ISO control + * characters nor in the space table. + */ + +static crange graphTable[] = { + {0x0021, 0x007e}, {0x00a1, 0x1fff}, {0x2010, 0x2027}, {0x202f, 0x2069}, + {0x2070, 0x2fff}, {0x3001, 0xfefe}, {0xff00, 0xffff} +}; + +#define NUM_GRAPH (sizeof(graphTable)/sizeof(crange)) +#define CH NOCELT + +/* + - nmcces - how many distinct MCCEs are there? + ^ static int nmcces(struct vars *); + */ +static int +nmcces(v) +struct vars *v; +{ + return 0; +} + +/* + - nleaders - how many chrs can be first chrs of MCCEs? + ^ static int nleaders(struct vars *); + */ +static int +nleaders(v) +struct vars *v; +{ + return 0; +} + +/* + - allmcces - return a cvec with all the MCCEs of the locale + ^ static struct cvec *allmcces(struct vars *, struct cvec *); + */ +static struct cvec * +allmcces(v, cv) +struct vars *v; +struct cvec *cv; /* this is supposed to have enough room */ +{ + return clearcvec(cv); +} + +/* + - element - map collating-element name to celt + ^ static celt element(struct vars *, chr *, chr *); + */ +static celt +element(v, startp, endp) +struct vars *v; +chr *startp; /* points to start of name */ +chr *endp; /* points just past end of name */ +{ + struct cname *cn; + size_t len; + Tcl_DString ds; + 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(v, a, b, cases) +struct vars *v; +celt a; +celt b; /* 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, 0); + 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, 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(x, y) +celt x; +celt y; +{ + /* trivial because no MCCEs */ + 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(v, c, cases) +struct vars *v; +celt c; +int cases; /* all cases? */ +{ + struct cvec *cv; + + /* crude fake equivalence class for testing */ + if ((v->cflags®_FAKEEC) && c == 'x') { + cv = getcvec(v, 4, 0, 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, 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 *, chr *, chr *, int); + */ +static struct cvec * +cclass(v, startp, endp, cases) +struct vars *v; +chr *startp; /* where the name starts */ +chr *endp; /* just past the end of the name */ +int cases; /* case-independent? */ +{ + size_t len; + struct cvec *cv = NULL; + Tcl_DString ds; + char *np, **namePtr; + int i, index; + + /* + * The following arrays define the valid character class names. + */ + + static char *classNames[] = { + "alnum", "alpha", "blank", "cntrl", "digit", "graph", "lower", + "print", "punct", "space", "upper", "xdigit", NULL + }; + + enum classes { + CC_ALNUM, CC_ALPHA, 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); + + /* + * Remap lower and upper to alpha if the match is case insensitive. + */ + + if (cases && len == 5 && (strncmp("lower", np, 5) == 0 + || strncmp("upper", np, 5) == 0)) { + np = "alpha"; + } + + /* + * 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_DStringInit(&ds); + if (index == -1) { + ERR(REG_ECTYPE); + return NULL; + } + + /* + * Now compute the character class contents. + */ + + switch((enum classes) index) { + case CC_PRINT: + case CC_ALNUM: + cv = getcvec(v, 0, NUM_DIGIT + NUM_ALPHA, 0); + if (cv) { + for (i = 0; i < NUM_ALPHA; i++) { + addrange(cv, alphaTable[i].start, alphaTable[i].end); + } + for (i = 0; i < NUM_DIGIT; i++) { + addrange(cv, digitTable[i].start, digitTable[i].end); + } + } + break; + case CC_ALPHA: + cv = getcvec(v, 0, NUM_ALPHA, 0); + if (cv) { + for (i = 0; i < NUM_ALPHA; i++) { + addrange(cv, alphaTable[i].start, alphaTable[i].end); + } + } + break; + case CC_BLANK: + cv = getcvec(v, 2, 0, 0); + addchr(cv, '\t'); + addchr(cv, ' '); + break; + case CC_CNTRL: + cv = getcvec(v, 0, 2, 0); + addrange(cv, 0x0, 0x1f); + addrange(cv, 0x7f, 0x9f); + break; + case CC_DIGIT: + cv = getcvec(v, 0, NUM_DIGIT, 0); + if (cv) { + for (i = 0; i < NUM_DIGIT; i++) { + addrange(cv, digitTable[i].start, digitTable[i].end); + } + } + break; + case CC_PUNCT: + cv = getcvec(v, 0, NUM_PUNCT, 0); + if (cv) { + for (i = 0; i < NUM_PUNCT; i++) { + addrange(cv, punctTable[i].start, punctTable[i].end); + } + } + break; + case CC_XDIGIT: + cv = getcvec(v, 0, NUM_DIGIT+2, 0); + if (cv) { + for (i = 0; i < NUM_DIGIT; i++) { + addrange(cv, digitTable[i].start, digitTable[i].end); + } + addrange(cv, 'a', 'f'); + addrange(cv, 'A', 'F'); + } + break; + case CC_SPACE: + cv = getcvec(v, 0, NUM_SPACE, 0); + if (cv) { + for (i = 0; i < NUM_SPACE; i++) { + addrange(cv, spaceTable[i].start, spaceTable[i].end); + } + } + break; + case CC_LOWER: + cv = getcvec(v, NUM_LOWER_CHAR, NUM_LOWER_RANGE, 0); + if (cv) { + for (i = 0; i < NUM_LOWER_RANGE; i++) { + addrange(cv, lowerRangeTable[i].start, + lowerRangeTable[i].end); + } + for (i = 0; i < NUM_LOWER_CHAR; i++) { + addchr(cv, lowerCharTable[i]); + } + } + break; + case CC_UPPER: + cv = getcvec(v, NUM_UPPER_CHAR, NUM_UPPER_RANGE, 0); + if (cv) { + for (i = 0; i < NUM_UPPER_RANGE; i++) { + addrange(cv, upperRangeTable[i].start, + upperRangeTable[i].end); + } + for (i = 0; i < NUM_UPPER_CHAR; i++) { + addchr(cv, upperCharTable[i]); + } + } + break; + case CC_GRAPH: + cv = getcvec(v, 0, NUM_GRAPH, 0); + if (cv) { + for (i = 0; i < NUM_GRAPH; i++) { + addrange(cv, graphTable[i].start, graphTable[i].end); + } + } + break; + } + if (cv == NULL) { + ERR(REG_ESPACE); + } + return cv; +} + +/* + - allcases - supply cvec for all case counterparts of a chr (including itself) + * This is a shortcut, preferably an efficient one, for simple characters; + * messy cases are done via range(). + ^ static struct cvec *allcases(struct vars *, pchr); + */ +static struct cvec * +allcases(v, pc) +struct vars *v; +pchr pc; +{ + struct cvec *cv; + chr c = (chr)pc; + chr lc, uc, tc; + + lc = Tcl_UniCharToLower((chr)c); + uc = Tcl_UniCharToUpper((chr)c); + tc = Tcl_UniCharToTitle((chr)c); + + if (tc != uc) { + cv = getcvec(v, 3, 0, 0); + addchr(cv, tc); + } else { + cv = getcvec(v, 2, 0, 0); + } + addchr(cv, lc); + if (lc != uc) { + addchr(cv, uc); + } + return cv; +} + +/* + - cmp - chr-substring compare + * Backrefs need this. It should preferably be efficient. + * Note that it does not need to report anything except equal/unequal. + * Note also that the length is exact, and the comparison should not + * stop at embedded NULs! + ^ static int cmp(CONST chr *, CONST chr *, size_t); + */ +static int /* 0 for equal, nonzero for unequal */ +cmp(x, y, len) +CONST chr *x; +CONST chr *y; +size_t len; /* exact length of comparison */ +{ + return memcmp(VS(x), VS(y), len*sizeof(chr)); +} + +/* + - casecmp - case-independent chr-substring compare + * REG_ICASE backrefs need this. It should preferably be efficient. + * Note that it does not need to report anything except equal/unequal. + * Note also that the length is exact, and the comparison should not + * stop at embedded NULs! + ^ static int casecmp(CONST chr *, CONST chr *, size_t); + */ +static int /* 0 for equal, nonzero for unequal */ +casecmp(x, y, len) +CONST chr *x; +CONST chr *y; +size_t len; /* exact length of comparison */ +{ + size_t i; + CONST chr *xp; + CONST chr *yp; + + for (xp = x, yp = y, i = len; i > 0; i--) + if (Tcl_UniCharToLower(*xp++) != Tcl_UniCharToLower(*yp++)) + return 1; + return 0; +} ADDED generic/regc_nfa.c Index: generic/regc_nfa.c ================================================================== --- /dev/null +++ generic/regc_nfa.c @@ -0,0 +1,1528 @@ +/* + * NFA utilities. + * This file is #included by regcomp.c. + * + * 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)) + + +/* + - newnfa - set up an NFA + ^ static struct nfa *newnfa(struct vars *, struct colormap *, struct nfa *); + */ +static struct nfa * /* the NFA, or NULL */ +newnfa(v, cm, parent) +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) + 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->post = newfstate(nfa, '@'); /* number 0 */ + nfa->pre = newfstate(nfa, '>'); /* number 1 */ + nfa->parent = parent; + + 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(nfa) +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); +} + +/* + - newfstate - allocate an NFA state, with specified flag value + ^ static struct state *newfstate(struct nfa *, int flag); + */ +static struct state * /* NULL on error */ +newfstate(nfa, flag) +struct nfa *nfa; +int flag; +{ + struct state *s; + int i; + + if (nfa->free != NULL) { + s = nfa->free; + nfa->free = s->next; + } else { + s = (struct state *)MALLOC(sizeof(struct state)); + if (s == NULL) { + NERR(REG_ESPACE); + return NULL; + } + s->oas.next = NULL; + s->free = &s->oas.a[0]; + for (i = 0; i < ABSIZE; i++) { + s->oas.a[i].type = 0; + s->oas.a[i].freechain = &s->oas.a[i+1]; + } + s->oas.a[ABSIZE-1].freechain = NULL; + } + + assert(nfa->nstates >= 0); + s->no = nfa->nstates++; + s->flag = (char)flag; + 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; +} + +/* + - newstate - allocate an ordinary NFA state + ^ static struct state *newstate(struct nfa *); + */ +static struct state * /* NULL on error */ +newstate(nfa) +struct nfa *nfa; +{ + return newfstate(nfa, 0); +} + +/* + - dropstate - delete a state's inarcs and outarcs and free it + ^ static VOID dropstate(struct nfa *, struct state *); + */ +static VOID +dropstate(nfa, s) +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(nfa, s) +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(nfa, s) +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); + } + s->ins = NULL; + s->outs = NULL; + s->next = NULL; + FREE(s); +} + +/* + - newarc - set up a new arc within an NFA + ^ static VOID newarc(struct nfa *, int, pcolor, struct state *, + ^ struct state *); + */ +static VOID +newarc(nfa, t, co, from, to) +struct nfa *nfa; +int t; +pcolor co; +struct state *from; +struct state *to; +{ + struct arc *a; + + assert(from != NULL && to != NULL); + + /* check for duplicates */ + for (a = from->outs; a != NULL; a = a->outchain) + if (a->type == t && a->co == co && a->to == to) + return; + + 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. + * Not only is this easier, it has the very useful side effect that + * deleting the most-recently-added arc is the cheapest case rather + * than the most expensive one. + */ + a->inchain = to->ins; + to->ins = a; + a->outchain = from->outs; + from->outs = a; + + from->nouts++; + to->nins++; + + if (COLORED(a) && nfa->parent == NULL) + colorchain(nfa->cm, a); + + return; +} + +/* + - allocarc - allocate a new out-arc within a state + ^ static struct arc *allocarc(struct nfa *, struct state *); + */ +static struct arc * /* NULL for failure */ +allocarc(nfa, s) +struct nfa *nfa; +struct state *s; +{ + struct arc *a; + struct arcbatch *new; + int i; + + /* if none at hand, get more */ + if (s->free == NULL) { + new = (struct arcbatch *)MALLOC(sizeof(struct arcbatch)); + if (new == NULL) { + NERR(REG_ESPACE); + return NULL; + } + new->next = s->oas.next; + s->oas.next = new; + + for (i = 0; i < ABSIZE; i++) { + new->a[i].type = 0; + new->a[i].freechain = &new->a[i+1]; + } + new->a[ABSIZE-1].freechain = NULL; + s->free = &new->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(nfa, victim) +struct nfa *nfa; +struct arc *victim; +{ + struct state *from = victim->from; + struct state *to = victim->to; + struct arc *a; + + 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); + assert(from->outs != NULL); + a = from->outs; + if (a == victim) /* simple case: first in chain */ + from->outs = victim->outchain; + else { + for (; a != NULL && a->outchain != victim; a = a->outchain) + continue; + assert(a != NULL); + a->outchain = victim->outchain; + } + from->nouts--; + + /* take it off target's in-chain */ + assert(to != NULL); + assert(to->ins != NULL); + a = to->ins; + if (a == victim) /* simple case: first in chain */ + to->ins = victim->inchain; + else { + for (; a != NULL && a->inchain != victim; a = a->inchain) + continue; + assert(a != NULL); + a->inchain = victim->inchain; + } + to->nins--; + + /* clean up and place on free list */ + victim->type = 0; + victim->from = NULL; /* precautions... */ + victim->to = NULL; + victim->inchain = NULL; + victim->outchain = NULL; + victim->freechain = from->free; + from->free = victim; +} + +/* + - 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(s, type, co) +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(nfa, oa, from, to) +struct nfa *nfa; +struct arc *oa; +struct state *from; +struct state *to; +{ + newarc(nfa, oa->type, oa->co, from, to); +} + +/* + - 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 desire + * for duplicate suppression, which makes it easier to just make new + * ones to exploit the suppression built into newarc. + ^ static VOID moveins(struct nfa *, struct state *, struct state *); + */ +static VOID +moveins(nfa, old, new) +struct nfa *nfa; +struct state *old; +struct state *new; +{ + struct arc *a; + + assert(old != new); + + while ((a = old->ins) != NULL) { + cparc(nfa, a, a->from, new); + freearc(nfa, a); + } + assert(old->nins == 0); + assert(old->ins == NULL); +} + +/* + - copyins - copy all in arcs of a state to another state + ^ static VOID copyins(struct nfa *, struct state *, struct state *); + */ +static VOID +copyins(nfa, old, new) +struct nfa *nfa; +struct state *old; +struct state *new; +{ + struct arc *a; + + assert(old != new); + + for (a = old->ins; a != NULL; a = a->inchain) + cparc(nfa, a, a->from, new); +} + +/* + - moveouts - move all out arcs of a state to another state + ^ static VOID moveouts(struct nfa *, struct state *, struct state *); + */ +static VOID +moveouts(nfa, old, new) +struct nfa *nfa; +struct state *old; +struct state *new; +{ + struct arc *a; + + assert(old != new); + + while ((a = old->outs) != NULL) { + cparc(nfa, a, new, a->to); + freearc(nfa, a); + } +} + +/* + - copyouts - copy all out arcs of a state to another state + ^ static VOID copyouts(struct nfa *, struct state *, struct state *); + */ +static VOID +copyouts(nfa, old, new) +struct nfa *nfa; +struct state *old; +struct state *new; +{ + struct arc *a; + + assert(old != new); + + for (a = old->outs; a != NULL; a = a->outchain) + cparc(nfa, a, new, 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(nfa, old, from, to, type) +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(nfa, lp, rp) +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(nfa, leftend, s) +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(nfa, start, stop, from, to) +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); + /* 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(nfa, s, stmp) +struct nfa *nfa; +struct state *s; +struct state *stmp; /* s's duplicate, or NULL */ +{ + struct arc *a; + + if (s->tmp != NULL) + return; /* already done */ + + s->tmp = (stmp == NULL) ? newstate(nfa) : stmp; + if (s->tmp == NULL) { + assert(NISERR()); + return; + } + + for (a = s->outs; a != NULL && !NISERR(); a = a->outchain) { + duptraverse(nfa, a->to, (struct state *)NULL); + 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(nfa, s) +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(nfa) +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 int optimize(struct nfa *, FILE *); + */ +static int /* re_info bits */ +optimize(nfa, f) +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"); + 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 */ + return analyze(nfa); /* and analysis */ +} + +/* + - pullback - pull back constraints backward to (with luck) eliminate them + ^ static VOID pullback(struct nfa *, FILE *); + */ +static VOID +pullback(nfa, f) +struct nfa *nfa; +FILE *f; /* for debug output; NULL none */ +{ + struct state *s; + struct state *nexts; + struct arc *a; + struct arc *nexta; + 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; + for (a = s->outs; a != NULL && !NISERR(); a = nexta) { + nexta = a->outchain; + if (a->type == '^' || a->type == BEHIND) + if (pull(nfa, a)) + progress = 1; + assert(nexta == NULL || s->no != FREESTATE); + } + } + if (progress && f != NULL) + dumpnfa(nfa, f); + } while (progress && !NISERR()); + if (NISERR()) + return; + + 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 + * A significant property of this function is that it deletes at most + * one state -- the constraint's from state -- and only if the constraint + * was that state's last outarc. + ^ static int pull(struct nfa *, struct arc *); + */ +static int /* 0 couldn't, 1 could */ +pull(nfa, con) +struct nfa *nfa; +struct arc *con; +{ + struct state *from = con->from; + struct state *to = con->to; + struct arc *a; + struct arc *nexta; + struct state *s; + + if (from == to) { /* circular constraint is pointless */ + freearc(nfa, con); + return 1; + } + 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 */ + if (from->nouts > 1) { + s = newstate(nfa); + if (NISERR()) + return 0; + assert(to != from); /* con is not an inarc */ + copyins(nfa, from, s); /* duplicate inarcs */ + cparc(nfa, con, s, to); /* move constraint arc */ + freearc(nfa, con); + from = s; + con = from->outs; + } + assert(from->nouts == 1); + + /* propagate the constraint into the from state's inarcs */ + for (a = from->ins; a != NULL; 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 */ + s = newstate(nfa); + if (NISERR()) + return 0; + cparc(nfa, a, s, to); /* anticipate move */ + cparc(nfa, con, a->from, s); + if (NISERR()) + return 0; + freearc(nfa, a); + break; + default: + assert(NOTREACHED); + break; + } + } + + /* remaining inarcs, if any, incorporate the constraint */ + moveins(nfa, from, to); + dropstate(nfa, from); /* will free the constraint */ + return 1; +} + +/* + - pushfwd - push forward constraints forward to (with luck) eliminate them + ^ static VOID pushfwd(struct nfa *, FILE *); + */ +static VOID +pushfwd(nfa, f) +struct nfa *nfa; +FILE *f; /* for debug output; NULL none */ +{ + struct state *s; + struct state *nexts; + struct arc *a; + struct arc *nexta; + 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; + for (a = s->ins; a != NULL && !NISERR(); a = nexta) { + nexta = a->inchain; + if (a->type == '$' || a->type == AHEAD) + if (push(nfa, a)) + progress = 1; + assert(nexta == NULL || s->no != FREESTATE); + } + } + if (progress && f != NULL) + dumpnfa(nfa, f); + } while (progress && !NISERR()); + if (NISERR()) + return; + + 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 + * A significant property of this function is that it deletes at most + * one state -- the constraint's to state -- and only if the constraint + * was that state's last inarc. + ^ static int push(struct nfa *, struct arc *); + */ +static int /* 0 couldn't, 1 could */ +push(nfa, con) +struct nfa *nfa; +struct arc *con; +{ + struct state *from = con->from; + struct state *to = con->to; + struct arc *a; + struct arc *nexta; + struct state *s; + + if (to == from) { /* circular constraint is pointless */ + freearc(nfa, con); + return 1; + } + 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 */ + if (to->nins > 1) { + s = newstate(nfa); + if (NISERR()) + return 0; + copyouts(nfa, to, s); /* duplicate outarcs */ + cparc(nfa, con, from, s); /* move constraint */ + freearc(nfa, con); + to = s; + con = to->ins; + } + assert(to->nins == 1); + + /* propagate the constraint into the to state's outarcs */ + for (a = to->outs; a != NULL; 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 */ + s = newstate(nfa); + if (NISERR()) + return 0; + cparc(nfa, con, s, a->to); /* anticipate move */ + cparc(nfa, a, from, s); + if (NISERR()) + return 0; + freearc(nfa, a); + break; + default: + assert(NOTREACHED); + break; + } + } + + /* remaining outarcs, if any, incorporate the constraint */ + moveouts(nfa, to, from); + dropstate(nfa, to); /* will free the constraint */ + 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(con, a) +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(nfa, f) +struct nfa *nfa; +FILE *f; /* for debug output; NULL none */ +{ + struct state *s; + struct state *nexts; + struct arc *a; + struct arc *nexta; + int progress; + + /* find and eliminate empties until there are no more */ + do { + progress = 0; + for (s = nfa->states; s != NULL && !NISERR(); s = nexts) { + nexts = s->next; + for (a = s->outs; a != NULL && !NISERR(); a = nexta) { + nexta = a->outchain; + if (a->type == EMPTY && unempty(nfa, a)) + progress = 1; + assert(nexta == NULL || s->no != FREESTATE); + } + } + if (progress && f != NULL) + dumpnfa(nfa, f); + } while (progress && !NISERR()); +} + +/* + - unempty - optimize out an EMPTY arc, if possible + * Actually, as it stands this function always succeeds, but the return + * value is kept with an eye on possible future changes. + ^ static int unempty(struct nfa *, struct arc *); + */ +static int /* 0 couldn't, 1 could */ +unempty(nfa, a) +struct nfa *nfa; +struct arc *a; +{ + struct state *from = a->from; + struct state *to = a->to; + int usefrom; /* work on from, as opposed to to? */ + + assert(a->type == EMPTY); + assert(from != nfa->pre && to != nfa->post); + + if (from == to) { /* vacuous loop */ + freearc(nfa, a); + return 1; + } + + /* decide which end to work on */ + usefrom = 1; /* default: attack from */ + if (from->nouts > to->nins) + usefrom = 0; + else if (from->nouts == to->nins) { + /* decide on secondary issue: move/copy fewest arcs */ + if (from->nins > to->nouts) + usefrom = 0; + } + + freearc(nfa, a); + if (usefrom) { + if (from->nouts == 0) { + /* was the state's only outarc */ + moveins(nfa, from, to); + freestate(nfa, from); + } else + copyins(nfa, from, to); + } else { + if (to->nins == 0) { + /* was the state's only inarc */ + moveouts(nfa, to, from); + freestate(nfa, to); + } else + copyouts(nfa, to, from); + } + + return 1; +} + +/* + - cleanup - clean up NFA after optimizations + ^ static VOID cleanup(struct nfa *); + */ +static VOID +cleanup(nfa) +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, (struct state *)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(nfa, s, okay, mark) +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(nfa, s, okay, mark) +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 int analyze(struct nfa *); + */ +static int /* re_info bits to be ORed in */ +analyze(nfa) +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 - compact an NFA + ^ static VOID compact(struct nfa *, struct cnfa *); + */ +static VOID +compact(nfa, cnfa) +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 += 1 + s->nouts + 1; + /* 1 as a fake for flags, nouts for arcs, 1 as endmarker */ + } + + cnfa->states = (struct carc **)MALLOC(nstates * sizeof(struct carc *)); + cnfa->arcs = (struct carc *)MALLOC(narcs * sizeof(struct carc)); + if (cnfa->states == NULL || cnfa->arcs == NULL) { + 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->states[s->no] = ca; + ca->co = 0; /* clear and skip flags "arc" */ + 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: + assert(NOTREACHED); + break; + } + carcsort(first, ca-1); + 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->states[a->to->no]->co = 1; + cnfa->states[nfa->pre->no]->co = 1; +} + +/* + - carcsort - sort compacted-NFA arcs by color + * Really dumb algorithm, but if the list is long enough for that to matter, + * you're in real trouble anyway. + ^ static VOID carcsort(struct carc *, struct carc *); + */ +static VOID +carcsort(first, last) +struct carc *first; +struct carc *last; +{ + struct carc *p; + struct carc *q; + struct carc tmp; + + if (last - first <= 1) + return; + + for (p = first; p <= last; p++) + for (q = p; q <= last; q++) + if (p->co > q->co || + (p->co == q->co && p->to > q->to)) { + assert(p != q); + tmp = *p; + *p = *q; + *q = tmp; + } +} + +/* + - freecnfa - free a compacted NFA + ^ static VOID freecnfa(struct cnfa *); + */ +static VOID +freecnfa(cnfa) +struct cnfa *cnfa; +{ + assert(cnfa->nstates != 0); /* not empty already */ + cnfa->nstates = 0; + FREE(cnfa->states); + FREE(cnfa->arcs); +} + +/* + - dumpnfa - dump an NFA in human-readable form + ^ static VOID dumpnfa(struct nfa *, FILE *); + */ +static VOID +dumpnfa(nfa, f) +struct nfa *nfa; +FILE *f; +{ +#ifdef REG_DEBUG + struct state *s; + + 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); + if (nfa->parent == NULL) + dumpcolors(nfa->cm, f); + fflush(f); +#endif +} + +#ifdef REG_DEBUG /* subordinates of dumpnfa */ + +/* + - dumpstate - dump an NFA state in human-readable form + ^ static VOID dumpstate(struct state *, FILE *); + */ +static VOID +dumpstate(s, f) +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(s, f) +struct state *s; +FILE *f; +{ + int pos; + + assert(s->nouts > 0); + /* printing arcs in reverse order is usually clearer */ + pos = dumprarcs(s->outs, s, f, 1); + if (pos != 1) + fprintf(f, "\n"); +} + +/* + - dumprarcs - dump remaining outarcs, recursively, in reverse order + ^ static int dumprarcs(struct arc *, struct state *, FILE *, int); + */ +static int /* resulting print position */ +dumprarcs(a, s, f, pos) +struct arc *a; +struct state *s; +FILE *f; +int pos; /* initial print position */ +{ + if (a->outchain != NULL) + pos = dumprarcs(a->outchain, s, f, pos); + dumparc(a, s, f); + if (pos == 5) { + fprintf(f, "\n"); + pos = 1; + } else + pos++; + return pos; +} + +/* + - dumparc - dump one outarc in readable form, including prefixing tab + ^ static VOID dumparc(struct arc *, struct state *, FILE *); + */ +static VOID +dumparc(a, s, f) +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 /* ifdef REG_DEBUG */ + +/* + - dumpcnfa - dump a compacted NFA in human-readable form + ^ static VOID dumpcnfa(struct cnfa *, FILE *); + */ +static VOID +dumpcnfa(cnfa, f) +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->states[st], cnfa, f); + fflush(f); +#endif +} + +#ifdef REG_DEBUG /* subordinates of dumpcnfa */ + +/* + - dumpcstate - dump a compacted-NFA state in human-readable form + ^ static VOID dumpcstate(int, struct carc *, struct cnfa *, FILE *); + */ +static VOID +dumpcstate(st, ca, cnfa, f) +int st; +struct carc *ca; +struct cnfa *cnfa; +FILE *f; +{ + int i; + int pos; + + fprintf(f, "%d%s", st, (ca[0].co) ? ":" : "."); + pos = 1; + for (i = 1; ca[i].co != COLORLESS; i++) { + if (ca[i].co < cnfa->ncolors) + fprintf(f, "\t[%ld]->%d", (long)ca[i].co, ca[i].to); + else + fprintf(f, "\t:%ld:->%d", (long)ca[i].co-cnfa->ncolors, + ca[i].to); + if (pos == 5) { + fprintf(f, "\n"); + pos = 1; + } else + pos++; + } + if (i == 1 || pos != 1) + fprintf(f, "\n"); + fflush(f); +} + +#endif /* ifdef REG_DEBUG */ ADDED generic/regcomp.c Index: generic/regcomp.c ================================================================== --- /dev/null +++ generic/regcomp.c @@ -0,0 +1,2124 @@ +/* + * re_*comp and friends - compile REs + * This file #includes several others (see the bottom). + */ + +#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 _ANSI_ARGS_((regex_t *, CONST chr *, size_t, int)); +static VOID moresubs _ANSI_ARGS_((struct vars *, int)); +static int freev _ANSI_ARGS_((struct vars *, int)); +static VOID makescan _ANSI_ARGS_((struct vars *, struct nfa *)); +static struct subre *parse _ANSI_ARGS_((struct vars *, int, int, struct state *, struct state *)); +static struct subre *parsebranch _ANSI_ARGS_((struct vars *, int, int, struct state *, struct state *, int)); +static VOID parseqatom _ANSI_ARGS_((struct vars *, int, int, struct state *, struct state *, struct subre *)); +static VOID nonword _ANSI_ARGS_((struct vars *, int, struct state *, struct state *)); +static VOID word _ANSI_ARGS_((struct vars *, int, struct state *, struct state *)); +static int scannum _ANSI_ARGS_((struct vars *)); +static VOID repeat _ANSI_ARGS_((struct vars *, struct state *, struct state *, int, int)); +static VOID bracket _ANSI_ARGS_((struct vars *, struct state *, struct state *)); +static VOID cbracket _ANSI_ARGS_((struct vars *, struct state *, struct state *)); +static VOID brackpart _ANSI_ARGS_((struct vars *, struct state *, struct state *)); +static chr *scanplain _ANSI_ARGS_((struct vars *)); +static VOID leaders _ANSI_ARGS_((struct vars *, struct cvec *)); +static VOID onechr _ANSI_ARGS_((struct vars *, pchr, struct state *, struct state *)); +static VOID dovec _ANSI_ARGS_((struct vars *, struct cvec *, struct state *, struct state *)); +static celt nextleader _ANSI_ARGS_((struct vars *, pchr, pchr)); +static VOID wordchrs _ANSI_ARGS_((struct vars *)); +static struct subre *subre _ANSI_ARGS_((struct vars *, int, int, struct state *, struct state *)); +static VOID freesubre _ANSI_ARGS_((struct vars *, struct subre *)); +static VOID freesrnode _ANSI_ARGS_((struct vars *, struct subre *)); +static VOID optst _ANSI_ARGS_((struct vars *, struct subre *)); +static int numst _ANSI_ARGS_((struct subre *, int)); +static VOID markst _ANSI_ARGS_((struct subre *)); +static VOID cleanst _ANSI_ARGS_((struct vars *)); +static int nfatree _ANSI_ARGS_((struct vars *, struct subre *, FILE *)); +static int nfanode _ANSI_ARGS_((struct vars *, struct subre *, FILE *)); +static int newlacon _ANSI_ARGS_((struct vars *, struct state *, struct state *, int)); +static VOID freelacons _ANSI_ARGS_((struct subre *, int)); +static VOID rfree _ANSI_ARGS_((regex_t *)); +static VOID dump _ANSI_ARGS_((regex_t *, FILE *)); +static VOID dumpst _ANSI_ARGS_((struct subre *, FILE *, int)); +static VOID stdump _ANSI_ARGS_((struct subre *, FILE *, int, int)); +/* === regc_lex.c === */ +static VOID lexstart _ANSI_ARGS_((struct vars *)); +static VOID prefixes _ANSI_ARGS_((struct vars *)); +static VOID lexnest _ANSI_ARGS_((struct vars *, chr *, chr *)); +static VOID lexword _ANSI_ARGS_((struct vars *)); +static int next _ANSI_ARGS_((struct vars *)); +static int lexescape _ANSI_ARGS_((struct vars *)); +static chr lexdigits _ANSI_ARGS_((struct vars *, int, int, int)); +static int brenext _ANSI_ARGS_((struct vars *, pchr)); +static VOID skip _ANSI_ARGS_((struct vars *)); +static chr newline _ANSI_ARGS_((NOPARMS)); +static chr chrnamed _ANSI_ARGS_((struct vars *, chr *, chr *, pchr)); +/* === regc_color.c === */ +static VOID initcm _ANSI_ARGS_((struct vars *, struct colormap *)); +static VOID freecm _ANSI_ARGS_((struct colormap *)); +static VOID cmtreefree _ANSI_ARGS_((struct colormap *, union tree *, int)); +static color setcolor _ANSI_ARGS_((struct colormap *, pchr, pcolor)); +static color maxcolor _ANSI_ARGS_((struct colormap *)); +static color newcolor _ANSI_ARGS_((struct colormap *)); +static VOID freecolor _ANSI_ARGS_((struct colormap *, pcolor)); +static color pseudocolor _ANSI_ARGS_((struct colormap *)); +static color subcolor _ANSI_ARGS_((struct colormap *, pchr c)); +static color newsub _ANSI_ARGS_((struct colormap *, pcolor)); +static VOID subrange _ANSI_ARGS_((struct vars *, pchr, pchr, struct state *, struct state *)); +static VOID subblock _ANSI_ARGS_((struct vars *, pchr, struct state *, struct state *)); +static VOID okcolors _ANSI_ARGS_((struct nfa *, struct colormap *)); +static VOID colorchain _ANSI_ARGS_((struct colormap *, struct arc *)); +static VOID uncolorchain _ANSI_ARGS_((struct colormap *, struct arc *)); +#if 0 +static int singleton _ANSI_ARGS_((struct colormap *, pchr c)); +#endif +static VOID rainbow _ANSI_ARGS_((struct nfa *, struct colormap *, int, pcolor, struct state *, struct state *)); +static VOID colorcomplement _ANSI_ARGS_((struct nfa *, struct colormap *, int, struct state *, struct state *, struct state *)); +#ifdef REG_DEBUG +static VOID dumpcolors _ANSI_ARGS_((struct colormap *, FILE *)); +static VOID fillcheck _ANSI_ARGS_((struct colormap *, union tree *, int, FILE *)); +static VOID dumpchr _ANSI_ARGS_((pchr, FILE *)); +#endif +/* === regc_nfa.c === */ +static struct nfa *newnfa _ANSI_ARGS_((struct vars *, struct colormap *, struct nfa *)); +static VOID freenfa _ANSI_ARGS_((struct nfa *)); +static struct state *newfstate _ANSI_ARGS_((struct nfa *, int flag)); +static struct state *newstate _ANSI_ARGS_((struct nfa *)); +static VOID dropstate _ANSI_ARGS_((struct nfa *, struct state *)); +static VOID freestate _ANSI_ARGS_((struct nfa *, struct state *)); +static VOID destroystate _ANSI_ARGS_((struct nfa *, struct state *)); +static VOID newarc _ANSI_ARGS_((struct nfa *, int, pcolor, struct state *, struct state *)); +static struct arc *allocarc _ANSI_ARGS_((struct nfa *, struct state *)); +static VOID freearc _ANSI_ARGS_((struct nfa *, struct arc *)); +static struct arc *findarc _ANSI_ARGS_((struct state *, int, pcolor)); +static VOID cparc _ANSI_ARGS_((struct nfa *, struct arc *, struct state *, struct state *)); +static VOID moveins _ANSI_ARGS_((struct nfa *, struct state *, struct state *)); +static VOID copyins _ANSI_ARGS_((struct nfa *, struct state *, struct state *)); +static VOID moveouts _ANSI_ARGS_((struct nfa *, struct state *, struct state *)); +static VOID copyouts _ANSI_ARGS_((struct nfa *, struct state *, struct state *)); +static VOID cloneouts _ANSI_ARGS_((struct nfa *, struct state *, struct state *, struct state *, int)); +static VOID delsub _ANSI_ARGS_((struct nfa *, struct state *, struct state *)); +static VOID deltraverse _ANSI_ARGS_((struct nfa *, struct state *, struct state *)); +static VOID dupnfa _ANSI_ARGS_((struct nfa *, struct state *, struct state *, struct state *, struct state *)); +static VOID duptraverse _ANSI_ARGS_((struct nfa *, struct state *, struct state *)); +static VOID cleartraverse _ANSI_ARGS_((struct nfa *, struct state *)); +static VOID specialcolors _ANSI_ARGS_((struct nfa *)); +static int optimize _ANSI_ARGS_((struct nfa *, FILE *)); +static VOID pullback _ANSI_ARGS_((struct nfa *, FILE *)); +static int pull _ANSI_ARGS_((struct nfa *, struct arc *)); +static VOID pushfwd _ANSI_ARGS_((struct nfa *, FILE *)); +static int push _ANSI_ARGS_((struct nfa *, struct arc *)); +#define INCOMPATIBLE 1 /* destroys arc */ +#define SATISFIED 2 /* constraint satisfied */ +#define COMPATIBLE 3 /* compatible but not satisfied yet */ +static int combine _ANSI_ARGS_((struct arc *, struct arc *)); +static VOID fixempties _ANSI_ARGS_((struct nfa *, FILE *)); +static int unempty _ANSI_ARGS_((struct nfa *, struct arc *)); +static VOID cleanup _ANSI_ARGS_((struct nfa *)); +static VOID markreachable _ANSI_ARGS_((struct nfa *, struct state *, struct state *, struct state *)); +static VOID markcanreach _ANSI_ARGS_((struct nfa *, struct state *, struct state *, struct state *)); +static int analyze _ANSI_ARGS_((struct nfa *)); +static VOID compact _ANSI_ARGS_((struct nfa *, struct cnfa *)); +static VOID carcsort _ANSI_ARGS_((struct carc *, struct carc *)); +static VOID freecnfa _ANSI_ARGS_((struct cnfa *)); +static VOID dumpnfa _ANSI_ARGS_((struct nfa *, FILE *)); +#ifdef REG_DEBUG +static VOID dumpstate _ANSI_ARGS_((struct state *, FILE *)); +static VOID dumparcs _ANSI_ARGS_((struct state *, FILE *)); +static int dumprarcs _ANSI_ARGS_((struct arc *, struct state *, FILE *, int)); +static VOID dumparc _ANSI_ARGS_((struct arc *, struct state *, FILE *)); +#endif +static VOID dumpcnfa _ANSI_ARGS_((struct cnfa *, FILE *)); +#ifdef REG_DEBUG +static VOID dumpcstate _ANSI_ARGS_((int, struct carc *, struct cnfa *, FILE *)); +#endif +/* === regc_cvec.c === */ +static struct cvec *newcvec _ANSI_ARGS_((int, int, int)); +static struct cvec *clearcvec _ANSI_ARGS_((struct cvec *)); +static VOID addchr _ANSI_ARGS_((struct cvec *, pchr)); +static VOID addrange _ANSI_ARGS_((struct cvec *, pchr, pchr)); +#ifdef USE_MCCE +static VOID addmcce _ANSI_ARGS_((struct cvec *, chr *, chr *)); +#endif +static int haschr _ANSI_ARGS_((struct cvec *, pchr)); +static struct cvec *getcvec _ANSI_ARGS_((struct vars *, int, int, int)); +static VOID freecvec _ANSI_ARGS_((struct cvec *)); +/* === regc_locale.c === */ +static int nmcces _ANSI_ARGS_((struct vars *)); +static int nleaders _ANSI_ARGS_((struct vars *)); +static struct cvec *allmcces _ANSI_ARGS_((struct vars *, struct cvec *)); +static celt element _ANSI_ARGS_((struct vars *, chr *, chr *)); +static struct cvec *range _ANSI_ARGS_((struct vars *, celt, celt, int)); +static int before _ANSI_ARGS_((celt, celt)); +static struct cvec *eclass _ANSI_ARGS_((struct vars *, celt, int)); +static struct cvec *cclass _ANSI_ARGS_((struct vars *, chr *, chr *, int)); +static struct cvec *allcases _ANSI_ARGS_((struct vars *, pchr)); +static int cmp _ANSI_ARGS_((CONST chr *, CONST chr *, size_t)); +static int casecmp _ANSI_ARGS_((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; + chr *now; /* scan pointer into string */ + chr *stop; /* end of string */ + chr *savenow; /* saved now and stop for "subroutine call" */ + 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 */ + struct cvec *cv; /* interface cvec */ + struct cvec *cv2; /* utility cvec */ + struct cvec *mcces; /* collating-element information */ +# define ISCELEADER(v,c) (v->mcces != NULL && haschr(v->mcces, (c))) + struct state *mccepbegin; /* in nfa, start of MCCE prototypes */ + struct state *mccepend; /* in nfa, end of MCCE prototypes */ + struct subre *lacons; /* lookahead-constraint vector */ + int nlacons; /* size of lacons */ + int usedshorter; /* used short-preferring quantifiers */ + int unmatchable; /* can never match */ +}; + +/* 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) ((c) ? 0 : ERR(e)) /* if condition false, error */ +#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 struct fns functions = { + rfree, /* regfree insides */ +}; + + + +/* + - compile - compile regular expression + ^ int compile(regex_t *, CONST chr *, size_t, int); + */ +int +compile(re, string, len, flags) +regex_t *re; +CONST chr *string; +size_t len; +int flags; +{ + struct vars var; + struct vars *v = &var; + struct guts *g; + int i; + size_t j; + FILE *debug = (flags®_PROGRESS) ? stdout : (FILE *)NULL; +# define CNOERR() { if (ISERR()) return freev(v, v->err); } + + /* sanity checks */ + + if (re == NULL || string == NULL) + return REG_INVARG; + if ((flags®_QUOTE) && + (flags&(REG_ADVANCED|REG_EXPANDED|REG_NEWLINE))) + return REG_INVARG; + if (!(flags®_EXTENDED) && (flags®_ADVF)) + return REG_INVARG; + + /* initial setup (after which freev() is callable) */ + v->re = re; + v->now = (chr *)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->mcces = NULL; + v->lacons = NULL; + v->nlacons = 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, (struct nfa *)NULL); + CNOERR(); + v->cv = newcvec(100, 20, 10); + if (v->cv == NULL) + return freev(v, REG_ESPACE); + i = nmcces(v); + if (i > 0) { + v->mcces = newcvec(nleaders(v), 0, i); + CNOERR(); + v->mcces = allmcces(v, v->mcces); + leaders(v, v->mcces); + } + CNOERR(); + + /* 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) { + dumpnfa(v->nfa, debug); + dumpst(v->tree, debug, 1); + } + v->usedshorter = 0; + v->unmatchable = 0; + optst(v, v->tree); + v->ntree = numst(v->tree, 1); + markst(v->tree); + cleanst(v); + if (debug != NULL) { + fprintf(debug, "-->\n"); + dumpst(v->tree, debug, 1); + } + + /* build compacted NFAs for tree, lacons, fast search */ + re->re_info |= nfatree(v, v->tree, debug); + if (debug != NULL) { + fprintf(debug, "---->\n"); + dumpst(v->tree, debug, 1); + } + CNOERR(); + if (re->re_info®_UIMPOSSIBLE) + v->unmatchable = 1; + assert(v->nlacons == 0 || v->lacons != NULL); + for (i = 1; i < v->nlacons; i++) + nfanode(v, &v->lacons[i], debug); + CNOERR(); + (DISCARD)optimize(v->nfa, debug); + CNOERR(); + makescan(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; + g->usedshorter = v->usedshorter; + g->unmatchable = v->unmatchable; + + 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(v, wanted) +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(VS(p), VS(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(v, err) +struct vars *v; +int err; +{ + 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->mcces != NULL) + freecvec(v->mcces); + if (v->lacons != NULL) + freelacons(v->lacons, v->nlacons); + ERR(err); /* nop if err==0 */ + + return v->err; +} + +/* + - makescan - turn an NFA into a fast-scan NFA (implicit prepend of .*?) + * NFA must have been optimize()d already. + ^ static VOID makescan(struct vars *, struct nfa *); + */ +static VOID +makescan(v, nfa) +struct vars *v; +struct nfa *nfa; +{ + struct arc *a; + struct arc *b; + struct state *pre = nfa->pre; + struct state *s; + struct state *s2; + struct state *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 \Z* 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; + if (b != NULL) { /* must be split */ + s->tmp = slist; + slist = s; + } + } + + /* do the splits */ + for (s = slist; s != NULL; s = s2) { + s2 = newstate(nfa); + copyouts(nfa, s, s2); + 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->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(v, stopper, type, init, final) +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; /* scaffolding for branch */ + struct state *right; + 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 it */ + 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(v, stopper, type, left, right, partial) +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); + } + + 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(v, stopper, type, lp, rp, top) +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; + break; + case '$': + ARCV('$', 1); + if (v->cflags®_NLANCH) + ARCV(AHEAD, v->nlcolor); + NEXT(); + return; + break; + case SBEGIN: + ARCV('^', 1); /* BOL */ + ARCV('^', 0); /* or BOS */ + NEXT(); + return; + break; + case SEND: + ARCV('$', 1); /* EOL */ + ARCV('$', 0); /* or EOS */ + NEXT(); + return; + break; + case '<': + wordchrs(v); /* does NEXT() */ + s = newstate(v->nfa); + NOERR(); + nonword(v, BEHIND, lp, s); + word(v, AHEAD, s, rp); + return; + break; + case '>': + wordchrs(v); /* does NEXT() */ + s = newstate(v->nfa); + NOERR(); + word(v, BEHIND, lp, s); + nonword(v, AHEAD, s, rp); + return; + break; + 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; + break; + 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; + break; + 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; + break; + /* then errors, to get them out of the way */ + case '*': + case '+': + case '?': + case '{': + ERR(REG_BADRPT); + return; + break; + default: + ERR(REG_ASSERT); + return; + break; + /* 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); + 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 = INFINITY; + qprefer = (v->nextvalue) ? LONGER : SHORTER; + NEXT(); + break; + case '+': + m = 1; + n = INFINITY; + 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 = INFINITY; + 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 + * + * ---> [s] ---prefix---> [begin] ---atom---> [end] ----rest---> [rp] + * / / + * [lp] ----> [s2] ----bypass--------------------- + * + * where bypass is an empty, and prefix is some repetitions of atom + */ + 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); /* and spots for prefix and bypass */ + s2 = newstate(v->nfa); + NOERR(); + EMPTYARC(lp, s); + EMPTYARC(lp, s2); + NOERR(); + + /* break remaining subRE into x{...} and what follows */ + t = subre(v, '.', COMBINE(qprefer, atom->flags), lp, rp); + 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); + 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; first, turn x{0,...} into x{1,...}|empty */ + if (m == 0) { + EMPTYARC(s2, atom->end); /* the bypass */ + assert(PREF(qprefer) != 0); + f = COMBINE(qprefer, atom->flags); + t = subre(v, '|', f, lp, atom->end); + NOERR(); + t->left = atom; + t->right = subre(v, '|', PREF(f), s2, atom->end); + NOERR(); + t->right->left = subre(v, '=', 0, s2, atom->end); + NOERR(); + *atomp = t; + atomp = &t->left; + m = 1; + } + + /* deal with the rest of the quantifier */ + 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); + } else if (m == 1 && n == 1) { + /* no/vacuous quantifier: done */ + EMPTYARC(s, atom->begin); /* empty prefix */ + } else { + /* turn x{m,n} into x{m-1,n-1}x, with capturing */ + /* parens in only second x */ + dupnfa(v->nfa, atom->begin, atom->end, s, atom->begin); + assert(m >= 1 && m != INFINITY && n >= 1); + repeat(v, s, atom->begin, m-1, (n == INFINITY) ? 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; + } + + /* and finally, look after that postponed recursion */ + t = top->right; + if (!(SEE('|') || SEE(stopper) || SEE(EOS))) + t->right = parsebranch(v, stopper, type, atom->end, rp, 1); + else { + EMPTYARC(atom->end, rp); + t->right = subre(v, '=', 0, atom->end, rp); + } + 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(v, dir, lp, rp) +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(v, dir, lp, rp) +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(v) +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 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(v, lp, rp, m, n) +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) == INFINITY) ? INF : (((x) > 1) ? SOME : (x)) ) + CONST int rm = REDUCE(m); + CONST int rn = REDUCE(n); + struct state *s; + struct state *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(v, lp, rp) +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(v, lp, rp) +struct vars *v; +struct state *lp; +struct state *rp; +{ + struct state *left = newstate(v->nfa); + struct state *right = newstate(v->nfa); + struct state *s; + struct arc *a; /* arc from lp */ + struct arc *ba; /* arc from left, from bracket() */ + struct arc *pa; /* MCCE-prototype arc */ + color co; + chr *p; + int i; + + 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 */ + colorcomplement(v->nfa, v->cm, PLAIN, left, lp, rp); + NOERR(); + if (v->mcces == NULL) { /* no MCCEs -- we're done */ + dropstate(v->nfa, left); + assert(right->nins == 0); + freestate(v->nfa, right); + return; + } + + /* but complementing gets messy in the presence of MCCEs... */ + NOTE(REG_ULOCALE); + for (p = v->mcces->chrs, i = v->mcces->nchrs; i > 0; p++, i--) { + co = GETCOLOR(v->cm, *p); + a = findarc(lp, PLAIN, co); + ba = findarc(left, PLAIN, co); + if (ba == NULL) { + assert(a != NULL); + freearc(v->nfa, a); + } else { + assert(a == NULL); + } + s = newstate(v->nfa); + NOERR(); + newarc(v->nfa, PLAIN, co, lp, s); + NOERR(); + pa = findarc(v->mccepbegin, PLAIN, co); + assert(pa != NULL); + if (ba == NULL) { /* easy case, need all of them */ + cloneouts(v->nfa, pa->to, s, rp, PLAIN); + newarc(v->nfa, '$', 1, s, rp); + newarc(v->nfa, '$', 0, s, rp); + colorcomplement(v->nfa, v->cm, AHEAD, pa->to, s, rp); + } else { /* must be selective */ + if (findarc(ba->to, '$', 1) == NULL) { + newarc(v->nfa, '$', 1, s, rp); + newarc(v->nfa, '$', 0, s, rp); + colorcomplement(v->nfa, v->cm, AHEAD, pa->to, + s, rp); + } + for (pa = pa->to->outs; pa != NULL; pa = pa->outchain) + if (findarc(ba->to, PLAIN, pa->co) == NULL) + newarc(v->nfa, PLAIN, pa->co, s, rp); + if (s->nouts == 0) /* limit of selectivity: none */ + dropstate(v->nfa, s); /* frees arc too */ + } + NOERR(); + } + + delsub(v->nfa, left, right); + assert(left->nouts == 0); + freestate(v->nfa, left); + assert(right->nins == 0); + freestate(v->nfa, right); +} + +/* + - brackpart - handle one item (or range) within a bracket expression + ^ static VOID brackpart(struct vars *, struct state *, struct state *); + */ +static VOID +brackpart(v, lp, rp) +struct vars *v; +struct state *lp; +struct state *rp; +{ + celt startc; + celt endc; + struct cvec *cv; + chr *startp; + chr *endp; + chr c[1]; + + /* 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[0] = v->nextvalue; + NEXT(); + /* shortcut for ordinary chr (not range, not MCCE leader) */ + if (!SEE(RANGE) && !ISCELEADER(v, c[0])) { + onechr(v, c[0], 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[0] = 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 chr *scanplain(struct vars *); + */ +static chr * /* just after end of sequence */ +scanplain(v) +struct vars *v; +{ + 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; +} + +/* + - leaders - process a cvec of collating elements to also include leaders + * Also gives all characters involved their own colors, which is almost + * certainly necessary, and sets up little disconnected subNFA. + ^ static VOID leaders(struct vars *, struct cvec *); + */ +static VOID +leaders(v, cv) +struct vars *v; +struct cvec *cv; +{ + int mcce; + chr *p; + chr leader; + struct state *s; + struct arc *a; + + v->mccepbegin = newstate(v->nfa); + v->mccepend = newstate(v->nfa); + NOERR(); + + for (mcce = 0; mcce < cv->nmcces; mcce++) { + p = cv->mcces[mcce]; + leader = *p; + if (!haschr(cv, leader)) { + addchr(cv, leader); + s = newstate(v->nfa); + newarc(v->nfa, PLAIN, subcolor(v->cm, leader), + v->mccepbegin, s); + okcolors(v->nfa, v->cm); + } else { + a = findarc(v->mccepbegin, PLAIN, + GETCOLOR(v->cm, leader)); + assert(a != NULL); + s = a->to; + assert(s != v->mccepend); + } + p++; + assert(*p != 0 && *(p+1) == 0); /* only 2-char MCCEs for now */ + newarc(v->nfa, PLAIN, subcolor(v->cm, *p), s, v->mccepend); + okcolors(v->nfa, v->cm); + } +} + +/* + - 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(v, c, lp, rp) +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 + * This one has to handle the messy cases, like MCCEs and MCCE leaders. + ^ static VOID dovec(struct vars *, struct cvec *, struct state *, + ^ struct state *); + */ +static VOID +dovec(v, cv, lp, rp) +struct vars *v; +struct cvec *cv; +struct state *lp; +struct state *rp; +{ + chr ch, from, to; + celt ce; + chr *p; + int i; + color co; + struct cvec *leads; + struct arc *a; + struct arc *pa; /* arc in prototype */ + struct state *s; + struct state *ps; /* state in prototype */ + + /* need a place to store leaders, if any */ + if (nmcces(v) > 0) { + assert(v->mcces != NULL); + if (v->cv2 == NULL || v->cv2->nchrs < v->mcces->nchrs) { + if (v->cv2 != NULL) + free(v->cv2); + v->cv2 = newcvec(v->mcces->nchrs, 0, v->mcces->nmcces); + NOERR(); + leads = v->cv2; + } else + leads = clearcvec(v->cv2); + } else + leads = NULL; + + /* first, get the ordinary characters out of the way */ + for (p = cv->chrs, i = cv->nchrs; i > 0; p++, i--) { + ch = *p; + if (!ISCELEADER(v, ch)) + newarc(v->nfa, PLAIN, subcolor(v->cm, ch), lp, rp); + else { + assert(singleton(v->cm, ch)); + assert(leads != NULL); + if (!haschr(leads, ch)) + addchr(leads, ch); + } + } + + /* and the ranges */ + for (p = cv->ranges, i = cv->nranges; i > 0; p += 2, i--) { + from = *p; + to = *(p+1); + while (from <= to && (ce = nextleader(v, from, to)) != NOCELT) { + if (from < ce) + subrange(v, from, ce - 1, lp, rp); + assert(singleton(v->cm, ce)); + assert(leads != NULL); + if (!haschr(leads, ce)) + addchr(leads, ce); + from = ce + 1; + } + if (from <= to) + subrange(v, from, to, lp, rp); + } + + if ((leads == NULL || leads->nchrs == 0) && cv->nmcces == 0) + return; + + /* deal with the MCCE leaders */ + NOTE(REG_ULOCALE); + for (p = leads->chrs, i = leads->nchrs; i > 0; p++, i--) { + co = GETCOLOR(v->cm, *p); + a = findarc(lp, PLAIN, co); + if (a != NULL) + s = a->to; + else { + s = newstate(v->nfa); + NOERR(); + newarc(v->nfa, PLAIN, co, lp, s); + NOERR(); + } + pa = findarc(v->mccepbegin, PLAIN, co); + assert(pa != NULL); + ps = pa->to; + newarc(v->nfa, '$', 1, s, rp); + newarc(v->nfa, '$', 0, s, rp); + colorcomplement(v->nfa, v->cm, AHEAD, ps, s, rp); + NOERR(); + } + + /* and the MCCEs */ + for (i = 0; i < cv->nmcces; i++) { + p = cv->mcces[i]; + assert(singleton(v->cm, *p)); + ch = *p++; + co = GETCOLOR(v->cm, ch); + a = findarc(lp, PLAIN, co); + if (a != NULL) + s = a->to; + else { + s = newstate(v->nfa); + NOERR(); + newarc(v->nfa, PLAIN, co, lp, s); + NOERR(); + } + assert(*p != 0); /* at least two chars */ + assert(singleton(v->cm, *p)); + ch = *p++; + co = GETCOLOR(v->cm, ch); + assert(*p == 0); /* and only two, for now */ + newarc(v->nfa, PLAIN, co, s, rp); + NOERR(); + } +} + +/* + - nextleader - find next MCCE leader within range + ^ static celt nextleader(struct vars *, pchr, pchr); + */ +static celt /* NOCELT means none */ +nextleader(v, from, to) +struct vars *v; +pchr from; +pchr to; +{ + int i; + chr *p; + chr ch; + celt it = NOCELT; + + if (v->mcces == NULL) + return it; + + for (i = v->mcces->nchrs, p = v->mcces->chrs; i > 0; i--, p++) { + ch = *p; + if (from <= ch && ch <= to) + if (it == NOCELT || ch < it) + it = ch; + } + return it; +} + +/* + - 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(v) +struct vars *v; +{ + struct state *left; + struct state *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(v, op, flags, begin, end) +struct vars *v; +int op; +int flags; +struct state *begin; +struct state *end; +{ + struct subre *ret; + + 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->retry = 0; + 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(v, sr) +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(v, sr) +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) { + 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(v, t) +struct vars *v; +struct subre *t; +{ + if (t == NULL) + return; + + /* preference cleanup and analysis */ + if (t->flags&SHORTER) + v->usedshorter = 1; + + /* recurse through children */ + if (t->left != NULL) + optst(v, t->left); + if (t->right != NULL) + optst(v, t->right); +} + +/* + - numst - number tree nodes (assigning retry indexes) + ^ static int numst(struct subre *, int); + */ +static int /* next number */ +numst(t, start) +struct subre *t; +int start; /* starting point for subtree numbers */ +{ + int i; + + assert(t != NULL); + + i = start; + t->retry = (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 + ^ static VOID markst(struct subre *); + */ +static VOID +markst(t) +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(v) +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 int nfatree(struct vars *, struct subre *, FILE *); + */ +static int /* optimize results from top node */ +nfatree(v, t, f) +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 int nfanode(struct vars *, struct subre *, FILE *); + */ +static int /* optimize results */ +nfanode(v, t, f) +struct vars *v; +struct subre *t; +FILE *f; /* for debug output */ +{ + struct nfa *nfa; + int ret = 0; + + assert(t->begin != NULL); + + 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(v, begin, end, pos) +struct vars *v; +struct state *begin; +struct state *end; +int pos; +{ + int n; + struct subre *sub; + + if (v->nlacons == 0) { + v->lacons = (struct subre *)MALLOC(2 * sizeof(struct subre)); + n = 1; /* skip 0th */ + v->nlacons = 2; + } else { + v->lacons = (struct subre *)REALLOC(v->lacons, + (v->nlacons+1)*sizeof(struct subre)); + n = v->nlacons++; + } + if (v->lacons == NULL) { + ERR(REG_ESPACE); + return 0; + } + 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(subs, n) +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(re) +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; + g->magic = 0; + freecm(&g->cmap); + if (g->tree != NULL) + freesubre((struct vars *)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(re, f) +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, "nsub %d, info 0%o, csize %d, ntree %d, usedshort %d\n", + re->re_nsub, re->re_info, re->re_csize, g->ntree, + g->usedshorter); + + dumpcolors(&g->cmap, f); + if (!NULLCNFA(g->search)) { + printf("search:\n"); + dumpcnfa(&g->search, f); + } + for (i = 1; i < g->nlacons; i++) { + fprintf(f, "la%d (%s):\n", i, + (g->lacons[i].subno) ? "positive" : "negative"); + dumpcnfa(&g->lacons[i].cnfa, f); + } + dumpst(g->tree, f, 0); +#endif +} + +/* + - dumpst - dump a subRE tree + ^ static VOID dumpst(struct subre *, FILE *, int); + */ +static VOID +dumpst(t, f, nfapresent) +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, 0); + fflush(f); +} + +/* + - stdump - recursive guts of dumpst + ^ static VOID stdump(struct subre *, FILE *, int, int); + */ +static VOID +stdump(t, f, nfapresent, level) +struct subre *t; +FILE *f; +int nfapresent; /* is the original NFA still around? */ +int level; +{ + int i; +# define RTSEP " " + + for (i = 0; i < level; i++) + fprintf(f, RTSEP); + fprintf(f, "%c (", t->op); + if (t->flags&LONGER) + fprintf(f, "L"); + if (t->flags&SHORTER) + fprintf(f, "S"); + if (t->flags&MIXED) + fprintf(f, "M"); + if (t->flags&CAP) + fprintf(f, "c"); + if (t->flags&BACKR) + fprintf(f, "b"); + if (!(t->flags&INUSE)) + fprintf(f, "!u"); + fprintf(f, ") r%d", t->retry); + if (t->subno != 0) + fprintf(f, " #%d", t->subno); + if (t->min != 1 || t->max != 1) { + fprintf(f, "{%d,", t->min); + if (t->max != INFINITY) + fprintf(f, "%d", t->max); + fprintf(f, "}"); + } + if (nfapresent) + fprintf(f, " %ld-%ld", (long)t->begin->no, (long)t->end->no); + if (!NULLCNFA(t->cnfa)) + fprintf(f, ":"); + fprintf(f, "\n"); + if (t->left != NULL) + stdump(t->left, f, nfapresent, level+1); + if (!NULLCNFA(t->cnfa)) + dumpcnfa(&t->cnfa, f); + if (t->right != NULL) + stdump(t->right, f, nfapresent, level+1); +} + +#include "regc_lex.c" +#include "regc_color.c" +#include "regc_nfa.c" +#include "regc_cvec.c" +#include "regc_locale.c" ADDED generic/regcustom.h Index: generic/regcustom.h ================================================================== --- /dev/null +++ generic/regcustom.h @@ -0,0 +1,85 @@ +/* headers (which also pick up the standard ones, or equivalents) */ +#include "tclInt.h" + +/* overrides for regguts.h definitions */ +/* function-pointer declarations */ +#define FUNCPTR(name, args) (*name) _ANSI_ARGS_(args) +#define MALLOC(n) ckalloc(n) +#define FREE(p) ckfree(VS(p)) +#define REALLOC(p,n) ckrealloc(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_VOID_T +#undef __REG_VOID_T +#endif +#ifdef __REG_CONST +#undef __REG_CONST +#endif +/* interface types */ +#define __REG_WIDE_T Tcl_UniChar +#define __REG_REGOFF_T long /* not really right, but good enough... */ +#define __REG_VOID_T VOID +#define __REG_CONST CONST +/* names and declarations */ +#define __REG_WIDE_COMPILE TclReComp +#define __REG_WIDE_EXEC TclReExec +#ifndef __REG_NOFRONT +#define __REG_NOFRONT /* don't want regcomp() and regexec() */ +#endif +#ifndef __REG_NOCHAR +#define __REG_NOCHAR /* or the char versions */ +#endif +#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, MCCE number, or NOCELT */ +#define NOCELT (-1) /* celt value which is not valid chr or MCCE */ +#define CHR(c) (UCHAR(c)) /* turn char literal into chr literal */ +#define DIGITVAL(c) ((c)-'0') /* turn chr digit into its value */ +#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 */ + +/* 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) */ +#ifdef notdef +#define REG_DEBUG /* */ +#endif + +/* and pick up the standard header */ +#include "regex.h" ADDED generic/rege_dfa.c Index: generic/rege_dfa.c ================================================================== --- /dev/null +++ generic/rege_dfa.c @@ -0,0 +1,627 @@ +/* + * DFA routines + * This file is #included by regexec.c. + */ + +/* + - longest - longest-preferred matching engine + ^ static chr *longest(struct vars *, struct dfa *, chr *, chr *); + */ +static chr * /* endpoint, or NULL */ +longest(v, d, start, stop) +struct vars *v; /* used only for debug and exec flags */ +struct dfa *d; +chr *start; /* where the match should start */ +chr *stop; /* match must end at or before here */ +{ + chr *cp; + chr *realstop = (stop == v->stop) ? stop : stop + 1; + color co; + struct sset *css; + struct sset *ss; + chr *post; + int i; + struct colormap *cm = d->cm; + + /* initialize */ + css = initialize(v, d, start); + cp = start; + + /* 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", 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", css - d->ssets)); + if (cp == v->stop && stop == 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); + /* 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 = 0; i < d->nssused; 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 **); + */ +static chr * /* endpoint, or NULL */ +shortest(v, d, start, min, max, coldp) +struct vars *v; /* used only for debug and exec flags */ +struct dfa *d; +chr *start; /* where the match should start */ +chr *min; /* match must end at or after here */ +chr *max; /* match must end at or before here */ +chr **coldp; /* store coldstart pointer here, if nonNULL */ +{ + chr *cp; + chr *realmin = (min == v->stop) ? min : min + 1; + chr *realmax = (max == v->stop) ? max : max + 1; + color co; + struct sset *css; + struct sset *ss; + struct colormap *cm = d->cm; + chr *nopr; + int i; + + /* initialize */ + css = initialize(v, d, start); + cp = start; + + /* 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", 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; + else if (ss->flags&POSTSTATE) { + 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)) + return NULL; + + /* find last no-progress state set, if any */ + nopr = d->lastnopr; + for (ss = d->ssets, i = 0; i < d->nssused; ss++, i++) + if ((ss->flags&NOPROGRESS) && nopr != ss->lastseen && + (nopr == NULL || nopr < ss->lastseen)) + nopr = ss->lastseen; + assert(nopr != NULL); + if (coldp != NULL) + *coldp = (nopr == v->start) ? nopr : nopr-1; + return cp; +} + +/* + - newdfa - set up a fresh DFA + ^ static struct dfa *newdfa(struct vars *, struct cnfa *, + ^ struct colormap *, struct smalldfa *); + */ +static struct dfa * +newdfa(v, cnfa, cm, small) +struct vars *v; +struct cnfa *cnfa; +struct colormap *cm; +struct smalldfa *small; /* preallocated space, may be NULL */ +{ + struct dfa *d; + size_t nss = cnfa->nstates * 2; + int wordsper = (cnfa->nstates + UBITS - 1) / UBITS; + struct smalldfa *smallwas = small; + + assert(cnfa != NULL && cnfa->nstates != 0); + + if (nss <= FEWSTATES && cnfa->ncolors <= FEWCOLORS) { + assert(wordsper == 1); + if (small == NULL) { + small = (struct smalldfa *)MALLOC( + sizeof(struct smalldfa)); + if (small == NULL) { + ERR(REG_ESPACE); + return NULL; + } + } + d = &small->dfa; + d->ssets = small->ssets; + d->statesarea = small->statesarea; + d->work = &d->statesarea[nss]; + d->outsarea = small->outsarea; + d->incarea = small->incarea; + d->cptsmalloced = 0; + d->mallocarea = (smallwas == NULL) ? (char *)small : 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(d) +struct dfa *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(uv, n) +unsigned *uv; +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(v, d, start) +struct vars *v; /* used only for debug flags */ +struct dfa *d; +chr *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 = getvacant(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(v, d, css, co, cp, start) +struct vars *v; /* used only for debug flags */ +struct dfa *d; +struct sset *css; +pcolor co; +chr *cp; /* next chr */ +chr *start; /* where the attempt got started */ +{ + struct cnfa *cnfa = d->cnfa; + int i; + unsigned h; + struct carc *ca; + struct sset *p; + int ispost; + int noprogress; + int gotstate; + int dolacons; + int didlacons; + + /* 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]+1; ca->co != COLORLESS; ca++) + if (ca->co == co) { + BSET(d->work, ca->to); + gotstate = 1; + if (ca->to == cnfa->post) + ispost = 1; + if (!cnfa->states[ca->to]->co) + noprogress = 0; + FDEBUG(("%d -> %d\n", i, ca->to)); + } + dolacons = (gotstate) ? (cnfa->flags&HASLACONS) : 0; + didlacons = 0; + while (dolacons) { /* transitive closure */ + dolacons = 0; + for (i = 0; i < d->nstates; i++) + if (ISBSET(d->work, i)) + for (ca = cnfa->states[i]+1; ca->co != COLORLESS; + ca++) + if (ca->co > cnfa->ncolors && + !ISBSET(d->work, ca->to) && + lacon(v, cnfa, cp, + ca->co)) { + BSET(d->work, ca->to); + dolacons = 1; + didlacons = 1; + if (ca->to == cnfa->post) + ispost = 1; + if (!cnfa->states[ca->to]->co) + 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)) { +#ifndef xxx +p->hash == h && +memcmp(VS(d->work), VS(p->states), + d->wordsper*sizeof(unsigned)) == 0) { +#endif + FDEBUG(("cached c%d\n", p - d->ssets)); + break; /* NOTE BREAK OUT */ + } + if (i == 0) { /* nope, need a new cache entry */ + p = getvacant(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 (!didlacons) { /* lookahead conds. always cache miss */ + css->outs[co] = p; + css->inchain[co] = p->ins; + p->ins.ss = css; + p->ins.co = (color)co; + } + return p; +} + +/* + - lacon - lookahead-constraint checker for miss() + ^ static int lacon(struct vars *, struct cnfa *, chr *, pcolor); + */ +static int /* predicate: constraint satisfied? */ +lacon(v, pcnfa, cp, co) +struct vars *v; +struct cnfa *pcnfa; /* parent cnfa */ +chr *cp; +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); + freedfa(d); + FDEBUG(("=== lacon %d match %d\n", n, (end != NULL))); + return (sub->subno) ? (end != NULL) : (end == NULL); +} + +/* + - getvacant - 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 *getvacant(struct vars *, struct dfa *, chr *, chr *); + */ +static struct sset * +getvacant(v, d, cp, start) +struct vars *v; /* used only for debug flags */ +struct dfa *d; +chr *cp; +chr *start; +{ + int i; + struct sset *ss; + struct sset *p; + struct arcp ap; + struct arcp lastap; + color co; + + ss = pickss(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", 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, 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; +} + +/* + - pickss - pick the next stateset to be used + ^ static struct sset *pickss(struct vars *, struct dfa *, chr *, chr *); + */ +static struct sset * +pickss(v, d, cp, start) +struct vars *v; /* used only for debug flags */ +struct dfa *d; +chr *cp; +chr *start; +{ + int i; + struct sset *ss; + struct sset *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", 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", 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; +} ADDED generic/regerror.c Index: generic/regerror.c ================================================================== --- /dev/null +++ generic/regerror.c @@ -0,0 +1,82 @@ +/* + * regerror - error-code expansion + */ + +#include "regguts.h" + +/* unknown-error explanation */ +static char unk[] = "*** unknown regex error code 0x%x ***"; + +/* struct to map among codes, code names, and explanations */ +static struct rerr { + int code; + char *name; + 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(errcode, preg, errbuf, errbuf_size) +int errcode; /* 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 */ +{ + struct rerr *r; + char *msg; + char convbuf[sizeof(unk)+50]; /* 50 = plenty for int */ + size_t len; + int icode; + + switch (errcode) { + 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 == errcode) + break; + if (r->code >= 0) + msg = r->explain; + else { /* unknown; say so */ + sprintf(convbuf, unk, errcode); + 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; +} ADDED generic/regerrs.h Index: generic/regerrs.h ================================================================== --- /dev/null +++ generic/regerrs.h @@ -0,0 +1,18 @@ +{ REG_OKAY, "REG_OKAY", "no errors detected" }, +{ REG_NOMATCH, "REG_NOMATCH", "failed to match" }, +{ REG_BADPAT, "REG_BADPAT", "invalid regexp (reg version 0.2)" }, +{ 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" }, ADDED generic/regex.h Index: generic/regex.h ================================================================== --- /dev/null +++ generic/regex.h @@ -0,0 +1,308 @@ +#ifndef _REGEX_H_ +#define _REGEX_H_ /* never again */ +/* + * regular expressions + * + * 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_VOID_T +#undef __REG_VOID_T +#endif +#ifdef __REG_CONST +#undef __REG_CONST +#endif +/* interface types */ +#define __REG_WIDE_T Tcl_UniChar +#define __REG_REGOFF_T long /* not really right, but good enough... */ +#define __REG_VOID_T VOID +#define __REG_CONST CONST +/* names and declarations */ +#define __REG_WIDE_COMPILE TclReComp +#define __REG_WIDE_EXEC TclReExec +#ifndef __REG_NOFRONT +#define __REG_NOFRONT /* don't want regcomp() and regexec() */ +#endif +#ifndef __REG_NOCHAR +#define __REG_NOCHAR /* or the char versions */ +#endif +#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 + +/* + * For benefit of old compilers, we offer the option of + * overriding the `void' type used to declare nonexistent return types. + */ +#ifdef __REG_VOID_T +typedef __REG_VOID_T re_void; +#else +typedef void re_void; +#endif + +/* + * Also for benefit of old compilers, can supply a macro + * which expands to a substitute for `const'. + */ +#ifndef __REG_CONST +#define __REG_CONST const +#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 */ + int 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 + 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 (placeholder for later work) */ +typedef struct { + int rm_dummy; +} rm_detail_t; + + + +/* + * compilation + ^ #ifndef __REG_NOCHAR + ^ int re_comp(regex_t *, __REG_CONST char *, size_t, int); + ^ #endif + ^ #ifndef __REG_NOFRONT + ^ int regcomp(regex_t *, __REG_CONST char *, int); + ^ #endif + ^ #ifdef __REG_WIDE_T + ^ int __REG_WIDE_COMPILE(regex_t *, __REG_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_DUMP 004000 /* none of your business :-) */ +#define REG_FAKEEC 010000 /* none of your business :-) */ +#define REG_PROGRESS 020000 /* none of your business :-) */ + + + +/* + * execution + ^ #ifndef __REG_NOCHAR + ^ int re_exec(regex_t *, __REG_CONST char *, size_t, + ^ rm_detail_t *, size_t, regmatch_t [], int); + ^ #endif + ^ #ifndef __REG_NOFRONT + ^ int regexec(regex_t *, __REG_CONST char *, size_t, regmatch_t [], int); + ^ #endif + ^ #ifdef __REG_WIDE_T + ^ int __REG_WIDE_EXEC(regex_t *, __REG_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) + ^ re_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, __REG_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 */ +/* 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 _ANSI_ARGS_((regex_t *, __REG_CONST char *, size_t, int)); +#endif +#ifndef __REG_NOFRONT +int regcomp _ANSI_ARGS_((regex_t *, __REG_CONST char *, int)); +#endif +#ifdef __REG_WIDE_T +int __REG_WIDE_COMPILE _ANSI_ARGS_((regex_t *, __REG_CONST __REG_WIDE_T *, size_t, int)); +#endif +#ifndef __REG_NOCHAR +int re_exec _ANSI_ARGS_((regex_t *, __REG_CONST char *, size_t, rm_detail_t *, size_t, regmatch_t [], int)); +#endif +#ifndef __REG_NOFRONT +int regexec _ANSI_ARGS_((regex_t *, __REG_CONST char *, size_t, regmatch_t [], int)); +#endif +#ifdef __REG_WIDE_T +int __REG_WIDE_EXEC _ANSI_ARGS_((regex_t *, __REG_CONST __REG_WIDE_T *, size_t, rm_detail_t *, size_t, regmatch_t [], int)); +#endif +re_void regfree _ANSI_ARGS_((regex_t *)); +extern size_t regerror _ANSI_ARGS_((int, __REG_CONST regex_t *, char *, size_t)); +/* automatically gathered by fwd; do not hand-edit */ +/* =====^!^===== end forwards =====^!^===== */ + + + +/* + * more C++ voodoo + */ +#ifdef __cplusplus +} +#endif + + + +#endif ADDED generic/regexec.c Index: generic/regexec.c ================================================================== --- /dev/null +++ generic/regexec.c @@ -0,0 +1,952 @@ +/* + * re_*exec and friends - match REs + */ + +#include "regguts.h" + + + +/* 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; + chr *start; /* start of string */ + chr *stop; /* just past end of string */ + int err; /* error code if any (0 none) */ + regoff_t *mem; /* memory vector for backtracking */ +}; +#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;} /* if error seen, return */ +#define OFF(p) ((p) - v->start) +#define LOFF(p) ((long)OFF(p)) + + + +/* 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]; +}; + + + + +/* + * forward declarations + */ +/* =====^!^===== begin forwards =====^!^===== */ +/* automatically gathered by fwd; do not hand-edit */ +/* === regexec.c === */ +int exec _ANSI_ARGS_((regex_t *, CONST chr *, size_t, rm_detail_t *, size_t, regmatch_t [], int)); +static int find _ANSI_ARGS_((struct vars *, struct cnfa *, struct colormap *)); +static int cfind _ANSI_ARGS_((struct vars *, struct cnfa *, struct colormap *)); +static VOID zapsubs _ANSI_ARGS_((regmatch_t *, size_t)); +static VOID zapmem _ANSI_ARGS_((struct vars *, struct subre *)); +static VOID subset _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *)); +static int dissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *)); +static int condissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *)); +static int altdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *)); +static int cdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *)); +static int ccondissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *)); +static int crevdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *)); +static int cbrdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *)); +static int caltdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *)); +/* === rege_dfa.c === */ +static chr *longest _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *)); +static chr *shortest _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *, chr *, chr **)); +static struct dfa *newdfa _ANSI_ARGS_((struct vars *, struct cnfa *, struct colormap *, struct smalldfa *)); +static VOID freedfa _ANSI_ARGS_((struct dfa *)); +static unsigned hash _ANSI_ARGS_((unsigned *, int)); +static struct sset *initialize _ANSI_ARGS_((struct vars *, struct dfa *, chr *)); +static struct sset *miss _ANSI_ARGS_((struct vars *, struct dfa *, struct sset *, pcolor, chr *, chr *)); +static int lacon _ANSI_ARGS_((struct vars *, struct cnfa *, chr *, pcolor)); +static struct sset *getvacant _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *)); +static struct sset *pickss _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *)); +/* 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(re, string, len, details, nmatch, pmatch, flags) +regex_t *re; +CONST chr *string; +size_t len; +rm_detail_t *details; /* hook for future elaboration */ +size_t nmatch; +regmatch_t pmatch[]; +int flags; +{ + struct vars var; + register struct vars *v = &var; + int st; + size_t n; + int complications; +# define LOCALMAT 20 + regmatch_t mat[LOCALMAT]; +# define LOCALMEM 40 + regoff_t mem[LOCALMEM]; + + /* sanity checks */ + if (re == NULL || string == NULL || re->re_magic != REMAGIC) + return REG_INVARG; + if (re->re_csize != sizeof(chr)) + return REG_MIXED; + + /* setup */ + v->re = re; + v->g = (struct guts *)re->re_guts; + if (v->g->unmatchable) + return REG_NOMATCH; + complications = (v->g->info®_UBACKREF) ? 1 : 0; + if (v->g->usedshorter) + complications = 1; + v->eflags = flags; + if (v->g->cflags®_NOSUB) + nmatch = 0; /* override client */ + v->nmatch = nmatch; + if (complications && v->nmatch < v->g->nsub + 1) { + /* need work area bigger than what user gave us */ + 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) + return REG_ESPACE; + v->nmatch = v->g->nsub + 1; + } else + v->pmatch = pmatch; + v->start = (chr *)string; + v->stop = (chr *)string + len; + v->err = 0; + if (complications) { + assert(v->g->ntree >= 0); + n = (size_t)v->g->ntree; + if (n <= LOCALMEM) + v->mem = mem; + else + v->mem = (regoff_t *)MALLOC(n*sizeof(regoff_t)); + if (v->mem == NULL) { + if (v->pmatch != pmatch && v->pmatch != mat) + FREE(v->pmatch); + return REG_ESPACE; + } + } else + v->mem = NULL; + + /* do it */ + assert(v->g->tree != NULL); + if (complications) + st = cfind(v, &v->g->tree->cnfa, &v->g->cmap); + else + st = find(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) { + zapsubs(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); + if (v->mem != NULL && v->mem != mem) + FREE(v->mem); + return st; +} + +/* + - find - find a match for the main NFA (no-complications case) + ^ static int find(struct vars *, struct cnfa *, struct colormap *); + */ +static int +find(v, cnfa, cm) +struct vars *v; +struct cnfa *cnfa; +struct colormap *cm; +{ + struct smalldfa da; + struct dfa *d = newdfa(v, cnfa, cm, &da); + struct smalldfa sa; + struct dfa *s = newdfa(v, &v->g->search, cm, &sa); + chr *begin; + chr *end; + chr *open; /* open and close of range of possible starts */ + chr *close; + + if (d == NULL) + return v->err; + if (s == NULL) { + freedfa(d); + return v->err; + } + + close = v->start; + do { + MDEBUG(("\nsearch at %ld\n", LOFF(close))); + close = shortest(v, s, close, close, v->stop, &open); + if (close == NULL) + break; /* NOTE BREAK */ + if (v->nmatch == 0) { + /* don't need exact location */ + freedfa(d); + freedfa(s); + return REG_OKAY; + } + MDEBUG(("between %ld and %ld\n", LOFF(open), LOFF(close))); + for (begin = open; begin <= close; begin++) { + MDEBUG(("\nfind trying at %ld\n", LOFF(begin))); + end = longest(v, d, begin, v->stop); + if (end != NULL) { + assert(v->nmatch > 0); + v->pmatch[0].rm_so = OFF(begin); + v->pmatch[0].rm_eo = OFF(end); + freedfa(d); + freedfa(s); + if (v->nmatch > 1) { + zapsubs(v->pmatch, v->nmatch); + return dissect(v, v->g->tree, begin, + end); + } + if (ISERR()) + return v->err; + return REG_OKAY; + } + } + } while (close < v->stop); + + freedfa(d); + freedfa(s); + if (ISERR()) + return v->err; + return REG_NOMATCH; +} + +/* + - cfind - find a match for the main NFA (with complications) + ^ static int cfind(struct vars *, struct cnfa *, struct colormap *); + */ +static int +cfind(v, cnfa, cm) +struct vars *v; +struct cnfa *cnfa; +struct colormap *cm; +{ + struct smalldfa da; + struct dfa *d = newdfa(v, cnfa, cm, &da); + struct smalldfa sa; + struct dfa *s = newdfa(v, &v->g->search, cm, &sa); + chr *begin; + chr *end; + chr *open; /* open and close of range of possible starts */ + chr *close; + chr *estart; + chr *estop; + int er; + int shorter = v->g->tree->flags&SHORTER; + + if (d == NULL) + return v->err; + if (s == NULL) { + freedfa(d); + return v->err; + } + + close = v->start; + do { + MDEBUG(("\ncsearch at %ld\n", LOFF(close))); + close = shortest(v, s, close, close, v->stop, &open); + if (close == NULL) + break; /* NOTE BREAK */ + MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close))); + for (begin = open; begin <= close; begin++) { + MDEBUG(("\ncfind trying at %ld\n", LOFF(begin))); + estart = begin; + estop = v->stop; + for (;;) { + if (shorter) + end = shortest(v, d, begin, estart, + estop, (chr **)NULL); + else + end = longest(v, d, begin, estop); + if (end == NULL) + break; /* NOTE BREAK OUT */ + MDEBUG(("tentative end %ld\n", LOFF(end))); + zapsubs(v->pmatch, v->nmatch); + zapmem(v, v->g->tree); + er = cdissect(v, v->g->tree, begin, end); + switch (er) { + case REG_OKAY: + if (v->nmatch > 0) { + v->pmatch[0].rm_so = OFF(begin); + v->pmatch[0].rm_eo = OFF(end); + } + freedfa(d); + freedfa(s); + if (ISERR()) + return v->err; + return REG_OKAY; + break; + case REG_NOMATCH: + /* go around and try again */ + if ((shorter) ? end == estop : + end == begin) { + /* no point in trying again */ + freedfa(s); + freedfa(d); + return REG_NOMATCH; + } + if (shorter) + estart = end + 1; + else + estop = end - 1; + break; + default: + freedfa(d); + freedfa(s); + return er; + break; + } + } + } + } while (close < v->stop); + + freedfa(d); + freedfa(s); + if (ISERR()) + return v->err; + return REG_NOMATCH; +} + +/* + - zapsubs - initialize the subexpression matches to "no match" + ^ static VOID zapsubs(regmatch_t *, size_t); + */ +static VOID +zapsubs(p, n) +regmatch_t *p; +size_t n; +{ + size_t i; + + for (i = n-1; i > 0; i--) { + p[i].rm_so = -1; + p[i].rm_eo = -1; + } +} + +/* + - zapmem - initialize the retry memory of a subtree to zeros + ^ static VOID zapmem(struct vars *, struct subre *); + */ +static VOID +zapmem(v, t) +struct vars *v; +struct subre *t; +{ + if (t == NULL) + return; + + assert(v->mem != NULL); + v->mem[t->retry] = 0; + if (t->op == '(') { + assert(t->subno > 0); + v->pmatch[t->subno].rm_so = -1; + v->pmatch[t->subno].rm_eo = -1; + } + + if (t->left != NULL) + zapmem(v, t->left); + if (t->right != NULL) + zapmem(v, t->right); +} + +/* + - subset - set any subexpression relevant to a successful subre + ^ static VOID subset(struct vars *, struct subre *, chr *, chr *); + */ +static VOID +subset(v, sub, begin, end) +struct vars *v; +struct subre *sub; +chr *begin; +chr *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); +} + +/* + - dissect - determine subexpression matches (uncomplicated case) + ^ static int dissect(struct vars *, struct subre *, chr *, chr *); + */ +static int /* regexec return code */ +dissect(v, t, begin, end) +struct vars *v; +struct subre *t; +chr *begin; /* beginning of relevant substring */ +chr *end; /* end of same */ +{ + assert(t != NULL); + MDEBUG(("dissect %ld-%ld\n", LOFF(begin), LOFF(end))); + + switch (t->op) { + case '=': /* terminal node */ + assert(t->left == NULL && t->right == NULL); + return REG_OKAY; /* no action, parent did the work */ + break; + case '|': /* alternation */ + assert(t->left != NULL); + return altdissect(v, t, begin, end); + break; + case 'b': /* back ref -- shouldn't be calling us! */ + return REG_ASSERT; + break; + case '.': /* concatenation */ + assert(t->left != NULL && t->right != NULL); + return condissect(v, t, begin, end); + break; + case '(': /* capturing */ + assert(t->left != NULL && t->right == NULL); + assert(t->subno > 0); + subset(v, t, begin, end); + return dissect(v, t->left, begin, end); + break; + default: + return REG_ASSERT; + break; + } +} + +/* + - condissect - determine concatenation subexpression matches (uncomplicated) + ^ static int condissect(struct vars *, struct subre *, chr *, chr *); + */ +static int /* regexec return code */ +condissect(v, t, begin, end) +struct vars *v; +struct subre *t; +chr *begin; /* beginning of relevant substring */ +chr *end; /* end of same */ +{ + struct smalldfa da; + struct dfa *d; + struct smalldfa d2a; + struct dfa *d2; + chr *mid; + int i; + + assert(t->op == '.'); + assert(t->left != NULL && t->left->cnfa.nstates > 0); + assert(t->right != NULL && t->right->cnfa.nstates > 0); + + d = newdfa(v, &t->left->cnfa, &v->g->cmap, &da); + if (ISERR()) + return v->err; + d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, &d2a); + if (ISERR()) { + freedfa(d); + return v->err; + } + + /* pick a tentative midpoint */ + mid = longest(v, d, begin, end); + if (mid == NULL) { + freedfa(d); + freedfa(d2); + return REG_ASSERT; + } + MDEBUG(("tentative midpoint %ld\n", LOFF(mid))); + + /* iterate until satisfaction or failure */ + while (longest(v, d2, mid, end) != end) { + /* that midpoint didn't work, find a new one */ + if (mid == begin) { + /* all possibilities exhausted! */ + MDEBUG(("no midpoint!\n")); + freedfa(d); + freedfa(d2); + return REG_ASSERT; + } + mid = longest(v, d, begin, mid-1); + if (mid == NULL) { + /* failed to find a new one! */ + MDEBUG(("failed midpoint!\n")); + freedfa(d); + freedfa(d2); + return REG_ASSERT; + } + MDEBUG(("new midpoint %ld\n", LOFF(mid))); + } + + /* satisfaction */ + MDEBUG(("successful\n")); + freedfa(d); + freedfa(d2); + i = dissect(v, t->left, begin, mid); + if (i != REG_OKAY) + return i; + return dissect(v, t->right, mid, end); +} + +/* + - altdissect - determine alternative subexpression matches (uncomplicated) + ^ static int altdissect(struct vars *, struct subre *, chr *, chr *); + */ +static int /* regexec return code */ +altdissect(v, t, begin, end) +struct vars *v; +struct subre *t; +chr *begin; /* beginning of relevant substring */ +chr *end; /* end of same */ +{ + struct smalldfa da; + struct dfa *d; + int i; + + assert(t != NULL); + assert(t->op == '|'); + + for (i = 0; t != NULL; t = t->right, i++) { + MDEBUG(("trying %dth\n", i)); + assert(t->left != NULL && t->left->cnfa.nstates > 0); + d = newdfa(v, &t->left->cnfa, &v->g->cmap, &da); + if (ISERR()) + return v->err; + if (longest(v, d, begin, end) == end) { + MDEBUG(("success\n")); + freedfa(d); + return dissect(v, t->left, begin, end); + } + freedfa(d); + } + return REG_ASSERT; /* none of them matched?!? */ +} + +/* + - cdissect - determine subexpression matches (with complications) + * The retry memory stores the offset of the trial midpoint from begin, + * plus 1 so that 0 uniquely means "clean slate". + ^ static int cdissect(struct vars *, struct subre *, chr *, chr *); + */ +static int /* regexec return code */ +cdissect(v, t, begin, end) +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\n", LOFF(begin), LOFF(end))); + + switch (t->op) { + case '=': /* terminal node */ + assert(t->left == NULL && t->right == NULL); + return REG_OKAY; /* no action, parent did the work */ + break; + case '|': /* alternation */ + assert(t->left != NULL); + return caltdissect(v, t, begin, end); + break; + case 'b': /* back ref -- shouldn't be calling us! */ + assert(t->left == NULL && t->right == NULL); + return cbrdissect(v, t, begin, end); + break; + case '.': /* concatenation */ + assert(t->left != NULL && t->right != NULL); + return ccondissect(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); + return er; + break; + default: + return REG_ASSERT; + break; + } +} + +/* + - ccondissect - concatenation subexpression matches (with complications) + * The retry memory stores the offset of the trial midpoint from begin, + * plus 1 so that 0 uniquely means "clean slate". + ^ static int ccondissect(struct vars *, struct subre *, chr *, chr *); + */ +static int /* regexec return code */ +ccondissect(v, t, begin, end) +struct vars *v; +struct subre *t; +chr *begin; /* beginning of relevant substring */ +chr *end; /* end of same */ +{ + struct smalldfa da; + struct dfa *d; + struct smalldfa d2a; + struct dfa *d2; + chr *mid; + int er; + + assert(t->op == '.'); + assert(t->left != NULL && t->left->cnfa.nstates > 0); + assert(t->right != NULL && t->right->cnfa.nstates > 0); + + if (t->left->flags&SHORTER) /* reverse scan */ + return crevdissect(v, t, begin, end); + + d = newdfa(v, &t->left->cnfa, &v->g->cmap, &da); + if (ISERR()) + return v->err; + d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, &d2a); + if (ISERR()) { + freedfa(d); + return v->err; + } + MDEBUG(("cconcat %d\n", t->retry)); + + /* pick a tentative midpoint */ + if (v->mem[t->retry] == 0) { + mid = longest(v, d, begin, end); + if (mid == NULL) { + freedfa(d); + freedfa(d2); + return REG_NOMATCH; + } + MDEBUG(("tentative midpoint %ld\n", LOFF(mid))); + v->mem[t->retry] = (mid - begin) + 1; + } else { + mid = begin + (v->mem[t->retry] - 1); + MDEBUG(("working midpoint %ld\n", LOFF(mid))); + } + + /* iterate until satisfaction or failure */ + for (;;) { + /* try this midpoint on for size */ + er = cdissect(v, t->left, begin, mid); + if (er == REG_OKAY && longest(v, d2, mid, end) == end && + (er = cdissect(v, t->right, mid, end)) == + REG_OKAY) + break; /* NOTE BREAK OUT */ + if (er != REG_OKAY && er != REG_NOMATCH) { + freedfa(d); + freedfa(d2); + return er; + } + + /* that midpoint didn't work, find a new one */ + if (mid == begin) { + /* all possibilities exhausted */ + MDEBUG(("%d no midpoint\n", t->retry)); + freedfa(d); + freedfa(d2); + return REG_NOMATCH; + } + mid = longest(v, d, begin, mid-1); + if (mid == NULL) { + /* failed to find a new one */ + MDEBUG(("%d failed midpoint\n", t->retry)); + freedfa(d); + freedfa(d2); + return REG_NOMATCH; + } + MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid))); + v->mem[t->retry] = (mid - begin) + 1; + zapmem(v, t->left); + zapmem(v, t->right); + } + + /* satisfaction */ + MDEBUG(("successful\n")); + freedfa(d); + freedfa(d2); + return REG_OKAY; +} + +/* + - crevdissect - determine shortest-first subexpression matches + * The retry memory stores the offset of the trial midpoint from begin, + * plus 1 so that 0 uniquely means "clean slate". + ^ static int crevdissect(struct vars *, struct subre *, chr *, chr *); + */ +static int /* regexec return code */ +crevdissect(v, t, begin, end) +struct vars *v; +struct subre *t; +chr *begin; /* beginning of relevant substring */ +chr *end; /* end of same */ +{ + struct smalldfa da; + struct dfa *d; + struct smalldfa d2a; + struct dfa *d2; + chr *mid; + int er; + + 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); + + /* concatenation -- need to split the substring between parts */ + d = newdfa(v, &t->left->cnfa, &v->g->cmap, &da); + if (ISERR()) + return v->err; + d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, &d2a); + if (ISERR()) { + freedfa(d); + return v->err; + } + MDEBUG(("crev %d\n", t->retry)); + + /* pick a tentative midpoint */ + if (v->mem[t->retry] == 0) { + mid = shortest(v, d, begin, begin, end, (chr **)NULL); + if (mid == NULL) { + freedfa(d); + freedfa(d2); + return REG_NOMATCH; + } + MDEBUG(("tentative midpoint %ld\n", LOFF(mid))); + v->mem[t->retry] = (mid - begin) + 1; + } else { + mid = begin + (v->mem[t->retry] - 1); + MDEBUG(("working midpoint %ld\n", LOFF(mid))); + } + + /* iterate until satisfaction or failure */ + for (;;) { + /* try this midpoint on for size */ + er = cdissect(v, t->left, begin, mid); + if (er == REG_OKAY && longest(v, d2, mid, end) == end && + (er = cdissect(v, t->right, mid, end)) == + REG_OKAY) + break; /* NOTE BREAK OUT */ + if (er != REG_OKAY && er != REG_NOMATCH) { + freedfa(d); + freedfa(d2); + return er; + } + + /* that midpoint didn't work, find a new one */ + if (mid == end) { + /* all possibilities exhausted */ + MDEBUG(("%d no midpoint\n", t->retry)); + freedfa(d); + freedfa(d2); + return REG_NOMATCH; + } + mid = shortest(v, d, begin, mid+1, end, (chr **)NULL); + if (mid == NULL) { + /* failed to find a new one */ + MDEBUG(("%d failed midpoint\n", t->retry)); + freedfa(d); + freedfa(d2); + return REG_NOMATCH; + } + MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid))); + v->mem[t->retry] = (mid - begin) + 1; + zapmem(v, t->left); + zapmem(v, t->right); + } + + /* satisfaction */ + MDEBUG(("successful\n")); + freedfa(d); + freedfa(d2); + return REG_OKAY; +} + +/* + - cbrdissect - determine backref subexpression matches + ^ static int cbrdissect(struct vars *, struct subre *, chr *, chr *); + */ +static int /* regexec return code */ +cbrdissect(v, t, begin, end) +struct vars *v; +struct subre *t; +chr *begin; /* beginning of relevant substring */ +chr *end; /* end of same */ +{ + int i; + int n = t->subno; + size_t len; + chr *paren; + chr *p; + chr *stop; + int min = t->min; + int max = t->max; + + 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->retry, n, min, max)); + + if (v->pmatch[n].rm_so == -1) + return REG_NOMATCH; + paren = v->start + v->pmatch[n].rm_so; + len = v->pmatch[n].rm_eo - v->pmatch[n].rm_so; + + /* no room to maneuver -- retries are pointless */ + if (v->mem[t->retry]) + return REG_NOMATCH; + v->mem[t->retry] = 1; + + /* special-case zero-length string */ + if (len == 0) { + if (begin == end) + return REG_OKAY; + return REG_NOMATCH; + } + + /* and too-short string */ + assert(end >= begin); + if ((size_t)(end - begin) < len) + return REG_NOMATCH; + stop = end - len; + + /* count occurrences */ + i = 0; + for (p = begin; p <= stop && (i < max || max == INFINITY); p += len) { + if ((*v->g->compare)(paren, p, len) != 0) + break; + i++; + } + MDEBUG(("cbackref found %d\n", i)); + + /* and sort it out */ + if (p != end) /* didn't consume all of it */ + return REG_NOMATCH; + if (min <= i && (i <= max || max == INFINITY)) + return REG_OKAY; + return REG_NOMATCH; /* out of range */ +} + +/* + - caltdissect - determine alternative subexpression matches (w. complications) + ^ static int caltdissect(struct vars *, struct subre *, chr *, chr *); + */ +static int /* regexec return code */ +caltdissect(v, t, begin, end) +struct vars *v; +struct subre *t; +chr *begin; /* beginning of relevant substring */ +chr *end; /* end of same */ +{ + struct smalldfa da; + struct dfa *d; + int er; +# define UNTRIED 0 /* not yet tried at all */ +# define TRYING 1 /* top matched, trying submatches */ +# define TRIED 2 /* top didn't match or submatches exhausted */ + + if (t == NULL) + return REG_NOMATCH; + assert(t->op == '|'); + if (v->mem[t->retry] == TRIED) + return caltdissect(v, t->right, begin, end); + + MDEBUG(("calt n%d\n", t->retry)); + assert(t->left != NULL); + + if (v->mem[t->retry] == UNTRIED) { + d = newdfa(v, &t->left->cnfa, &v->g->cmap, &da); + if (ISERR()) + return v->err; + if (longest(v, d, begin, end) != end) { + freedfa(d); + v->mem[t->retry] = TRIED; + return caltdissect(v, t->right, begin, end); + } + freedfa(d); + MDEBUG(("calt matched\n")); + v->mem[t->retry] = TRYING; + } + + er = cdissect(v, t->left, begin, end); + if (er != REG_NOMATCH) + return er; + + v->mem[t->retry] = TRIED; + return caltdissect(v, t->right, begin, end); +} + + + +#include "rege_dfa.c" DELETED generic/regexp.c Index: generic/regexp.c ================================================================== --- generic/regexp.c +++ /dev/null @@ -1,1333 +0,0 @@ -/* - * TclRegComp and TclRegExec -- TclRegSub is elsewhere - * - * Copyright (c) 1986 by University of Toronto. - * Written by Henry Spencer. Not derived from licensed software. - * - * Permission is granted to anyone to use this software for any - * purpose on any computer system, and to redistribute it freely, - * subject to the following restrictions: - * - * 1. The author is not responsible for the consequences of use of - * this software, no matter how awful, even if they arise - * from defects in it. - * - * 2. The origin of this software must not be misrepresented, either - * by explicit claim or by omission. - * - * 3. Altered versions must be plainly marked as such, and must not - * be misrepresented as being the original software. - * - * Beware that some of this code is subtly aware of the way operator - * precedence is structured in regular expressions. Serious changes in - * regular-expression syntax might require a total rethink. - * - * *** NOTE: this code has been altered slightly for use in Tcl: *** - * *** 1. Use ckalloc and ckfree instead of malloc and free. *** - * *** 2. Add extra argument to regexp to specify the real *** - * *** start of the string separately from the start of the *** - * *** current search. This is needed to search for multiple *** - * *** matches within a string. *** - * *** 3. Names have been changed, e.g. from regcomp to *** - * *** TclRegComp, to avoid clashes with other *** - * *** regexp implementations used by applications. *** - * *** 4. Added errMsg declaration and TclRegError procedure *** - * *** 5. Various lint-like things, such as casting arguments *** - * *** in procedure calls. *** - * - * *** NOTE: This code has been altered for use in MT-Sturdy Tcl *** - * *** 1. All use of static variables has been changed to access *** - * *** fields of a structure. *** - * *** 2. This in addition to changes to TclRegError makes the *** - * *** code multi-thread safe. *** - * - * SCCS: @(#) regexp.c 1.13 97/04/29 17:49:17 - */ - -#include "tclInt.h" -#include "tclPort.h" - -/* - * The variable below is set to NULL before invoking regexp functions - * and checked after those functions. If an error occurred then TclRegError - * will set the variable to point to a (static) error message. This - * mechanism unfortunately does not support multi-threading, but the - * procedures TclRegError and TclGetRegError can be modified to use - * thread-specific storage for the variable and thereby make the code - * thread-safe. - */ - -static char *errMsg = NULL; - -/* - * The "internal use only" fields in regexp.h are present to pass info from - * compile to execute that permits the execute phase to run lots faster on - * simple cases. They are: - * - * regstart char that must begin a match; '\0' if none obvious - * reganch is the match anchored (at beginning-of-line only)? - * regmust string (pointer into program) that match must include, or NULL - * regmlen length of regmust string - * - * Regstart and reganch permit very fast decisions on suitable starting points - * for a match, cutting down the work a lot. Regmust permits fast rejection - * of lines that cannot possibly match. The regmust tests are costly enough - * that TclRegComp() supplies a regmust only if the r.e. contains something - * potentially expensive (at present, the only such thing detected is * or + - * at the start of the r.e., which can involve a lot of backup). Regmlen is - * supplied because the test in TclRegExec() needs it and TclRegComp() is - * computing it anyway. - */ - -/* - * Structure for regexp "program". This is essentially a linear encoding - * of a nondeterministic finite-state machine (aka syntax charts or - * "railroad normal form" in parsing technology). Each node is an opcode - * plus a "next" pointer, possibly plus an operand. "Next" pointers of - * all nodes except BRANCH implement concatenation; a "next" pointer with - * a BRANCH on both ends of it is connecting two alternatives. (Here we - * have one of the subtle syntax dependencies: an individual BRANCH (as - * opposed to a collection of them) is never concatenated with anything - * because of operator precedence.) The operand of some types of node is - * a literal string; for others, it is a node leading into a sub-FSM. In - * particular, the operand of a BRANCH node is the first node of the branch. - * (NB this is *not* a tree structure: the tail of the branch connects - * to the thing following the set of BRANCHes.) The opcodes are: - */ - -/* definition number opnd? meaning */ -#define END 0 /* no End of program. */ -#define BOL 1 /* no Match "" at beginning of line. */ -#define EOL 2 /* no Match "" at end of line. */ -#define ANY 3 /* no Match any one character. */ -#define ANYOF 4 /* str Match any character in this string. */ -#define ANYBUT 5 /* str Match any character not in this string. */ -#define BRANCH 6 /* node Match this alternative, or the next... */ -#define BACK 7 /* no Match "", "next" ptr points backward. */ -#define EXACTLY 8 /* str Match this string. */ -#define NOTHING 9 /* no Match empty string. */ -#define STAR 10 /* node Match this (simple) thing 0 or more times. */ -#define PLUS 11 /* node Match this (simple) thing 1 or more times. */ -#define OPEN 20 /* no Mark this point in input as start of #n. */ - /* OPEN+1 is number 1, etc. */ -#define CLOSE (OPEN+NSUBEXP) /* no Analogous to OPEN. */ - -/* - * Opcode notes: - * - * BRANCH The set of branches constituting a single choice are hooked - * together with their "next" pointers, since precedence prevents - * anything being concatenated to any individual branch. The - * "next" pointer of the last BRANCH in a choice points to the - * thing following the whole choice. This is also where the - * final "next" pointer of each individual branch points; each - * branch starts with the operand node of a BRANCH node. - * - * BACK Normal "next" pointers all implicitly point forward; BACK - * exists to make loop structures possible. - * - * STAR,PLUS '?', and complex '*' and '+', are implemented as circular - * BRANCH structures using BACK. Simple cases (one character - * per match) are implemented with STAR and PLUS for speed - * and to minimize recursive plunges. - * - * OPEN,CLOSE ...are numbered at compile time. - */ - -/* - * A node is one char of opcode followed by two chars of "next" pointer. - * "Next" pointers are stored as two 8-bit pieces, high order first. The - * value is a positive offset from the opcode of the node containing it. - * An operand, if any, simply follows the node. (Note that much of the - * code generation knows about this implicit relationship.) - * - * Using two bytes for the "next" pointer is vast overkill for most things, - * but allows patterns to get big without disasters. - */ -#define OP(p) (*(p)) -#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) -#define OPERAND(p) ((p) + 3) - -/* - * See regmagic.h for one further detail of program structure. - */ - - -/* - * Utility definitions. - */ -#ifndef CHARBITS -#define UCHARAT(p) ((int)*(unsigned char *)(p)) -#else -#define UCHARAT(p) ((int)*(p)&CHARBITS) -#endif - -#define FAIL(m) { TclRegError(m); return(NULL); } -#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') -#define META "^$.[()|?+*\\" - -/* - * Flags to be passed up and down. - */ -#define HASWIDTH 01 /* Known never to match null string. */ -#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ -#define SPSTART 04 /* Starts with * or +. */ -#define WORST 0 /* Worst case. */ - -/* - * Global work variables for TclRegComp(). - */ -struct regcomp_state { - char *regparse; /* Input-scan pointer. */ - int regnpar; /* () count. */ - char *regcode; /* Code-emit pointer; ®dummy = don't. */ - long regsize; /* Code size. */ -}; - -static char regdummy; - -/* - * The first byte of the regexp internal "program" is actually this magic - * number; the start node begins in the second byte. - */ -#define MAGIC 0234 - - -/* - * Forward declarations for TclRegComp()'s friends. - */ - -static char * reg _ANSI_ARGS_((int paren, int *flagp, - struct regcomp_state *rcstate)); -static char * regatom _ANSI_ARGS_((int *flagp, - struct regcomp_state *rcstate)); -static char * regbranch _ANSI_ARGS_((int *flagp, - struct regcomp_state *rcstate)); -static void regc _ANSI_ARGS_((int b, - struct regcomp_state *rcstate)); -static void reginsert _ANSI_ARGS_((int op, char *opnd, - struct regcomp_state *rcstate)); -static char * regnext _ANSI_ARGS_((char *p)); -static char * regnode _ANSI_ARGS_((int op, - struct regcomp_state *rcstate)); -static void regoptail _ANSI_ARGS_((char *p, char *val)); -static char * regpiece _ANSI_ARGS_((int *flagp, - struct regcomp_state *rcstate)); -static void regtail _ANSI_ARGS_((char *p, char *val)); - -#ifdef STRCSPN -static int strcspn _ANSI_ARGS_((char *s1, char *s2)); -#endif - -/* - - TclRegComp - compile a regular expression into internal code - * - * We can't allocate space until we know how big the compiled form will be, - * but we can't compile it (and thus know how big it is) until we've got a - * place to put the code. So we cheat: we compile it twice, once with code - * generation turned off and size counting turned on, and once "for real". - * This also means that we don't allocate space until we are sure that the - * thing really will compile successfully, and we never have to move the - * code and thus invalidate pointers into it. (Note that it has to be in - * one piece because free() must be able to free it all.) - * - * Beware that the optimization-preparation code in here knows about some - * of the structure of the compiled regexp. - */ -regexp * -TclRegComp(exp) -char *exp; -{ - register regexp *r; - register char *scan; - register char *longest; - register int len; - int flags; - struct regcomp_state state; - struct regcomp_state *rcstate= &state; - - if (exp == NULL) - FAIL("NULL argument"); - - /* First pass: determine size, legality. */ - rcstate->regparse = exp; - rcstate->regnpar = 1; - rcstate->regsize = 0L; - rcstate->regcode = ®dummy; - regc(MAGIC, rcstate); - if (reg(0, &flags, rcstate) == NULL) - return(NULL); - - /* Small enough for pointer-storage convention? */ - if (rcstate->regsize >= 32767L) /* Probably could be 65535L. */ - FAIL("regexp too big"); - - /* Allocate space. */ - r = (regexp *)ckalloc(sizeof(regexp) + (unsigned)rcstate->regsize); - if (r == NULL) - FAIL("out of space"); - - /* Second pass: emit code. */ - rcstate->regparse = exp; - rcstate->regnpar = 1; - rcstate->regcode = r->program; - regc(MAGIC, rcstate); - if (reg(0, &flags, rcstate) == NULL) - return(NULL); - - /* Dig out information for optimizations. */ - r->regstart = '\0'; /* Worst-case defaults. */ - r->reganch = 0; - r->regmust = NULL; - r->regmlen = 0; - scan = r->program+1; /* First BRANCH. */ - if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ - scan = OPERAND(scan); - - /* Starting-point info. */ - if (OP(scan) == EXACTLY) - r->regstart = *OPERAND(scan); - else if (OP(scan) == BOL) - r->reganch++; - - /* - * If there's something expensive in the r.e., find the - * longest literal string that must appear and make it the - * regmust. Resolve ties in favor of later strings, since - * the regstart check works with the beginning of the r.e. - * and avoiding duplication strengthens checking. Not a - * strong reason, but sufficient in the absence of others. - */ - if (flags&SPSTART) { - longest = NULL; - len = 0; - for (; scan != NULL; scan = regnext(scan)) - if (OP(scan) == EXACTLY && ((int) strlen(OPERAND(scan))) >= len) { - longest = OPERAND(scan); - len = strlen(OPERAND(scan)); - } - r->regmust = longest; - r->regmlen = len; - } - } - - return(r); -} - -/* - - reg - regular expression, i.e. main body or parenthesized thing - * - * Caller must absorb opening parenthesis. - * - * Combining parenthesis handling with the base level of regular expression - * is a trifle forced, but the need to tie the tails of the branches to what - * follows makes it hard to avoid. - */ -static char * -reg(paren, flagp, rcstate) -int paren; /* Parenthesized? */ -int *flagp; -struct regcomp_state *rcstate; -{ - register char *ret; - register char *br; - register char *ender; - register int parno = 0; - int flags; - - *flagp = HASWIDTH; /* Tentatively. */ - - /* Make an OPEN node, if parenthesized. */ - if (paren) { - if (rcstate->regnpar >= NSUBEXP) - FAIL("too many ()"); - parno = rcstate->regnpar; - rcstate->regnpar++; - ret = regnode(OPEN+parno,rcstate); - } else - ret = NULL; - - /* Pick up the branches, linking them together. */ - br = regbranch(&flags,rcstate); - if (br == NULL) - return(NULL); - if (ret != NULL) - regtail(ret, br); /* OPEN -> first. */ - else - ret = br; - if (!(flags&HASWIDTH)) - *flagp &= ~HASWIDTH; - *flagp |= flags&SPSTART; - while (*rcstate->regparse == '|') { - rcstate->regparse++; - br = regbranch(&flags,rcstate); - if (br == NULL) - return(NULL); - regtail(ret, br); /* BRANCH -> BRANCH. */ - if (!(flags&HASWIDTH)) - *flagp &= ~HASWIDTH; - *flagp |= flags&SPSTART; - } - - /* Make a closing node, and hook it on the end. */ - ender = regnode((paren) ? CLOSE+parno : END,rcstate); - regtail(ret, ender); - - /* Hook the tails of the branches to the closing node. */ - for (br = ret; br != NULL; br = regnext(br)) - regoptail(br, ender); - - /* Check for proper termination. */ - if (paren && *rcstate->regparse++ != ')') { - FAIL("unmatched ()"); - } else if (!paren && *rcstate->regparse != '\0') { - if (*rcstate->regparse == ')') { - FAIL("unmatched ()"); - } else - FAIL("junk on end"); /* "Can't happen". */ - /* NOTREACHED */ - } - - return(ret); -} - -/* - - regbranch - one alternative of an | operator - * - * Implements the concatenation operator. - */ -static char * -regbranch(flagp, rcstate) -int *flagp; -struct regcomp_state *rcstate; -{ - register char *ret; - register char *chain; - register char *latest; - int flags; - - *flagp = WORST; /* Tentatively. */ - - ret = regnode(BRANCH,rcstate); - chain = NULL; - while (*rcstate->regparse != '\0' && *rcstate->regparse != '|' && - *rcstate->regparse != ')') { - latest = regpiece(&flags, rcstate); - if (latest == NULL) - return(NULL); - *flagp |= flags&HASWIDTH; - if (chain == NULL) /* First piece. */ - *flagp |= flags&SPSTART; - else - regtail(chain, latest); - chain = latest; - } - if (chain == NULL) /* Loop ran zero times. */ - (void) regnode(NOTHING,rcstate); - - return(ret); -} - -/* - - regpiece - something followed by possible [*+?] - * - * Note that the branching code sequences used for ? and the general cases - * of * and + are somewhat optimized: they use the same NOTHING node as - * both the endmarker for their branch list and the body of the last branch. - * It might seem that this node could be dispensed with entirely, but the - * endmarker role is not redundant. - */ -static char * -regpiece(flagp, rcstate) -int *flagp; -struct regcomp_state *rcstate; -{ - register char *ret; - register char op; - register char *next; - int flags; - - ret = regatom(&flags,rcstate); - if (ret == NULL) - return(NULL); - - op = *rcstate->regparse; - if (!ISMULT(op)) { - *flagp = flags; - return(ret); - } - - if (!(flags&HASWIDTH) && op != '?') - FAIL("*+ operand could be empty"); - *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); - - if (op == '*' && (flags&SIMPLE)) - reginsert(STAR, ret, rcstate); - else if (op == '*') { - /* Emit x* as (x&|), where & means "self". */ - reginsert(BRANCH, ret, rcstate); /* Either x */ - regoptail(ret, regnode(BACK,rcstate)); /* and loop */ - regoptail(ret, ret); /* back */ - regtail(ret, regnode(BRANCH,rcstate)); /* or */ - regtail(ret, regnode(NOTHING,rcstate)); /* null. */ - } else if (op == '+' && (flags&SIMPLE)) - reginsert(PLUS, ret, rcstate); - else if (op == '+') { - /* Emit x+ as x(&|), where & means "self". */ - next = regnode(BRANCH,rcstate); /* Either */ - regtail(ret, next); - regtail(regnode(BACK,rcstate), ret); /* loop back */ - regtail(next, regnode(BRANCH,rcstate)); /* or */ - regtail(ret, regnode(NOTHING,rcstate)); /* null. */ - } else if (op == '?') { - /* Emit x? as (x|) */ - reginsert(BRANCH, ret, rcstate); /* Either x */ - regtail(ret, regnode(BRANCH,rcstate)); /* or */ - next = regnode(NOTHING,rcstate); /* null. */ - regtail(ret, next); - regoptail(ret, next); - } - rcstate->regparse++; - if (ISMULT(*rcstate->regparse)) - FAIL("nested *?+"); - - return(ret); -} - -/* - - regatom - the lowest level - * - * Optimization: gobbles an entire sequence of ordinary characters so that - * it can turn them into a single node, which is smaller to store and - * faster to run. Backslashed characters are exceptions, each becoming a - * separate node; the code is simpler that way and it's not worth fixing. - */ -static char * -regatom(flagp, rcstate) -int *flagp; -struct regcomp_state *rcstate; -{ - register char *ret; - int flags; - - *flagp = WORST; /* Tentatively. */ - - switch (*rcstate->regparse++) { - case '^': - ret = regnode(BOL,rcstate); - break; - case '$': - ret = regnode(EOL,rcstate); - break; - case '.': - ret = regnode(ANY,rcstate); - *flagp |= HASWIDTH|SIMPLE; - break; - case '[': { - register int clss; - register int classend; - - if (*rcstate->regparse == '^') { /* Complement of range. */ - ret = regnode(ANYBUT,rcstate); - rcstate->regparse++; - } else - ret = regnode(ANYOF,rcstate); - if (*rcstate->regparse == ']' || *rcstate->regparse == '-') - regc(*rcstate->regparse++,rcstate); - while (*rcstate->regparse != '\0' && *rcstate->regparse != ']') { - if (*rcstate->regparse == '-') { - rcstate->regparse++; - if (*rcstate->regparse == ']' || *rcstate->regparse == '\0') - regc('-',rcstate); - else { - clss = UCHARAT(rcstate->regparse-2)+1; - classend = UCHARAT(rcstate->regparse); - if (clss > classend+1) - FAIL("invalid [] range"); - for (; clss <= classend; clss++) - regc((char)clss,rcstate); - rcstate->regparse++; - } - } else - regc(*rcstate->regparse++,rcstate); - } - regc('\0',rcstate); - if (*rcstate->regparse != ']') - FAIL("unmatched []"); - rcstate->regparse++; - *flagp |= HASWIDTH|SIMPLE; - } - break; - case '(': - ret = reg(1, &flags, rcstate); - if (ret == NULL) - return(NULL); - *flagp |= flags&(HASWIDTH|SPSTART); - break; - case '\0': - case '|': - case ')': - FAIL("internal urp"); /* Supposed to be caught earlier. */ - /* NOTREACHED */ - case '?': - case '+': - case '*': - FAIL("?+* follows nothing"); - /* NOTREACHED */ - case '\\': - if (*rcstate->regparse == '\0') - FAIL("trailing \\"); - ret = regnode(EXACTLY,rcstate); - regc(*rcstate->regparse++,rcstate); - regc('\0',rcstate); - *flagp |= HASWIDTH|SIMPLE; - break; - default: { - register int len; - register char ender; - - rcstate->regparse--; - len = strcspn(rcstate->regparse, META); - if (len <= 0) - FAIL("internal disaster"); - ender = *(rcstate->regparse+len); - if (len > 1 && ISMULT(ender)) - len--; /* Back off clear of ?+* operand. */ - *flagp |= HASWIDTH; - if (len == 1) - *flagp |= SIMPLE; - ret = regnode(EXACTLY,rcstate); - while (len > 0) { - regc(*rcstate->regparse++,rcstate); - len--; - } - regc('\0',rcstate); - } - break; - } - - return(ret); -} - -/* - - regnode - emit a node - */ -static char * /* Location. */ -regnode(op, rcstate) -int op; -struct regcomp_state *rcstate; -{ - register char *ret; - register char *ptr; - - ret = rcstate->regcode; - if (ret == ®dummy) { - rcstate->regsize += 3; - return(ret); - } - - ptr = ret; - *ptr++ = (char)op; - *ptr++ = '\0'; /* Null "next" pointer. */ - *ptr++ = '\0'; - rcstate->regcode = ptr; - - return(ret); -} - -/* - - regc - emit (if appropriate) a byte of code - */ -static void -regc(b, rcstate) -int b; -struct regcomp_state *rcstate; -{ - if (rcstate->regcode != ®dummy) - *rcstate->regcode++ = (char)b; - else - rcstate->regsize++; -} - -/* - - reginsert - insert an operator in front of already-emitted operand - * - * Means relocating the operand. - */ -static void -reginsert(op, opnd, rcstate) -int op; -char *opnd; -struct regcomp_state *rcstate; -{ - register char *src; - register char *dst; - register char *place; - - if (rcstate->regcode == ®dummy) { - rcstate->regsize += 3; - return; - } - - src = rcstate->regcode; - rcstate->regcode += 3; - dst = rcstate->regcode; - while (src > opnd) - *--dst = *--src; - - place = opnd; /* Op node, where operand used to be. */ - *place++ = (char)op; - *place++ = '\0'; - *place = '\0'; -} - -/* - - regtail - set the next-pointer at the end of a node chain - */ -static void -regtail(p, val) -char *p; -char *val; -{ - register char *scan; - register char *temp; - register int offset; - - if (p == ®dummy) - return; - - /* Find last node. */ - scan = p; - for (;;) { - temp = regnext(scan); - if (temp == NULL) - break; - scan = temp; - } - - if (OP(scan) == BACK) - offset = scan - val; - else - offset = val - scan; - *(scan+1) = (char)((offset>>8)&0377); - *(scan+2) = (char)(offset&0377); -} - -/* - - regoptail - regtail on operand of first argument; nop if operandless - */ -static void -regoptail(p, val) -char *p; -char *val; -{ - /* "Operandless" and "op != BRANCH" are synonymous in practice. */ - if (p == NULL || p == ®dummy || OP(p) != BRANCH) - return; - regtail(OPERAND(p), val); -} - -/* - * TclRegExec and friends - */ - -/* - * Global work variables for TclRegExec(). - */ -struct regexec_state { - char *reginput; /* String-input pointer. */ - char *regbol; /* Beginning of input, for ^ check. */ - char **regstartp; /* Pointer to startp array. */ - char **regendp; /* Ditto for endp. */ -}; - -/* - * Forwards. - */ -static int regtry _ANSI_ARGS_((regexp *prog, char *string, - struct regexec_state *restate)); -static int regmatch _ANSI_ARGS_((char *prog, - struct regexec_state *restate)); -static int regrepeat _ANSI_ARGS_((char *p, - struct regexec_state *restate)); - -#ifdef DEBUG -int regnarrate = 0; -void regdump _ANSI_ARGS_((regexp *r)); -static char *regprop _ANSI_ARGS_((char *op)); -#endif - -/* - - TclRegExec - match a regexp against a string - */ -int -TclRegExec(prog, string, start) -register regexp *prog; -register char *string; -char *start; -{ - register char *s; - struct regexec_state state; - struct regexec_state *restate= &state; - - /* Be paranoid... */ - if (prog == NULL || string == NULL) { - TclRegError("NULL parameter"); - return(0); - } - - /* Check validity of program. */ - if (UCHARAT(prog->program) != MAGIC) { - TclRegError("corrupted program"); - return(0); - } - - /* If there is a "must appear" string, look for it. */ - if (prog->regmust != NULL) { - s = string; - while ((s = strchr(s, prog->regmust[0])) != NULL) { - if (strncmp(s, prog->regmust, (size_t) prog->regmlen) - == 0) - break; /* Found it. */ - s++; - } - if (s == NULL) /* Not present. */ - return(0); - } - - /* Mark beginning of line for ^ . */ - restate->regbol = start; - - /* Simplest case: anchored match need be tried only once. */ - if (prog->reganch) - return(regtry(prog, string, restate)); - - /* Messy cases: unanchored match. */ - s = string; - if (prog->regstart != '\0') - /* We know what char it must start with. */ - while ((s = strchr(s, prog->regstart)) != NULL) { - if (regtry(prog, s, restate)) - return(1); - s++; - } - else - /* We don't -- general case. */ - do { - if (regtry(prog, s, restate)) - return(1); - } while (*s++ != '\0'); - - /* Failure. */ - return(0); -} - -/* - - regtry - try match at specific point - */ -static int /* 0 failure, 1 success */ -regtry(prog, string, restate) -regexp *prog; -char *string; -struct regexec_state *restate; -{ - register int i; - register char **sp; - register char **ep; - - restate->reginput = string; - restate->regstartp = prog->startp; - restate->regendp = prog->endp; - - sp = prog->startp; - ep = prog->endp; - for (i = NSUBEXP; i > 0; i--) { - *sp++ = NULL; - *ep++ = NULL; - } - if (regmatch(prog->program + 1,restate)) { - prog->startp[0] = string; - prog->endp[0] = restate->reginput; - return(1); - } else - return(0); -} - -/* - - regmatch - main matching routine - * - * Conceptually the strategy is simple: check to see whether the current - * node matches, call self recursively to see whether the rest matches, - * and then act accordingly. In practice we make some effort to avoid - * recursion, in particular by going through "ordinary" nodes (that don't - * need to know whether the rest of the match failed) by a loop instead of - * by recursion. - */ -static int /* 0 failure, 1 success */ -regmatch(prog, restate) -char *prog; -struct regexec_state *restate; -{ - register char *scan; /* Current node. */ - char *next; /* Next node. */ - - scan = prog; -#ifdef DEBUG - if (scan != NULL && regnarrate) - fprintf(stderr, "%s(\n", regprop(scan)); -#endif - while (scan != NULL) { -#ifdef DEBUG - if (regnarrate) - fprintf(stderr, "%s...\n", regprop(scan)); -#endif - next = regnext(scan); - - switch (OP(scan)) { - case BOL: - if (restate->reginput != restate->regbol) { - return 0; - } - break; - case EOL: - if (*restate->reginput != '\0') { - return 0; - } - break; - case ANY: - if (*restate->reginput == '\0') { - return 0; - } - restate->reginput++; - break; - case EXACTLY: { - register int len; - register char *opnd; - - opnd = OPERAND(scan); - /* Inline the first character, for speed. */ - if (*opnd != *restate->reginput) { - return 0 ; - } - len = strlen(opnd); - if (len > 1 && strncmp(opnd, restate->reginput, (size_t) len) - != 0) { - return 0; - } - restate->reginput += len; - break; - } - case ANYOF: - if (*restate->reginput == '\0' - || strchr(OPERAND(scan), *restate->reginput) == NULL) { - return 0; - } - restate->reginput++; - break; - case ANYBUT: - if (*restate->reginput == '\0' - || strchr(OPERAND(scan), *restate->reginput) != NULL) { - return 0; - } - restate->reginput++; - break; - case NOTHING: - break; - case BACK: - break; - case OPEN+1: - case OPEN+2: - case OPEN+3: - case OPEN+4: - case OPEN+5: - case OPEN+6: - case OPEN+7: - case OPEN+8: - case OPEN+9: { - register int no; - register char *save; - - doOpen: - no = OP(scan) - OPEN; - save = restate->reginput; - - if (regmatch(next,restate)) { - /* - * Don't set startp if some later invocation of the - * same parentheses already has. - */ - if (restate->regstartp[no] == NULL) { - restate->regstartp[no] = save; - } - return 1; - } else { - return 0; - } - } - case CLOSE+1: - case CLOSE+2: - case CLOSE+3: - case CLOSE+4: - case CLOSE+5: - case CLOSE+6: - case CLOSE+7: - case CLOSE+8: - case CLOSE+9: { - register int no; - register char *save; - - doClose: - no = OP(scan) - CLOSE; - save = restate->reginput; - - if (regmatch(next,restate)) { - /* - * Don't set endp if some later - * invocation of the same parentheses - * already has. - */ - if (restate->regendp[no] == NULL) - restate->regendp[no] = save; - return 1; - } else { - return 0; - } - } - case BRANCH: { - register char *save; - - if (OP(next) != BRANCH) { /* No choice. */ - next = OPERAND(scan); /* Avoid recursion. */ - } else { - do { - save = restate->reginput; - if (regmatch(OPERAND(scan),restate)) - return(1); - restate->reginput = save; - scan = regnext(scan); - } while (scan != NULL && OP(scan) == BRANCH); - return 0; - } - break; - } - case STAR: - case PLUS: { - register char nextch; - register int no; - register char *save; - register int min; - - /* - * Lookahead to avoid useless match attempts - * when we know what character comes next. - */ - nextch = '\0'; - if (OP(next) == EXACTLY) - nextch = *OPERAND(next); - min = (OP(scan) == STAR) ? 0 : 1; - save = restate->reginput; - no = regrepeat(OPERAND(scan),restate); - while (no >= min) { - /* If it could work, try it. */ - if (nextch == '\0' || *restate->reginput == nextch) - if (regmatch(next,restate)) - return(1); - /* Couldn't or didn't -- back up. */ - no--; - restate->reginput = save + no; - } - return(0); - } - case END: - return(1); /* Success! */ - default: - if (OP(scan) > OPEN && OP(scan) < OPEN+NSUBEXP) { - goto doOpen; - } else if (OP(scan) > CLOSE && OP(scan) < CLOSE+NSUBEXP) { - goto doClose; - } - TclRegError("memory corruption"); - return 0; - } - - scan = next; - } - - /* - * We get here only if there's trouble -- normally "case END" is - * the terminating point. - */ - TclRegError("corrupted pointers"); - return(0); -} - -/* - - regrepeat - repeatedly match something simple, report how many - */ -static int -regrepeat(p, restate) -char *p; -struct regexec_state *restate; -{ - register int count = 0; - register char *scan; - register char *opnd; - - scan = restate->reginput; - opnd = OPERAND(p); - switch (OP(p)) { - case ANY: - count = strlen(scan); - scan += count; - break; - case EXACTLY: - while (*opnd == *scan) { - count++; - scan++; - } - break; - case ANYOF: - while (*scan != '\0' && strchr(opnd, *scan) != NULL) { - count++; - scan++; - } - break; - case ANYBUT: - while (*scan != '\0' && strchr(opnd, *scan) == NULL) { - count++; - scan++; - } - break; - default: /* Oh dear. Called inappropriately. */ - TclRegError("internal foulup"); - count = 0; /* Best compromise. */ - break; - } - restate->reginput = scan; - - return(count); -} - -/* - - regnext - dig the "next" pointer out of a node - */ -static char * -regnext(p) -register char *p; -{ - register int offset; - - if (p == ®dummy) - return(NULL); - - offset = NEXT(p); - if (offset == 0) - return(NULL); - - if (OP(p) == BACK) - return(p-offset); - else - return(p+offset); -} - -#ifdef DEBUG - -static char *regprop(); - -/* - - regdump - dump a regexp onto stdout in vaguely comprehensible form - */ -void -regdump(r) -regexp *r; -{ - register char *s; - register char op = EXACTLY; /* Arbitrary non-END op. */ - register char *next; - - - s = r->program + 1; - while (op != END) { /* While that wasn't END last time... */ - op = OP(s); - printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ - next = regnext(s); - if (next == NULL) /* Next ptr. */ - printf("(0)"); - else - printf("(%d)", (s-r->program)+(next-s)); - s += 3; - if (op == ANYOF || op == ANYBUT || op == EXACTLY) { - /* Literal string, where present. */ - while (*s != '\0') { - putchar(*s); - s++; - } - s++; - } - putchar('\n'); - } - - /* Header fields of interest. */ - if (r->regstart != '\0') - printf("start `%c' ", r->regstart); - if (r->reganch) - printf("anchored "); - if (r->regmust != NULL) - printf("must have \"%s\"", r->regmust); - printf("\n"); -} - -/* - - regprop - printable representation of opcode - */ -static char * -regprop(op) -char *op; -{ - register char *p; - static char buf[50]; - - (void) strcpy(buf, ":"); - - switch (OP(op)) { - case BOL: - p = "BOL"; - break; - case EOL: - p = "EOL"; - break; - case ANY: - p = "ANY"; - break; - case ANYOF: - p = "ANYOF"; - break; - case ANYBUT: - p = "ANYBUT"; - break; - case BRANCH: - p = "BRANCH"; - break; - case EXACTLY: - p = "EXACTLY"; - break; - case NOTHING: - p = "NOTHING"; - break; - case BACK: - p = "BACK"; - break; - case END: - p = "END"; - break; - case OPEN+1: - case OPEN+2: - case OPEN+3: - case OPEN+4: - case OPEN+5: - case OPEN+6: - case OPEN+7: - case OPEN+8: - case OPEN+9: - sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); - p = NULL; - break; - case CLOSE+1: - case CLOSE+2: - case CLOSE+3: - case CLOSE+4: - case CLOSE+5: - case CLOSE+6: - case CLOSE+7: - case CLOSE+8: - case CLOSE+9: - sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); - p = NULL; - break; - case STAR: - p = "STAR"; - break; - case PLUS: - p = "PLUS"; - break; - default: - if (OP(op) > OPEN && OP(op) < OPEN+NSUBEXP) { - sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); - p = NULL; - break; - } else if (OP(op) > CLOSE && OP(op) < CLOSE+NSUBEXP) { - sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); - p = NULL; - } else { - TclRegError("corrupted opcode"); - } - break; - } - if (p != NULL) - (void) strcat(buf, p); - return(buf); -} -#endif - -/* - * The following is provided for those people who do not have strcspn() in - * their C libraries. They should get off their butts and do something - * about it; at least one public-domain implementation of those (highly - * useful) string routines has been published on Usenet. - */ -#ifdef STRCSPN -/* - * strcspn - find length of initial segment of s1 consisting entirely - * of characters not from s2 - */ - -static int -strcspn(s1, s2) -char *s1; -char *s2; -{ - register char *scan1; - register char *scan2; - register int count; - - count = 0; - for (scan1 = s1; *scan1 != '\0'; scan1++) { - for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ - if (*scan1 == *scan2++) - return(count); - count++; - } - return(count); -} -#endif - -/* - *---------------------------------------------------------------------- - * - * TclRegError -- - * - * This procedure is invoked by the regexp code when an error - * occurs. It saves the error message so it can be seen by the - * code that called Spencer's code. - * - * Results: - * None. - * - * Side effects: - * The value of "string" is saved in "errMsg". - * - *---------------------------------------------------------------------- - */ - -void -TclRegError(string) - char *string; /* Error message. */ -{ - errMsg = string; -} - -char * -TclGetRegError() -{ - return errMsg; -} ADDED generic/regfree.c Index: generic/regfree.c ================================================================== --- /dev/null +++ generic/regfree.c @@ -0,0 +1,25 @@ +/* + * regfree - free an RE + * + * 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(re) +regex_t *re; +{ + if (re == NULL) + return; + (*((struct fns *)re->re_fns)->free)(re); +} ADDED generic/regfronts.c Index: generic/regfronts.c ================================================================== --- /dev/null +++ generic/regfronts.c @@ -0,0 +1,56 @@ +/* + * regcomp and regexec - front ends to re_ routines + * + * Mostly for implementation of backward-compatibility kludges. Note + * that these routines exist ONLY in char versions. + */ + +#include "regguts.h" + +/* + - regcomp - compile regular expression + */ +int +regcomp(re, str, flags) +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(re, str, nmatch, pmatch, flags) +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®_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); +} ADDED generic/regguts.h Index: generic/regguts.h ================================================================== --- /dev/null +++ generic/regguts.h @@ -0,0 +1,388 @@ +/* + * Internal interface definitions, etc., for the regex package + */ + + + +/* + * 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. + */ + +/* standard header files (NULL is a reasonable indicator for them) */ +#ifndef NULL +#include +#include +#include +#include +#include +#endif + +/* assertions */ +#ifndef assert +#ifndef REG_DEBUG +#define NDEBUG +#include +#endif +#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) ((PVOID)(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 CHAR_BIT +#include +#endif +#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 INFINITY (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 */ +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. + * Multi-character collating elements (MCCEs) cause most of the trouble. + */ +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 */ + int nmcces; /* number of MCCEs */ + int mccespace; /* number of MCCEs possible */ + int nmccechrs; /* number of chrs used for MCCEs */ + chr *mcces[1]; /* pointers to 0-terminated MCCEs */ + /* and both batches of chrs are on the end */ +}; + +/* caution: this value cannot be changed easily */ +#define MAXMCCE 2 /* length of longest MCCE */ + + + +/* + * definitions for 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; +# define ARCFREE '\0' + color co; + struct state *from; /* where it's from (and contained within) */ + struct state *to; /* where it's to */ + struct arc *outchain; /* *from's outs chain or free chain */ +# define freechain outchain + struct arc *inchain; /* *to's ins chain */ + struct arc *colorchain; /* 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 */ +}; + +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 + */ +struct carc { + color co; /* COLORLESS is list terminator */ + int to; /* 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 */ + struct carc **states; /* vector of pointers to outarc lists */ + struct carc *arcs; /* the area for the lists */ +}; +#define ZAPCNFA(cnfa) ((cnfa).nstates = 0) +#define NULLCNFA(cnfa) ((cnfa).nstates == 0) + + + +/* + * subexpression tree + */ +struct subre { + char op; /* '|', '.' (concat), 'b' (backref), '(', '=' */ + 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 LOCAL 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)&~LOCAL) | (LMIX(f) & SMIX(f) & MIXED)) +# define MESSY(f) ((f)&(MIXED|CAP|BACKR)) +# define PREF(f) ((f)&LOCAL) +# define PREF2(f1, f2) ((PREF(f1) != 0) ? PREF(f1) : PREF(f2)) +# define COMBINE(f1, f2) (UP((f1)|(f2)) | PREF2(f1, f2)) + short retry; /* index into retry memory */ + int subno; /* subexpression number (for 'b' and '(') */ + short min; /* min repetitions, for backref only */ + short max; /* max repetitions, for backref only */ + 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 */ + int info; /* copy of re_info */ + size_t nsub; /* copy of re_nsub */ + struct subre *tree; + struct cnfa search; /* for fast preliminary search */ + int ntree; + struct colormap cmap; + int FUNCPTR(compare, (CONST chr *, CONST chr *, size_t)); + struct subre *lacons; /* lookahead-constraint vector */ + int nlacons; /* size of lacons */ + int usedshorter; /* used non-greedy quantifiers? */ + int unmatchable; /* cannot match anything? */ +}; ADDED generic/tcl.decls Index: generic/tcl.decls ================================================================== --- /dev/null +++ generic/tcl.decls @@ -0,0 +1,1321 @@ +# 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, +# tclStub.c, and tclPlatStub.c files. +# +# +# 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. +# +# RCS: @(#) $Id: tcl.decls,v 1.3.2.15 1999/04/06 03:13:12 redman Exp $ + +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} + +# 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 generic { + int Tcl_PkgProvideEx(Tcl_Interp *interp, char *name, char *version, \ + ClientData clientData) +} +declare 1 generic { + char * Tcl_PkgRequireEx(Tcl_Interp *interp, char *name, char *version, \ + int exact, ClientData *clientDataPtr) +} +declare 2 generic { + void Tcl_Panic(char *format, ...) +} +declare 3 generic { + char * Tcl_Alloc(unsigned int size) +} +declare 4 generic { + void Tcl_Free(char *ptr) +} +declare 5 generic { + char * Tcl_Realloc(char *ptr, unsigned int size) +} +declare 6 generic { + char * Tcl_DbCkalloc(unsigned int size, char *file, int line) +} +declare 7 generic { + int Tcl_DbCkfree(char *ptr, char *file, int line) +} +declare 8 generic { + char * Tcl_DbCkrealloc(char *ptr, unsigned int size, 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 generic { + void Tcl_SetTimer(Tcl_Time *timePtr) +} +declare 12 generic { + void Tcl_Sleep(int ms) +} +declare 13 generic { + int Tcl_WaitForEvent(Tcl_Time *timePtr) +} +declare 14 generic { + int Tcl_AppendAllObjTypes(Tcl_Interp *interp, Tcl_Obj *objPtr) +} +declare 15 generic { + void Tcl_AppendStringsToObj(Tcl_Obj *objPtr, ...) +} +declare 16 generic { + void Tcl_AppendToObj(Tcl_Obj *objPtr, char *bytes, int length) +} +declare 17 generic { + Tcl_Obj * Tcl_ConcatObj(int objc, Tcl_Obj *CONST objv[]) +} +declare 18 generic { + int Tcl_ConvertToType(Tcl_Interp *interp, Tcl_Obj *objPtr, \ + Tcl_ObjType *typePtr) +} +declare 19 generic { + void Tcl_DbDecrRefCount(Tcl_Obj *objPtr, char *file, int line) +} +declare 20 generic { + void Tcl_DbIncrRefCount(Tcl_Obj *objPtr, char *file, int line) +} +declare 21 generic { + int Tcl_DbIsShared(Tcl_Obj *objPtr, char *file, int line) +} +declare 22 generic { + Tcl_Obj * Tcl_DbNewBooleanObj(int boolValue, char *file, int line) +} +declare 23 generic { + Tcl_Obj * Tcl_DbNewByteArrayObj(unsigned char *bytes, int length, \ + char *file, int line) +} +declare 24 generic { + Tcl_Obj * Tcl_DbNewDoubleObj(double doubleValue, char *file, int line) +} +declare 25 generic { + Tcl_Obj * Tcl_DbNewListObj(int objc, Tcl_Obj *CONST objv[], char *file, \ + int line) +} +declare 26 generic { + Tcl_Obj * Tcl_DbNewLongObj(long longValue, char *file, int line) +} +declare 27 generic { + Tcl_Obj * Tcl_DbNewObj(char *file, int line) +} +declare 28 generic { + Tcl_Obj * Tcl_DbNewStringObj(CONST char *bytes, int length, \ + char *file, int line) +} +declare 29 generic { + Tcl_Obj * Tcl_DuplicateObj(Tcl_Obj *objPtr) +} +declare 30 generic { + void TclFreeObj(Tcl_Obj *objPtr) +} +declare 31 generic { + int Tcl_GetBoolean(Tcl_Interp *interp, char *str, int *boolPtr) +} +declare 32 generic { + int Tcl_GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, \ + int *boolPtr) +} +declare 33 generic { + unsigned char * Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, int *lengthPtr) +} +declare 34 generic { + int Tcl_GetDouble(Tcl_Interp *interp, char *str, double *doublePtr) +} +declare 35 generic { + int Tcl_GetDoubleFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, \ + double *doublePtr) +} +declare 36 generic { + int Tcl_GetIndexFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, \ + char **tablePtr, char *msg, int flags, int *indexPtr) +} +declare 37 generic { + int Tcl_GetInt(Tcl_Interp *interp, char *str, int *intPtr) +} +declare 38 generic { + int Tcl_GetIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr) +} +declare 39 generic { + int Tcl_GetLongFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr) +} +declare 40 generic { + Tcl_ObjType * Tcl_GetObjType(char *typeName) +} +declare 41 generic { + char * Tcl_GetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr) +} +declare 42 generic { + void Tcl_InvalidateStringRep(Tcl_Obj *objPtr) +} +declare 43 generic { + int Tcl_ListObjAppendList(Tcl_Interp *interp, Tcl_Obj *listPtr, \ + Tcl_Obj *elemListPtr) +} +declare 44 generic { + int Tcl_ListObjAppendElement(Tcl_Interp *interp, Tcl_Obj *listPtr, \ + Tcl_Obj *objPtr) +} +declare 45 generic { + int Tcl_ListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr, \ + int *objcPtr, Tcl_Obj ***objvPtr) +} +declare 46 generic { + int Tcl_ListObjIndex(Tcl_Interp *interp, Tcl_Obj *listPtr, int index, \ + Tcl_Obj **objPtrPtr) +} +declare 47 generic { + int Tcl_ListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr, int *intPtr) +} +declare 48 generic { + int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, int first, \ + int count, int objc, Tcl_Obj *CONST objv[]) +} +declare 49 generic { + Tcl_Obj * Tcl_NewBooleanObj(int boolValue) +} +declare 50 generic { + Tcl_Obj * Tcl_NewByteArrayObj(unsigned char *bytes, int length) +} +declare 51 generic { + Tcl_Obj * Tcl_NewDoubleObj(double doubleValue) +} +declare 52 generic { + Tcl_Obj * Tcl_NewIntObj(int intValue) +} +declare 53 generic { + Tcl_Obj * Tcl_NewListObj(int objc, Tcl_Obj *CONST objv[]) +} +declare 54 generic { + Tcl_Obj * Tcl_NewLongObj(long longValue) +} +declare 55 generic { + Tcl_Obj * Tcl_NewObj(void) +} +declare 56 generic { + Tcl_Obj *Tcl_NewStringObj(CONST char *bytes, int length) +} +declare 57 generic { + void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int boolValue) +} +declare 58 generic { + unsigned char * Tcl_SetByteArrayLength(Tcl_Obj *objPtr, int length) +} +declare 59 generic { + void Tcl_SetByteArrayObj(Tcl_Obj *objPtr, unsigned char *bytes, int length) +} +declare 60 generic { + void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue) +} +declare 61 generic { + void Tcl_SetIntObj(Tcl_Obj *objPtr, int intValue) +} +declare 62 generic { + void Tcl_SetListObj(Tcl_Obj *objPtr, int objc, Tcl_Obj *CONST objv[]) +} +declare 63 generic { + void Tcl_SetLongObj(Tcl_Obj *objPtr, long longValue) +} +declare 64 generic { + void Tcl_SetObjLength(Tcl_Obj *objPtr, int length) +} +declare 65 generic { + void Tcl_SetStringObj(Tcl_Obj *objPtr, char *bytes, int length) +} +declare 66 generic { + void Tcl_AddErrorInfo(Tcl_Interp *interp, CONST char *message) +} +declare 67 generic { + void Tcl_AddObjErrorInfo(Tcl_Interp *interp, CONST char *message, \ + int length) +} +declare 68 generic { + void Tcl_AllowExceptions(Tcl_Interp *interp) +} +declare 69 generic { + void Tcl_AppendElement(Tcl_Interp *interp, CONST char *string) +} +declare 70 generic { + void Tcl_AppendResult(Tcl_Interp *interp, ...) +} +declare 71 generic { + Tcl_AsyncHandler Tcl_AsyncCreate(Tcl_AsyncProc *proc, \ + ClientData clientData) +} +declare 72 generic { + void Tcl_AsyncDelete(Tcl_AsyncHandler async) +} +declare 73 generic { + int Tcl_AsyncInvoke(Tcl_Interp *interp, int code) +} +declare 74 generic { + void Tcl_AsyncMark(Tcl_AsyncHandler async) +} +declare 75 generic { + int Tcl_AsyncReady(void) +} +declare 76 generic { + void Tcl_BackgroundError(Tcl_Interp *interp) +} +declare 77 generic { + char Tcl_Backslash(CONST char *src, int *readPtr) +} +declare 78 generic { + int Tcl_BadChannelOption(Tcl_Interp *interp, char *optionName, \ + char *optionList) +} +declare 79 generic { + void Tcl_CallWhenDeleted(Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, \ + ClientData clientData) +} +declare 80 generic { + void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, ClientData clientData) +} +declare 81 generic { + int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan) +} +declare 82 generic { + int Tcl_CommandComplete(char *cmd) +} +declare 83 generic { + char * Tcl_Concat(int argc, char **argv) +} +declare 84 generic { + int Tcl_ConvertElement(CONST char *src, char *dst, int flags) +} +declare 85 generic { + int Tcl_ConvertCountedElement(CONST char *src, int length, char *dst, \ + int flags) +} +declare 86 generic { + int Tcl_CreateAlias(Tcl_Interp *slave, char *slaveCmd, \ + Tcl_Interp *target, char *targetCmd, int argc, char **argv) +} +declare 87 generic { + int Tcl_CreateAliasObj(Tcl_Interp *slave, char *slaveCmd, \ + Tcl_Interp *target, char *targetCmd, int objc, \ + Tcl_Obj *CONST objv[]) +} +declare 88 generic { + Tcl_Channel Tcl_CreateChannel(Tcl_ChannelType *typePtr, char *chanName, \ + ClientData instanceData, int mask) +} +declare 89 generic { + void Tcl_CreateChannelHandler(Tcl_Channel chan, int mask, \ + Tcl_ChannelProc *proc, ClientData clientData) +} +declare 90 generic { + void Tcl_CreateCloseHandler(Tcl_Channel chan, Tcl_CloseProc *proc, \ + ClientData clientData) +} +declare 91 generic { + Tcl_Command Tcl_CreateCommand(Tcl_Interp *interp, char *cmdName, \ + Tcl_CmdProc *proc, ClientData clientData, \ + Tcl_CmdDeleteProc *deleteProc) +} +declare 92 generic { + void Tcl_CreateEventSource(Tcl_EventSetupProc *setupProc, \ + Tcl_EventCheckProc *checkProc, ClientData clientData) +} +declare 93 generic { + void Tcl_CreateExitHandler(Tcl_ExitProc *proc, ClientData clientData) +} +declare 94 generic { + Tcl_Interp * Tcl_CreateInterp(void) +} +declare 95 generic { + void Tcl_CreateMathFunc(Tcl_Interp *interp, char *name, int numArgs, \ + Tcl_ValueType *argTypes, Tcl_MathProc *proc, ClientData clientData) +} +declare 96 generic { + Tcl_Command Tcl_CreateObjCommand(Tcl_Interp *interp, char *cmdName, \ + Tcl_ObjCmdProc *proc, ClientData clientData, \ + Tcl_CmdDeleteProc *deleteProc) +} +declare 97 generic { + Tcl_Interp * Tcl_CreateSlave(Tcl_Interp *interp, char *slaveName, \ + int isSafe) +} +declare 98 generic { + Tcl_TimerToken Tcl_CreateTimerHandler(int milliseconds, \ + Tcl_TimerProc *proc, ClientData clientData) +} +declare 99 generic { + Tcl_Trace Tcl_CreateTrace(Tcl_Interp *interp, int level, \ + Tcl_CmdTraceProc *proc, ClientData clientData) +} +declare 100 generic { + void Tcl_DeleteAssocData(Tcl_Interp *interp, char *name) +} +declare 101 generic { + void Tcl_DeleteChannelHandler(Tcl_Channel chan, Tcl_ChannelProc *proc, \ + ClientData clientData) +} +declare 102 generic { + void Tcl_DeleteCloseHandler(Tcl_Channel chan, Tcl_CloseProc *proc, \ + ClientData clientData) +} +declare 103 generic { + int Tcl_DeleteCommand(Tcl_Interp *interp, char *cmdName) +} +declare 104 generic { + int Tcl_DeleteCommandFromToken(Tcl_Interp *interp, Tcl_Command command) +} +declare 105 generic { + void Tcl_DeleteEvents(Tcl_EventDeleteProc *proc, ClientData clientData) +} +declare 106 generic { + void Tcl_DeleteEventSource(Tcl_EventSetupProc *setupProc, \ + Tcl_EventCheckProc *checkProc, ClientData clientData) +} +declare 107 generic { + void Tcl_DeleteExitHandler(Tcl_ExitProc *proc, ClientData clientData) +} +declare 108 generic { + void Tcl_DeleteHashEntry(Tcl_HashEntry *entryPtr) +} +declare 109 generic { + void Tcl_DeleteHashTable(Tcl_HashTable *tablePtr) +} +declare 110 generic { + void Tcl_DeleteInterp(Tcl_Interp *interp) +} +declare 111 generic { + void Tcl_DetachPids(int numPids, Tcl_Pid *pidPtr) +} +declare 112 generic { + void Tcl_DeleteTimerHandler(Tcl_TimerToken token) +} +declare 113 generic { + void Tcl_DeleteTrace(Tcl_Interp *interp, Tcl_Trace trace) +} +declare 114 generic { + void Tcl_DontCallWhenDeleted(Tcl_Interp *interp, \ + Tcl_InterpDeleteProc *proc, ClientData clientData) +} +declare 115 generic { + int Tcl_DoOneEvent(int flags) +} +declare 116 generic { + void Tcl_DoWhenIdle(Tcl_IdleProc *proc, ClientData clientData) +} +declare 117 generic { + char * Tcl_DStringAppend(Tcl_DString *dsPtr, CONST char *str, int length) +} +declare 118 generic { + char * Tcl_DStringAppendElement(Tcl_DString *dsPtr, CONST char *string) +} +declare 119 generic { + void Tcl_DStringEndSublist(Tcl_DString *dsPtr) +} +declare 120 generic { + void Tcl_DStringFree(Tcl_DString *dsPtr) +} +declare 121 generic { + void Tcl_DStringGetResult(Tcl_Interp *interp, Tcl_DString *dsPtr) +} +declare 122 generic { + void Tcl_DStringInit(Tcl_DString *dsPtr) +} +declare 123 generic { + void Tcl_DStringResult(Tcl_Interp *interp, Tcl_DString *dsPtr) +} +declare 124 generic { + void Tcl_DStringSetLength(Tcl_DString *dsPtr, int length) +} +declare 125 generic { + void Tcl_DStringStartSublist(Tcl_DString *dsPtr) +} +declare 126 generic { + int Tcl_Eof(Tcl_Channel chan) +} +declare 127 generic { + char * Tcl_ErrnoId(void) +} +declare 128 generic { + char * Tcl_ErrnoMsg(int err) +} +declare 129 generic { + int Tcl_Eval(Tcl_Interp *interp, char *string) +} +declare 130 generic { + int Tcl_EvalFile(Tcl_Interp *interp, char *fileName) +} +declare 131 generic { + int Tcl_EvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr) +} +declare 132 generic { + void Tcl_EventuallyFree(ClientData clientData, Tcl_FreeProc *freeProc) +} +declare 133 generic { + void Tcl_Exit(int status) +} +declare 134 generic { + int Tcl_ExposeCommand(Tcl_Interp *interp, char *hiddenCmdToken, \ + char *cmdName) +} +declare 135 generic { + int Tcl_ExprBoolean(Tcl_Interp *interp, char *str, int *ptr) +} +declare 136 generic { + int Tcl_ExprBooleanObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *ptr) +} +declare 137 generic { + int Tcl_ExprDouble(Tcl_Interp *interp, char *str, double *ptr) +} +declare 138 generic { + int Tcl_ExprDoubleObj(Tcl_Interp *interp, Tcl_Obj *objPtr, double *ptr) +} +declare 139 generic { + int Tcl_ExprLong(Tcl_Interp *interp, char *str, long *ptr) +} +declare 140 generic { + int Tcl_ExprLongObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *ptr) +} +declare 141 generic { + int Tcl_ExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr, \ + Tcl_Obj **resultPtrPtr) +} +declare 142 generic { + int Tcl_ExprString(Tcl_Interp *interp, char *string) +} +declare 143 generic { + void Tcl_Finalize(void) +} +declare 144 generic { + void Tcl_FindExecutable(CONST char *argv0) +} +declare 145 generic { + Tcl_HashEntry * Tcl_FirstHashEntry(Tcl_HashTable *tablePtr, \ + Tcl_HashSearch *searchPtr) +} +declare 146 generic { + int Tcl_Flush(Tcl_Channel chan) +} +declare 147 generic { + void Tcl_FreeResult(Tcl_Interp *interp) +} +declare 148 generic { + int Tcl_GetAlias(Tcl_Interp *interp, char *slaveCmd, \ + Tcl_Interp **targetInterpPtr, char **targetCmdPtr, int *argcPtr, \ + char ***argvPtr) +} +declare 149 generic { + int Tcl_GetAliasObj(Tcl_Interp *interp, char *slaveCmd, \ + Tcl_Interp **targetInterpPtr, char **targetCmdPtr, int *objcPtr, \ + Tcl_Obj ***objv) +} +declare 150 generic { + ClientData Tcl_GetAssocData(Tcl_Interp *interp, char *name, \ + Tcl_InterpDeleteProc **procPtr) +} +declare 151 generic { + Tcl_Channel Tcl_GetChannel(Tcl_Interp *interp, char *chanName, \ + int *modePtr) +} +declare 152 generic { + int Tcl_GetChannelBufferSize(Tcl_Channel chan) +} +declare 153 generic { + int Tcl_GetChannelHandle(Tcl_Channel chan, int direction, \ + ClientData *handlePtr) +} +declare 154 generic { + ClientData Tcl_GetChannelInstanceData(Tcl_Channel chan) +} +declare 155 generic { + int Tcl_GetChannelMode(Tcl_Channel chan) +} +declare 156 generic { + char * Tcl_GetChannelName(Tcl_Channel chan) +} +declare 157 generic { + int Tcl_GetChannelOption(Tcl_Interp *interp, Tcl_Channel chan, \ + char *optionName, Tcl_DString *dsPtr) +} +declare 158 generic { + Tcl_ChannelType * Tcl_GetChannelType(Tcl_Channel chan) +} +declare 159 generic { + int Tcl_GetCommandInfo(Tcl_Interp *interp, char *cmdName, \ + Tcl_CmdInfo *infoPtr) +} +declare 160 generic { + char * Tcl_GetCommandName(Tcl_Interp *interp, Tcl_Command command) +} +declare 161 generic { + int Tcl_GetErrno(void) +} +declare 162 generic { + char * Tcl_GetHostName(void) +} +declare 163 generic { + int Tcl_GetInterpPath(Tcl_Interp *askInterp, Tcl_Interp *slaveInterp) +} +declare 164 generic { + Tcl_Interp * Tcl_GetMaster(Tcl_Interp *interp) +} +declare 165 generic { + CONST char * Tcl_GetNameOfExecutable(void) +} +declare 166 generic { + 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, char *str, int write, \ + int checkUsage, ClientData *filePtr) +} + +declare 168 generic { + Tcl_PathType Tcl_GetPathType(char *path) +} +declare 169 generic { + int Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr) +} +declare 170 generic { + int Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr) +} +declare 171 generic { + int Tcl_GetServiceMode(void) +} +declare 172 generic { + Tcl_Interp * Tcl_GetSlave(Tcl_Interp *interp, char *slaveName) +} +declare 173 generic { + Tcl_Channel Tcl_GetStdChannel(int type) +} +declare 174 generic { + char * Tcl_GetStringResult(Tcl_Interp *interp) +} +declare 175 generic { + char * Tcl_GetVar(Tcl_Interp *interp, char *varName, int flags) +} +declare 176 generic { + char * Tcl_GetVar2(Tcl_Interp *interp, char *part1, char *part2, int flags) +} +declare 177 generic { + int Tcl_GlobalEval(Tcl_Interp *interp, char *command) +} +declare 178 generic { + int Tcl_GlobalEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr) +} +declare 179 generic { + int Tcl_HideCommand(Tcl_Interp *interp, char *cmdName, \ + char *hiddenCmdToken) +} +declare 180 generic { + int Tcl_Init(Tcl_Interp *interp) +} +declare 181 generic { + void Tcl_InitHashTable(Tcl_HashTable *tablePtr, int keyType) +} +declare 182 generic { + int Tcl_InputBlocked(Tcl_Channel chan) +} +declare 183 generic { + int Tcl_InputBuffered(Tcl_Channel chan) +} +declare 184 generic { + int Tcl_InterpDeleted(Tcl_Interp *interp) +} +declare 185 generic { + int Tcl_IsSafe(Tcl_Interp *interp) +} +declare 186 generic { + char * Tcl_JoinPath(int argc, char **argv, Tcl_DString *resultPtr) +} +declare 187 generic { + int Tcl_LinkVar(Tcl_Interp *interp, char *varName, char *addr, int type) +} + +# This slot is reserved for use by the plus patch: +# declare 188 generic { +# Tcl_MainLoop +# } + +declare 189 generic { + Tcl_Channel Tcl_MakeFileChannel(ClientData handle, int mode) +} +declare 190 generic { + int Tcl_MakeSafe(Tcl_Interp *interp) +} +declare 191 generic { + Tcl_Channel Tcl_MakeTcpClientChannel(ClientData tcpSocket) +} +declare 192 generic { + char * Tcl_Merge(int argc, char **argv) +} +declare 193 generic { + Tcl_HashEntry * Tcl_NextHashEntry(Tcl_HashSearch *searchPtr) +} +declare 194 generic { + void Tcl_NotifyChannel(Tcl_Channel channel, int mask) +} +declare 195 generic { + Tcl_Obj * Tcl_ObjGetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, \ + Tcl_Obj *part2Ptr, int flags) +} +declare 196 generic { + Tcl_Obj * Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, \ + Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags) +} +declare 197 generic { + Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc, \ + char **argv, int flags) +} +declare 198 generic { + Tcl_Channel Tcl_OpenFileChannel(Tcl_Interp *interp, char *fileName, \ + char *modeString, int permissions) +} +declare 199 generic { + Tcl_Channel Tcl_OpenTcpClient(Tcl_Interp *interp, int port, \ + char *address, char *myaddr, int myport, int async) +} +declare 200 generic { + Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port, char *host, \ + Tcl_TcpAcceptProc *acceptProc, ClientData callbackData) +} +declare 201 generic { + void Tcl_Preserve(ClientData data) +} +declare 202 generic { + void Tcl_PrintDouble(Tcl_Interp *interp, double value, char *dst) +} +declare 203 generic { + int Tcl_PutEnv(CONST char *string) +} +declare 204 generic { + char * Tcl_PosixError(Tcl_Interp *interp) +} +declare 205 generic { + void Tcl_QueueEvent(Tcl_Event *evPtr, Tcl_QueuePosition position) +} +declare 206 generic { + int Tcl_Read(Tcl_Channel chan, char *bufPtr, int toRead) +} +declare 207 generic { + void Tcl_ReapDetachedProcs(void) +} +declare 208 generic { + int Tcl_RecordAndEval(Tcl_Interp *interp, char *cmd, int flags) +} +declare 209 generic { + int Tcl_RecordAndEvalObj(Tcl_Interp *interp, Tcl_Obj *cmdPtr, int flags) +} +declare 210 generic { + void Tcl_RegisterChannel(Tcl_Interp *interp, Tcl_Channel chan) +} +declare 211 generic { + void Tcl_RegisterObjType(Tcl_ObjType *typePtr) +} +declare 212 generic { + Tcl_RegExp Tcl_RegExpCompile(Tcl_Interp *interp, char *string) +} +declare 213 generic { + int Tcl_RegExpExec(Tcl_Interp *interp, Tcl_RegExp regexp, \ + CONST char *str, CONST char *start) +} +declare 214 generic { + int Tcl_RegExpMatch(Tcl_Interp *interp, char *str, char *pattern) +} +declare 215 generic { + void Tcl_RegExpRange(Tcl_RegExp regexp, int index, char **startPtr, \ + char **endPtr) +} +declare 216 generic { + void Tcl_Release(ClientData clientData) +} +declare 217 generic { + void Tcl_ResetResult(Tcl_Interp *interp) +} +declare 218 generic { + int Tcl_ScanElement(CONST char *str, int *flagPtr) +} +declare 219 generic { + int Tcl_ScanCountedElement(CONST char *str, int length, int *flagPtr) +} +declare 220 generic { + int Tcl_Seek(Tcl_Channel chan, int offset, int mode) +} +declare 221 generic { + int Tcl_ServiceAll(void) +} +declare 222 generic { + int Tcl_ServiceEvent(int flags) +} +declare 223 generic { + void Tcl_SetAssocData(Tcl_Interp *interp, char *name, \ + Tcl_InterpDeleteProc *proc, ClientData clientData) +} +declare 224 generic { + void Tcl_SetChannelBufferSize(Tcl_Channel chan, int sz) +} +declare 225 generic { + int Tcl_SetChannelOption(Tcl_Interp *interp, Tcl_Channel chan, \ + char *optionName, char *newValue) +} +declare 226 generic { + int Tcl_SetCommandInfo(Tcl_Interp *interp, char *cmdName, \ + Tcl_CmdInfo *infoPtr) +} +declare 227 generic { + void Tcl_SetErrno(int err) +} +declare 228 generic { + void Tcl_SetErrorCode(Tcl_Interp *interp, ...) +} +declare 229 generic { + void Tcl_SetMaxBlockTime(Tcl_Time *timePtr) +} +declare 230 generic { + void Tcl_SetPanicProc(Tcl_PanicProc *panicProc) +} +declare 231 generic { + int Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth) +} +declare 232 generic { + void Tcl_SetResult(Tcl_Interp *interp, char *str, \ + Tcl_FreeProc *freeProc) +} +declare 233 generic { + int Tcl_SetServiceMode(int mode) +} +declare 234 generic { + void Tcl_SetObjErrorCode(Tcl_Interp *interp, Tcl_Obj *errorObjPtr) +} +declare 235 generic { + void Tcl_SetObjResult(Tcl_Interp *interp, Tcl_Obj *resultObjPtr) +} +declare 236 generic { + void Tcl_SetStdChannel(Tcl_Channel channel, int type) +} +declare 237 generic { + char * Tcl_SetVar(Tcl_Interp *interp, char *varName, char *newValue, \ + int flags) +} +declare 238 generic { + char * Tcl_SetVar2(Tcl_Interp *interp, char *part1, char *part2, \ + char *newValue, int flags) +} +declare 239 generic { + char * Tcl_SignalId(int sig) +} +declare 240 generic { + char * Tcl_SignalMsg(int sig) +} +declare 241 generic { + void Tcl_SourceRCFile(Tcl_Interp *interp) +} +declare 242 generic { + int Tcl_SplitList(Tcl_Interp *interp, CONST char *listStr, int *argcPtr, \ + char ***argvPtr) +} +declare 243 generic { + void Tcl_SplitPath(CONST char *path, int *argcPtr, char ***argvPtr) +} +declare 244 generic { + void Tcl_StaticPackage(Tcl_Interp *interp, char *pkgName, \ + Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc) +} +declare 245 generic { + int Tcl_StringMatch(CONST char *str, CONST char *pattern) +} +declare 246 generic { + int Tcl_Tell(Tcl_Channel chan) +} +declare 247 generic { + int Tcl_TraceVar(Tcl_Interp *interp, char *varName, int flags, \ + Tcl_VarTraceProc *proc, ClientData clientData) +} +declare 248 generic { + int Tcl_TraceVar2(Tcl_Interp *interp, char *part1, char *part2, \ + int flags, Tcl_VarTraceProc *proc, ClientData clientData) +} +declare 249 generic { + char * Tcl_TranslateFileName(Tcl_Interp *interp, char *name, \ + Tcl_DString *bufferPtr) +} +declare 250 generic { + int Tcl_Ungets(Tcl_Channel chan, char *str, int len, int atHead) +} +declare 251 generic { + void Tcl_UnlinkVar(Tcl_Interp *interp, char *varName) +} +declare 252 generic { + int Tcl_UnregisterChannel(Tcl_Interp *interp, Tcl_Channel chan) +} +declare 253 generic { + int Tcl_UnsetVar(Tcl_Interp *interp, char *varName, int flags) +} +declare 254 generic { + int Tcl_UnsetVar2(Tcl_Interp *interp, char *part1, char *part2, int flags) +} +declare 255 generic { + void Tcl_UntraceVar(Tcl_Interp *interp, char *varName, int flags, \ + Tcl_VarTraceProc *proc, ClientData clientData) +} +declare 256 generic { + void Tcl_UntraceVar2(Tcl_Interp *interp, char *part1, char *part2, \ + int flags, Tcl_VarTraceProc *proc, ClientData clientData) +} +declare 257 generic { + void Tcl_UpdateLinkedVar(Tcl_Interp *interp, char *varName) +} +declare 258 generic { + int Tcl_UpVar(Tcl_Interp *interp, char *frameName, char *varName, \ + char *localName, int flags) +} +declare 259 generic { + int Tcl_UpVar2(Tcl_Interp *interp, char *frameName, char *part1, \ + char *part2, char *localName, int flags) +} +declare 260 generic { + int Tcl_VarEval(Tcl_Interp *interp, ...) +} +declare 261 generic { + ClientData Tcl_VarTraceInfo(Tcl_Interp *interp, char *varName, \ + int flags, Tcl_VarTraceProc *procPtr, ClientData prevClientData) +} +declare 262 generic { + ClientData Tcl_VarTraceInfo2(Tcl_Interp *interp, char *part1, \ + char *part2, int flags, Tcl_VarTraceProc *procPtr, \ + ClientData prevClientData) +} +declare 263 generic { + int Tcl_Write(Tcl_Channel chan, char *s, int slen) +} +declare 264 generic { + void Tcl_WrongNumArgs(Tcl_Interp *interp, int objc, \ + Tcl_Obj *CONST objv[], char *message) +} +declare 265 generic { + int Tcl_DumpActiveMemory(char *fileName) +} +declare 266 generic { + void Tcl_ValidateAllMemory(char *file, int line) +} +declare 267 generic { + void Tcl_AppendResultVA(Tcl_Interp *interp, va_list argList) +} +declare 268 generic { + void Tcl_AppendStringsToObjVA(Tcl_Obj *objPtr, va_list argList) +} +declare 269 generic { + char * Tcl_HashStats(Tcl_HashTable *tablePtr) +} +declare 270 generic { + char * Tcl_ParseVar(Tcl_Interp *interp, char *str, char **termPtr) +} +declare 271 generic { + char * Tcl_PkgPresent(Tcl_Interp *interp, char *name, char *version, \ + int exact) +} +declare 272 generic { + char * Tcl_PkgPresentEx(Tcl_Interp *interp, char *name, char *version, \ + int exact, ClientData *clientDataPtr) +} +declare 273 generic { + int Tcl_PkgProvide(Tcl_Interp *interp, char *name, char *version) +} +declare 274 generic { + char * Tcl_PkgRequire(Tcl_Interp *interp, char *name, char *version, \ + int exact) +} +declare 275 generic { + void Tcl_SetErrorCodeVA(Tcl_Interp *interp, va_list argList) +} +declare 276 generic { + int Tcl_VarEvalVA(Tcl_Interp *interp, va_list argList) +} +declare 277 generic { + Tcl_Pid Tcl_WaitPid(Tcl_Pid pid, int *statPtr, int options) +} +declare 278 generic { + void Tcl_PanicVA(char *format, va_list argList) +} +declare 279 generic { + void Tcl_GetVersion(int *major, int *minor, int *patchLevel, int *type) +} +declare 280 generic { + void Tcl_InitMemory(Tcl_Interp *interp) +} + +# Reserved for future use (8.0.x vs. 8.1) +# declare 281 generic { +# } +# declare 282 generic { +# } +# declare 283 generic { +# } +# declare 284 generic { +# } +# declare 285 generic { +# } + + +# Added in 8.1: + +declare 286 generic { + void Tcl_AppendObjToObj(Tcl_Obj *objPtr, Tcl_Obj *appendObjPtr) +} +declare 287 generic { + Tcl_Encoding Tcl_CreateEncoding(Tcl_EncodingType *typePtr) +} +declare 288 generic { + void Tcl_CreateThreadExitHandler(Tcl_ExitProc *proc, ClientData clientData) +} +declare 289 generic { + void Tcl_DeleteThreadExitHandler(Tcl_ExitProc *proc, ClientData clientData) +} +declare 290 generic { + void Tcl_DiscardResult(Tcl_SavedResult *statePtr) +} +declare 291 generic { + int Tcl_EvalEx(Tcl_Interp *interp, char *script, int numBytes, int flags) +} +declare 292 generic { + int Tcl_EvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], \ + int flags) +} +declare 293 generic { + int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) +} +declare 294 generic { + void Tcl_ExitThread(int status) +} +declare 295 generic { + 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 generic { + char * Tcl_ExternalToUtfDString(Tcl_Encoding encoding, CONST char *src, \ + int srcLen, Tcl_DString *dsPtr) +} +declare 297 generic { + void Tcl_FinalizeThread(void) +} +declare 298 generic { + void Tcl_FinalizeNotifier(ClientData clientData) +} +declare 299 generic { + void Tcl_FreeEncoding(Tcl_Encoding encoding) +} +declare 300 generic { + Tcl_ThreadId Tcl_GetCurrentThread(void) +} +declare 301 generic { + Tcl_Encoding Tcl_GetEncoding(Tcl_Interp *interp, CONST char *name) +} +declare 302 generic { + char * Tcl_GetEncodingName(Tcl_Encoding encoding) +} +declare 303 generic { + void Tcl_GetEncodingNames(Tcl_Interp *interp) +} +declare 304 generic { + int Tcl_GetIndexFromObjStruct(Tcl_Interp *interp, Tcl_Obj *objPtr, \ + char **tablePtr, int offset, char *msg, int flags, int *indexPtr) +} +declare 305 generic { + VOID * Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr, int size) +} +declare 306 generic { + Tcl_Obj * Tcl_GetVar2Ex(Tcl_Interp *interp, char *part1, char *part2, \ + int flags) +} +declare 307 generic { + ClientData Tcl_InitNotifier(void) +} +declare 308 generic { + void Tcl_MutexLock(Tcl_Mutex *mutexPtr) +} +declare 309 generic { + void Tcl_MutexUnlock(Tcl_Mutex *mutexPtr) +} +declare 310 generic { + void Tcl_ConditionNotify(Tcl_Condition *condPtr) +} +declare 311 generic { + void Tcl_ConditionWait(Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr, \ + Tcl_Time *timePtr) +} +declare 312 generic { + int Tcl_NumUtfChars(CONST char *src, int len) +} +declare 313 generic { + int Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr, int charsToRead, \ + int appendFlag) +} +declare 314 generic { + void Tcl_RestoreResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr) +} +declare 315 generic { + void Tcl_SaveResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr) +} +declare 316 generic { + int Tcl_SetSystemEncoding(Tcl_Interp *interp, CONST char *name) +} +declare 317 generic { + Tcl_Obj * Tcl_SetVar2Ex(Tcl_Interp *interp, char *part1, char *part2, \ + Tcl_Obj *newValuePtr, int flags) +} +declare 318 generic { + void Tcl_ThreadAlert(Tcl_ThreadId threadId) +} +declare 319 generic { + void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId, Tcl_Event* evPtr, \ + Tcl_QueuePosition position) +} +declare 320 generic { + Tcl_UniChar Tcl_UniCharAtIndex(CONST char *src, int index) +} +declare 321 generic { + Tcl_UniChar Tcl_UniCharToLower(int ch) +} +declare 322 generic { + Tcl_UniChar Tcl_UniCharToTitle(int ch) +} +declare 323 generic { + Tcl_UniChar Tcl_UniCharToUpper(int ch) +} +declare 324 generic { + int Tcl_UniCharToUtf(int ch, char *buf) +} +declare 325 generic { + char * Tcl_UtfAtIndex(CONST char *src, int index) +} +declare 326 generic { + int Tcl_UtfCharComplete(CONST char *src, int len) +} +declare 327 generic { + int Tcl_UtfBackslash(CONST char *src, int *readPtr, char *dst) +} +declare 328 generic { + char * Tcl_UtfFindFirst(CONST char *src, int ch) +} +declare 329 generic { + char * Tcl_UtfFindLast(CONST char *src, int ch) +} +declare 330 generic { + char * Tcl_UtfNext(CONST char *src) +} +declare 331 generic { + char * Tcl_UtfPrev(CONST char *src, CONST char *start) +} +declare 332 generic { + 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 generic { + char * Tcl_UtfToExternalDString(Tcl_Encoding encoding, CONST char *src, \ + int srcLen, Tcl_DString *dsPtr) +} +declare 334 generic { + int Tcl_UtfToLower(char *src) +} +declare 335 generic { + int Tcl_UtfToTitle(char *src) +} +declare 336 generic { + int Tcl_UtfToUniChar(CONST char *src, Tcl_UniChar *chPtr) +} +declare 337 generic { + int Tcl_UtfToUpper(char *src) +} +declare 338 generic { + int Tcl_WriteChars(Tcl_Channel chan, CONST char *src, int srcLen) +} +declare 339 generic { + int Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr) +} +declare 340 generic { + char * Tcl_GetString(Tcl_Obj *objPtr) +} +declare 341 generic { + char * Tcl_GetDefaultEncodingDir(void) +} +declare 342 generic { + void Tcl_SetDefaultEncodingDir(char *path) +} +declare 343 generic { + void Tcl_AlertNotifier(ClientData clientData) +} +declare 344 generic { + void Tcl_ServiceModeHook(int mode) +} +declare 345 generic { + int Tcl_UniCharIsAlnum(int ch) +} +declare 346 generic { + int Tcl_UniCharIsAlpha(int ch) +} +declare 347 generic { + int Tcl_UniCharIsDigit(int ch) +} +declare 348 generic { + int Tcl_UniCharIsLower(int ch) +} +declare 349 generic { + int Tcl_UniCharIsSpace(int ch) +} +declare 350 generic { + int Tcl_UniCharIsUpper(int ch) +} +declare 351 generic { + int Tcl_UniCharIsWordChar(int ch) +} +declare 352 generic { + int Tcl_UniCharLen(Tcl_UniChar *str) +} +declare 353 generic { + int Tcl_UniCharNcmp(const Tcl_UniChar *cs, const Tcl_UniChar *ct, size_t n) +} +declare 354 generic { + char * Tcl_UniCharToUtfDString(CONST Tcl_UniChar *string, int numChars, \ + Tcl_DString *dsPtr) +} +declare 355 generic { + Tcl_UniChar * Tcl_UtfToUniCharDString(CONST char *string, int length, \ + Tcl_DString *dsPtr) +} +declare 356 generic { + Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, Tcl_Obj *patObj, int flags) +} + +declare 357 generic { + Tcl_Obj *Tcl_EvalTokens (Tcl_Interp *interp, Tcl_Token *tokenPtr, \ + int count) +} +declare 358 generic { + void Tcl_FreeParse (Tcl_Parse *parsePtr) +} +declare 359 generic { + void Tcl_LogCommandInfo (Tcl_Interp *interp, char *script, \ + char *command, int length) +} +declare 360 generic { + int Tcl_ParseBraces (Tcl_Interp *interp, char *string, \ + int numBytes, Tcl_Parse *parsePtr,int append, char **termPtr) +} +declare 361 generic { + int Tcl_ParseCommand (Tcl_Interp *interp, char *string, int numBytes, \ + int nested, Tcl_Parse *parsePtr) +} +declare 362 generic { + int Tcl_ParseExpr(Tcl_Interp *interp, char *string, int numBytes, \ + Tcl_Parse *parsePtr) +} +declare 363 generic { + int Tcl_ParseQuotedString(Tcl_Interp *interp, char *string, int numBytes, \ + Tcl_Parse *parsePtr, int append, char **termPtr) +} +declare 364 generic { + int Tcl_ParseVarName (Tcl_Interp *interp, char *string, \ + int numBytes, Tcl_Parse *parsePtr, int append) +} +declare 365 generic { + char *Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr) +} +declare 366 generic { + int Tcl_Chdir(CONST char *dirName) +} + +############################################################################## + +# Define the platform specific public Tcl interface. These functions are +# only available on the designated platform. + +interface tclPlat + +###################### +# Windows declarations + +# 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 declarations + +# This is needed by the shells to handle Macintosh events. + +declare 0 mac { + void Tcl_MacSetEventProc(Tcl_MacConvertEventPtr procPtr) +} + +# These routines are useful for handling using scripts from resources +# in the application shell + +declare 1 mac { + char * Tcl_MacConvertTextResource(Handle resource) +} +declare 2 mac { + int Tcl_MacEvalResource(Tcl_Interp *interp, char *resourceName, \ + int resourceNumber, char *fileName) +} +declare 3 mac { + Handle Tcl_MacFindResource(Tcl_Interp *interp, long resourceType, \ + char *resourceName, int resourceNumber, char *resFileRef, \ + int * releaseIt) +} + +# These routines support the new OSType object type (i.e. the packed 4 +# character type and creator codes). + +declare 4 mac { + int Tcl_GetOSTypeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, \ + OSType *osTypePtr) +} +declare 5 mac { + void Tcl_SetOSTypeObj(Tcl_Obj *objPtr, OSType osType) +} +declare 6 mac { + Tcl_Obj * Tcl_NewOSTypeObj(OSType osType) +} + +# These are not in MSL 2.1.2, so we need to export them from the +# Tcl shared library. They are found in the compat directory +# except the panic routine which is found in tclMacPanic.h. + +declare 7 mac { + int strncasecmp(CONST char *s1, CONST char *s2, size_t n) +} +declare 8 mac { + int strcasecmp(CONST char *s1, CONST char *s2) +} Index: generic/tcl.h ================================================================== --- generic/tcl.h +++ generic/tcl.h @@ -3,47 +3,54 @@ * * 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) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1993-1996 Lucent Technologies. + * Copyright (c) 1994-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. * - * SCCS: @(#) tcl.h 1.326 97/11/20 12:40:43 + * RCS: @(#) $Id: tcl.h,v 1.1.2.23 1999/04/14 00:33:19 surles Exp $ */ #ifndef _TCL #define _TCL +/* + * 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 + * library/init.tcl (only if major.minor changes, not patchlevel) * unix/configure.in - * unix/pkginfo - * win/makefile.bc - * win/makefile.vc - * - * The release level should be 0 for alpha, 1 for beta, and 2 for - * final/patch. The release serial value is the number that follows the - * "a", "b", or "p" in the patch level; for example, if the patch level - * is 7.6b2, TCL_RELEASE_SERIAL is 2. It restarts at 1 whenever the - * release level is changed, except for the final release which is 0 - * (the first patch will start at 1). + * win/makefile.bc (only if major.minor changes, not patchlevel) + * win/makefile.vc (only if major.minor changes, not patchlevel) + * win/pkgIndex.tcl (for tclregNN.dll, not patchlevel) + * README + * mac/README + * win/README.binary + * win/README (only if major.minor changes, not patchlevel) + * unix/README (only if major.minor changes, not patchlevel) */ #define TCL_MAJOR_VERSION 8 -#define TCL_MINOR_VERSION 0 -#define TCL_RELEASE_LEVEL 2 -#define TCL_RELEASE_SERIAL 2 +#define TCL_MINOR_VERSION 1 +#define TCL_RELEASE_LEVEL TCL_BETA_RELEASE +#define TCL_RELEASE_SERIAL 3 -#define TCL_VERSION "8.0" -#define TCL_PATCH_LEVEL "8.0p2" +#define TCL_VERSION "8.1" +#define TCL_PATCH_LEVEL "8.1b3" /* * The following definitions set up the proper options for Windows * compilers. We use this method because there is no autoconf equivalent. */ @@ -65,17 +72,19 @@ # define HAS_STDARG 1 # endif # ifndef USE_PROTOTYPE # define USE_PROTOTYPE 1 # endif + +/* + * Under Windows we need to call Tcl_Alloc in all cases to avoid competing + * C run-time library issues. + */ + # ifndef USE_TCLALLOC # define USE_TCLALLOC 1 # endif -# ifndef STRINGIFY -# define STRINGIFY(x) STRINGIFY1(x) -# define STRINGIFY1(x) #x -# endif #endif /* __WIN32__ */ /* * The following definitions set up the proper options for Macintosh * compilers. We use this method because there is no autoconf equivalent. @@ -89,12 +98,64 @@ # define USE_TCLALLOC 1 # endif # ifndef NO_STRERROR # define NO_STRERROR 1 # endif +# define INLINE +#endif + +/* + * Utility macros: STRINGIFY takes an argument and wraps it in "" (double + * quotation marks), JOIN joins two arguments. + */ + +#define VERBATIM(x) x +#ifdef _MSC_VER +# define STRINGIFY(x) STRINGIFY1(x) +# define STRINGIFY1(x) #x +# define JOIN(a,b) JOIN1(a,b) +# define JOIN1(a,b) a##b +#else +# ifdef RESOURCE_INCLUDED +# define STRINGIFY(x) STRINGIFY1(x) +# define STRINGIFY1(x) #x +# define JOIN(a,b) JOIN1(a,b) +# define JOIN1(a,b) a##b +# else +# ifdef __STDC__ +# define STRINGIFY(x) #x +# define JOIN(a,b) a##b +# else +# define STRINGIFY(x) "x" +# define JOIN(a,b) VERBATIM(a)VERBATIM(b) +# endif +# endif +#endif + +/* + * 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 +/* + * Macros that eliminate the overhead of the thread synchronization + * functions when compiling without thread support. + */ + +#ifndef TCL_THREADS +#define Tcl_MutexLock(mutexPtr) +#define Tcl_MutexUnlock(mutexPtr) +#define Tcl_ConditionNotify(condPtr) +#define Tcl_ConditionWait(condPtr, mutexPtr, timePtr) +#endif /* TCL_THREADS */ + /* * A special definition used to allow this header file to be included * in resource files so that they can get obtain version information from * this file. Resource compilers don't like all the C stuff, like typedefs * and procedure declarations, that occur below. @@ -115,14 +176,18 @@ * string for use in the function definition. TCL_VARARGS_START * initializes the va_list data structure and returns the first argument. */ #if defined(__STDC__) || defined(HAS_STDARG) +# include + # 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) #else +# include + # ifdef __cplusplus # define TCL_VARARGS(type, name) (type name, ...) # define TCL_VARARGS_DEF(type, name) (type va_alist, ...) # else # define TCL_VARARGS(type, name) () @@ -130,17 +195,68 @@ # endif # define TCL_VARARGS_START(type, name, list) \ (va_start(list), va_arg(list, type)) #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. + */ + +#ifdef STATIC_BUILD +# define DLLIMPORT +# define DLLEXPORT +#else +# if defined(__WIN32__) && (defined(_MSC_VER) || (defined(__GNUC__) && defined(__declspec))) +# define DLLIMPORT __declspec(dllimport) +# define DLLEXPORT __declspec(dllexport) +# else +# define DLLIMPORT +# define DLLEXPORT +# endif +#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 + /* * Definitions that allow this header file to be used either with or * without ANSI C features like function prototypes. */ #undef _ANSI_ARGS_ #undef CONST +#ifndef INLINE +# define INLINE +#endif #if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) || defined(USE_PROTOTYPE) # define _USING_PROTOTYPES_ 1 # define _ANSI_ARGS_(x) x # define CONST const @@ -148,13 +264,13 @@ # define _ANSI_ARGS_(x) () # define CONST #endif #ifdef __cplusplus -# define EXTERN extern "C" +# define EXTERN extern "C" TCL_STORAGE_CLASS #else -# define EXTERN extern +# define EXTERN extern TCL_STORAGE_CLASS #endif /* * Macro to use instead of "void" for arguments that must have * type "void *" in ANSI C; maps them to type "char *" in @@ -233,13 +349,19 @@ } Tcl_Interp; typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler; typedef struct Tcl_Channel_ *Tcl_Channel; typedef struct Tcl_Command_ *Tcl_Command; +typedef struct Tcl_Condition_ *Tcl_Condition; +typedef struct Tcl_EncodingState_ *Tcl_EncodingState; +typedef struct Tcl_Encoding_ *Tcl_Encoding; typedef struct Tcl_Event Tcl_Event; +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; /* @@ -306,10 +428,15 @@ typedef void (Tcl_CmdTraceProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int level, char *command, Tcl_CmdProc *proc, ClientData cmdClientData, int argc, char *argv[])); typedef void (Tcl_DupInternalRepProc) _ANSI_ARGS_((struct Tcl_Obj *srcPtr, struct Tcl_Obj *dupPtr)); +typedef int (Tcl_EncodingConvertProc)_ANSI_ARGS_((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)_ANSI_ARGS_((ClientData clientData)); typedef int (Tcl_EventProc) _ANSI_ARGS_((Tcl_Event *evPtr, int flags)); typedef void (Tcl_EventCheckProc) _ANSI_ARGS_((ClientData clientData, int flags)); typedef int (Tcl_EventDeleteProc) _ANSI_ARGS_((Tcl_Event *evPtr, ClientData clientData)); @@ -325,12 +452,13 @@ Tcl_Interp *interp)); typedef int (Tcl_MathProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, Tcl_Value *args, Tcl_Value *resultPtr)); typedef void (Tcl_NamespaceDeleteProc) _ANSI_ARGS_((ClientData clientData)); typedef int (Tcl_ObjCmdProc) _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, struct Tcl_Obj * CONST objv[])); + Tcl_Interp *interp, int objc, struct Tcl_Obj *CONST objv[])); typedef int (Tcl_PackageInitProc) _ANSI_ARGS_((Tcl_Interp *interp)); +typedef void (Tcl_PanicProc) _ANSI_ARGS_(TCL_VARARGS(char *, format)); typedef void (Tcl_TcpAcceptProc) _ANSI_ARGS_((ClientData callbackData, Tcl_Channel chan, char *address, int port)); typedef void (Tcl_TimerProc) _ANSI_ARGS_((ClientData clientData)); typedef int (Tcl_SetFromAnyProc) _ANSI_ARGS_((Tcl_Interp *interp, struct Tcl_Obj *objPtr)); @@ -378,12 +506,12 @@ * 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 - * to get a pointer to the byte array as a - * readonly value. */ + * 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. */ Tcl_ObjType *typePtr; /* Denotes the object's type. Always * corresponds to the type of the object's * internal rep. NULL indicates the object @@ -430,27 +558,19 @@ ((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 + * When TCL_MEM_DEBUG is defined, the Tcl_New declarations are * overridden to call debugging versions of the object creation procedures. */ -EXTERN Tcl_Obj * Tcl_NewBooleanObj _ANSI_ARGS_((int boolValue)); -EXTERN Tcl_Obj * Tcl_NewDoubleObj _ANSI_ARGS_((double doubleValue)); -EXTERN Tcl_Obj * Tcl_NewIntObj _ANSI_ARGS_((int intValue)); -EXTERN Tcl_Obj * Tcl_NewListObj _ANSI_ARGS_((int objc, - Tcl_Obj *CONST objv[])); -EXTERN Tcl_Obj * Tcl_NewLongObj _ANSI_ARGS_((long longValue)); -EXTERN Tcl_Obj * Tcl_NewObj _ANSI_ARGS_((void)); -EXTERN Tcl_Obj * Tcl_NewStringObj _ANSI_ARGS_((char *bytes, - int length)); - #ifdef TCL_MEM_DEBUG # define Tcl_NewBooleanObj(val) \ Tcl_DbNewBooleanObj(val, __FILE__, __LINE__) +# define Tcl_NewByteArrayObj(bytes, len) \ + Tcl_DbNewByteArrayObj(bytes, len, __FILE__, __LINE__) # define Tcl_NewDoubleObj(val) \ Tcl_DbNewDoubleObj(val, __FILE__, __LINE__) # define Tcl_NewIntObj(val) \ Tcl_DbNewLongObj(val, __FILE__, __LINE__) # define Tcl_NewListObj(objc, objv) \ @@ -460,10 +580,27 @@ # define Tcl_NewObj() \ Tcl_DbNewObj(__FILE__, __LINE__) # define Tcl_NewStringObj(bytes, len) \ Tcl_DbNewStringObj(bytes, len, __FILE__, __LINE__) #endif /* TCL_MEM_DEBUG */ + +/* + * 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 tcl.h). @@ -583,16 +720,24 @@ #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 - * characters of buffer space required by Tcl_PrintDouble. + * 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 that may be passed to Tcl_ConvertElement to force it not to * output braces (careful! if you change this flag be sure to change * the definitions at the front of tclUtil.c). */ @@ -605,17 +750,18 @@ */ #define TCL_EXACT 1 /* - * Flag values passed to Tcl_RecordAndEval. + * Flag values passed to Tcl_RecordAndEval and/or Tcl_EvalObj. * WARNING: these bit choices must not conflict with the bit choices * for evalFlag bits in tclInt.h!! */ #define TCL_NO_EVAL 0x10000 #define TCL_EVAL_GLOBAL 0x20000 +#define TCL_EVAL_DIRECT 0x40000 /* * Special freeProc values that may be passed to Tcl_SetResult (see * the man page for details): */ @@ -636,11 +782,23 @@ #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_PARSE_PART1 0x400 +#define TCL_TRACE_ARRAY 0x800 + +/* + * 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: */ @@ -648,50 +806,10 @@ #define TCL_LINK_DOUBLE 2 #define TCL_LINK_BOOLEAN 3 #define TCL_LINK_STRING 4 #define TCL_LINK_READ_ONLY 0x80 -/* - * The following declarations either map ckalloc and ckfree to - * malloc and free, or they map them to procedures with all sorts - * of debugging hooks defined in tclCkalloc.c. - */ - -EXTERN char * Tcl_Alloc _ANSI_ARGS_((unsigned int size)); -EXTERN void Tcl_Free _ANSI_ARGS_((char *ptr)); -EXTERN char * Tcl_Realloc _ANSI_ARGS_((char *ptr, - unsigned int size)); - -#ifdef TCL_MEM_DEBUG - -# define Tcl_Alloc(x) Tcl_DbCkalloc(x, __FILE__, __LINE__) -# define Tcl_Free(x) Tcl_DbCkfree(x, __FILE__, __LINE__) -# define Tcl_Realloc(x,y) Tcl_DbCkrealloc((x), (y),__FILE__, __LINE__) -# define ckalloc(x) Tcl_DbCkalloc(x, __FILE__, __LINE__) -# define ckfree(x) Tcl_DbCkfree(x, __FILE__, __LINE__) -# define ckrealloc(x,y) Tcl_DbCkrealloc((x), (y),__FILE__, __LINE__) - -EXTERN int Tcl_DumpActiveMemory _ANSI_ARGS_((char *fileName)); -EXTERN void Tcl_ValidateAllMemory _ANSI_ARGS_((char *file, - int line)); - -#else - -# if USE_TCLALLOC -# define ckalloc(x) Tcl_Alloc(x) -# define ckfree(x) Tcl_Free(x) -# define ckrealloc(x,y) Tcl_Realloc(x,y) -# else -# define ckalloc(x) malloc(x) -# define ckfree(x) free(x) -# define ckrealloc(x,y) realloc(x,y) -# endif -# define Tcl_DumpActiveMemory(x) -# define Tcl_ValidateAllMemory(x,y) - -#endif /* TCL_MEM_DEBUG */ - /* * Forward declaration of Tcl_HashTable. Needed by some C++ compilers * to prevent errors when the forward reference to Tcl_HashTable is * encountered in the Tcl_HashEntry structure. */ @@ -878,18 +996,35 @@ #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) + /* * Typedefs for the various operations in a channel type: */ typedef int (Tcl_DriverBlockModeProc) _ANSI_ARGS_(( ClientData instanceData, int mode)); typedef int (Tcl_DriverCloseProc) _ANSI_ARGS_((ClientData instanceData, Tcl_Interp *interp)); +typedef int (Tcl_DriverClose2Proc) _ANSI_ARGS_((ClientData instanceData, + Tcl_Interp *interp, int flags)); typedef int (Tcl_DriverInputProc) _ANSI_ARGS_((ClientData instanceData, char *buf, int toRead, int *errorCodePtr)); typedef int (Tcl_DriverOutputProc) _ANSI_ARGS_((ClientData instanceData, char *buf, int toWrite, int *errorCodePtr)); typedef int (Tcl_DriverSeekProc) _ANSI_ARGS_((ClientData instanceData, @@ -904,10 +1039,47 @@ ClientData instanceData, int mask)); typedef int (Tcl_DriverGetHandleProc) _ANSI_ARGS_(( ClientData instanceData, int direction, ClientData *handlePtr)); +/* + * The following declarations either map ckalloc and ckfree to + * malloc and free, or they map them to procedures with all sorts + * of debugging hooks defined in tclCkalloc.c. + */ + +#ifdef TCL_MEM_DEBUG + +# define ckalloc(x) Tcl_DbCkalloc(x, __FILE__, __LINE__) +# define ckfree(x) Tcl_DbCkfree(x, __FILE__, __LINE__) +# define ckrealloc(x,y) Tcl_DbCkrealloc((x), (y),__FILE__, __LINE__) + +#else /* !TCL_MEM_DEBUG */ + +/* + * If USE_TCLALLOC is true, then we need to call Tcl_Alloc instead of + * the native malloc/free. The only time USE_TCLALLOC should not be + * true is when compiling the Tcl/Tk libraries on Unix systems. In this + * case we can safely call the native malloc/free directly as a performance + * optimization. + */ + +# if USE_TCLALLOC +# define ckalloc(x) Tcl_Alloc(x) +# define ckfree(x) Tcl_Free(x) +# define ckrealloc(x,y) Tcl_Realloc(x,y) +# else +# define ckalloc(x) malloc(x) +# define ckfree(x) free(x) +# define ckrealloc(x,y) realloc(x,y) +# endif +# define Tcl_InitMemory(x) +# define Tcl_DumpActiveMemory(x) +# define Tcl_ValidateAllMemory(x,y) + +#endif /* !TCL_MEM_DEBUG */ + /* * Enum for different end of line translation and recognition modes. */ typedef enum Tcl_EolTranslation { @@ -930,12 +1102,14 @@ * commands. This storage is owned by * channel type. */ Tcl_DriverBlockModeProc *blockModeProc; /* Set blocking mode for the * raw channel. May be NULL. */ - Tcl_DriverCloseProc *closeProc; /* Procedure to call to close - * the channel. */ + Tcl_DriverCloseProc *closeProc; /* Procedure to call to close the + * channel, or TCL_CLOSE2PROC if the + * close2Proc should be used + * instead. */ Tcl_DriverInputProc *inputProc; /* Procedure to call for input * on channel. */ Tcl_DriverOutputProc *outputProc; /* Procedure to call for output * on channel. */ Tcl_DriverSeekProc *seekProc; /* Procedure to call to seek @@ -947,10 +1121,14 @@ 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; /* Procedure to call to close the + * channel if the device supports + * closing the read & write sides + * independently. */ } Tcl_ChannelType; /* * The following flags determine whether the blockModeProc above should * set the channel into blocking or nonblocking mode. They are passed @@ -970,519 +1148,373 @@ TCL_PATH_RELATIVE, TCL_PATH_VOLUME_RELATIVE } Tcl_PathType; /* - * Exported Tcl procedures: + * 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; + /* Procedure to convert from external + * encoding into UTF-8. */ + Tcl_EncodingConvertProc *fromUtfProc; + /* Procedure to convert from UTF-8 into + * external encoding. */ + Tcl_EncodingFreeProc *freeProc; + /* If non-NULL, procedure to call when this + * encoding is deleted. */ + ClientData clientData; /* Arbitrary value associated with encoding + * type. Passed to conversion procedures. */ + 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 procedure 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 sonvert the source. + */ + +#define TCL_ENCODING_START 0x01 +#define TCL_ENCODING_END 0x02 +#define TCL_ENCODING_STOPONERROR 0x04 + +/* + *---------------------------------------------------------------- + * The following data structures and declarations are for the new + * Tcl parser. This stuff should all move to tcl.h eventually. + *---------------------------------------------------------------- + */ + +/* + * 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. */ + 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 a + * 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. + */ + +#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 + +/* + * 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 { + 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. */ + 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. */ + + /* + * The fields below are intended only for the private use of the + * parser. They should not be used by procedures that invoke + * Tcl_ParseCommand. + */ + + char *string; /* The original command string passed to + * Tcl_ParseCommand. */ + 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. */ + 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 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. + */ + +#define TCL_UTF_MAX 3 + +/* + * This represents a Unicode character. + */ + +typedef unsigned short Tcl_UniChar; + +/* + * Deprecated Tcl procedures: + */ + +#ifndef TCL_NO_DEPRECATED +#define Tcl_EvalObj(interp,objPtr) Tcl_EvalObjEx((interp),(objPtr),0) +#define Tcl_GlobalEvalObj(interp,objPtr) \ + Tcl_EvalObjEx((interp),(objPtr),TCL_EVAL_GLOBAL) +#endif + +/* + * These function have been renamed. The old names are deprecated, but we + * define these macros for backwards compatibilty. */ -EXTERN void Tcl_AddErrorInfo _ANSI_ARGS_((Tcl_Interp *interp, - char *message)); -EXTERN void Tcl_AddObjErrorInfo _ANSI_ARGS_((Tcl_Interp *interp, - char *message, int length)); -EXTERN void Tcl_AllowExceptions _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN int Tcl_AppendAllObjTypes _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Obj *objPtr)); -EXTERN void Tcl_AppendElement _ANSI_ARGS_((Tcl_Interp *interp, - char *string)); -EXTERN void Tcl_AppendResult _ANSI_ARGS_( - TCL_VARARGS(Tcl_Interp *,interp)); -EXTERN void Tcl_AppendToObj _ANSI_ARGS_((Tcl_Obj *objPtr, - char *bytes, int length)); -EXTERN void Tcl_AppendStringsToObj _ANSI_ARGS_( - TCL_VARARGS(Tcl_Obj *,interp)); -EXTERN int Tcl_AppInit _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN Tcl_AsyncHandler Tcl_AsyncCreate _ANSI_ARGS_((Tcl_AsyncProc *proc, - ClientData clientData)); -EXTERN void Tcl_AsyncDelete _ANSI_ARGS_((Tcl_AsyncHandler async)); -EXTERN int Tcl_AsyncInvoke _ANSI_ARGS_((Tcl_Interp *interp, - int code)); -EXTERN void Tcl_AsyncMark _ANSI_ARGS_((Tcl_AsyncHandler async)); -EXTERN int Tcl_AsyncReady _ANSI_ARGS_((void)); -EXTERN void Tcl_BackgroundError _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN char Tcl_Backslash _ANSI_ARGS_((CONST char *src, - int *readPtr)); -EXTERN int Tcl_BadChannelOption _ANSI_ARGS_((Tcl_Interp *interp, - char *optionName, char *optionList)); -EXTERN void Tcl_CallWhenDeleted _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_InterpDeleteProc *proc, - ClientData clientData)); -EXTERN void Tcl_CancelIdleCall _ANSI_ARGS_((Tcl_IdleProc *idleProc, - ClientData clientData)); #define Tcl_Ckalloc Tcl_Alloc #define Tcl_Ckfree Tcl_Free #define Tcl_Ckrealloc Tcl_Realloc -EXTERN int Tcl_Close _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan)); -EXTERN int Tcl_CommandComplete _ANSI_ARGS_((char *cmd)); -EXTERN char * Tcl_Concat _ANSI_ARGS_((int argc, char **argv)); -EXTERN Tcl_Obj * Tcl_ConcatObj _ANSI_ARGS_((int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tcl_ConvertCountedElement _ANSI_ARGS_((CONST char *src, - int length, char *dst, int flags)); -EXTERN int Tcl_ConvertElement _ANSI_ARGS_((CONST char *src, - char *dst, int flags)); -EXTERN int Tcl_ConvertToType _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, Tcl_ObjType *typePtr)); -EXTERN int Tcl_CreateAlias _ANSI_ARGS_((Tcl_Interp *slave, - char *slaveCmd, Tcl_Interp *target, - char *targetCmd, int argc, char **argv)); -EXTERN int Tcl_CreateAliasObj _ANSI_ARGS_((Tcl_Interp *slave, - char *slaveCmd, Tcl_Interp *target, - char *targetCmd, int objc, - Tcl_Obj *CONST objv[])); -EXTERN Tcl_Channel Tcl_CreateChannel _ANSI_ARGS_(( - Tcl_ChannelType *typePtr, char *chanName, - ClientData instanceData, int mask)); -EXTERN void Tcl_CreateChannelHandler _ANSI_ARGS_(( - Tcl_Channel chan, int mask, - Tcl_ChannelProc *proc, ClientData clientData)); -EXTERN void Tcl_CreateCloseHandler _ANSI_ARGS_(( - Tcl_Channel chan, Tcl_CloseProc *proc, - ClientData clientData)); -EXTERN Tcl_Command Tcl_CreateCommand _ANSI_ARGS_((Tcl_Interp *interp, - char *cmdName, Tcl_CmdProc *proc, - ClientData clientData, - Tcl_CmdDeleteProc *deleteProc)); -EXTERN void Tcl_CreateEventSource _ANSI_ARGS_(( - Tcl_EventSetupProc *setupProc, - Tcl_EventCheckProc *checkProc, - ClientData clientData)); -EXTERN void Tcl_CreateExitHandler _ANSI_ARGS_((Tcl_ExitProc *proc, - ClientData clientData)); -EXTERN void Tcl_CreateFileHandler _ANSI_ARGS_(( - int fd, int mask, Tcl_FileProc *proc, - ClientData clientData)); -EXTERN Tcl_Interp * Tcl_CreateInterp _ANSI_ARGS_((void)); -EXTERN void Tcl_CreateMathFunc _ANSI_ARGS_((Tcl_Interp *interp, - char *name, int numArgs, Tcl_ValueType *argTypes, - Tcl_MathProc *proc, ClientData clientData)); -EXTERN Tcl_Command Tcl_CreateObjCommand _ANSI_ARGS_(( - Tcl_Interp *interp, char *cmdName, - Tcl_ObjCmdProc *proc, ClientData clientData, - Tcl_CmdDeleteProc *deleteProc)); -EXTERN Tcl_Interp * Tcl_CreateSlave _ANSI_ARGS_((Tcl_Interp *interp, - char *slaveName, int isSafe)); -EXTERN Tcl_TimerToken Tcl_CreateTimerHandler _ANSI_ARGS_((int milliseconds, - Tcl_TimerProc *proc, ClientData clientData)); -EXTERN Tcl_Trace Tcl_CreateTrace _ANSI_ARGS_((Tcl_Interp *interp, - int level, Tcl_CmdTraceProc *proc, - ClientData clientData)); -EXTERN char * Tcl_DbCkalloc _ANSI_ARGS_((unsigned int size, - char *file, int line)); -EXTERN int Tcl_DbCkfree _ANSI_ARGS_((char *ptr, - char *file, int line)); -EXTERN char * Tcl_DbCkrealloc _ANSI_ARGS_((char *ptr, - unsigned int size, char *file, int line)); -EXTERN void Tcl_DbDecrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr, - char *file, int line)); -EXTERN void Tcl_DbIncrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr, - char *file, int line)); -EXTERN int Tcl_DbIsShared _ANSI_ARGS_((Tcl_Obj *objPtr, - char *file, int line)); -EXTERN Tcl_Obj * Tcl_DbNewBooleanObj _ANSI_ARGS_((int boolValue, - char *file, int line)); -EXTERN Tcl_Obj * Tcl_DbNewDoubleObj _ANSI_ARGS_((double doubleValue, - char *file, int line)); -EXTERN Tcl_Obj * Tcl_DbNewListObj _ANSI_ARGS_((int objc, - Tcl_Obj *CONST objv[], char *file, int line)); -EXTERN Tcl_Obj * Tcl_DbNewLongObj _ANSI_ARGS_((long longValue, - char *file, int line)); -EXTERN Tcl_Obj * Tcl_DbNewObj _ANSI_ARGS_((char *file, int line)); -EXTERN Tcl_Obj * Tcl_DbNewStringObj _ANSI_ARGS_((char *bytes, - int length, char *file, int line)); -EXTERN void Tcl_DeleteAssocData _ANSI_ARGS_((Tcl_Interp *interp, - char *name)); -EXTERN int Tcl_DeleteCommand _ANSI_ARGS_((Tcl_Interp *interp, - char *cmdName)); -EXTERN int Tcl_DeleteCommandFromToken _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Command command)); -EXTERN void Tcl_DeleteChannelHandler _ANSI_ARGS_(( - Tcl_Channel chan, Tcl_ChannelProc *proc, - ClientData clientData)); -EXTERN void Tcl_DeleteCloseHandler _ANSI_ARGS_(( - Tcl_Channel chan, Tcl_CloseProc *proc, - ClientData clientData)); -EXTERN void Tcl_DeleteEvents _ANSI_ARGS_(( - Tcl_EventDeleteProc *proc, - ClientData clientData)); -EXTERN void Tcl_DeleteEventSource _ANSI_ARGS_(( - Tcl_EventSetupProc *setupProc, - Tcl_EventCheckProc *checkProc, - ClientData clientData)); -EXTERN void Tcl_DeleteExitHandler _ANSI_ARGS_((Tcl_ExitProc *proc, - ClientData clientData)); -EXTERN void Tcl_DeleteFileHandler _ANSI_ARGS_((int fd)); -EXTERN void Tcl_DeleteHashEntry _ANSI_ARGS_(( - Tcl_HashEntry *entryPtr)); -EXTERN void Tcl_DeleteHashTable _ANSI_ARGS_(( - Tcl_HashTable *tablePtr)); -EXTERN void Tcl_DeleteInterp _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN void Tcl_DeleteTimerHandler _ANSI_ARGS_(( - Tcl_TimerToken token)); -EXTERN void Tcl_DeleteTrace _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Trace trace)); -EXTERN void Tcl_DetachPids _ANSI_ARGS_((int numPids, Tcl_Pid *pidPtr)); -EXTERN void Tcl_DontCallWhenDeleted _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, - ClientData clientData)); -EXTERN int Tcl_DoOneEvent _ANSI_ARGS_((int flags)); -EXTERN void Tcl_DoWhenIdle _ANSI_ARGS_((Tcl_IdleProc *proc, - ClientData clientData)); -EXTERN char * Tcl_DStringAppend _ANSI_ARGS_((Tcl_DString *dsPtr, - CONST char *string, int length)); -EXTERN char * Tcl_DStringAppendElement _ANSI_ARGS_(( - Tcl_DString *dsPtr, CONST char *string)); -EXTERN void Tcl_DStringEndSublist _ANSI_ARGS_((Tcl_DString *dsPtr)); -EXTERN void Tcl_DStringFree _ANSI_ARGS_((Tcl_DString *dsPtr)); -EXTERN void Tcl_DStringGetResult _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_DString *dsPtr)); -EXTERN void Tcl_DStringInit _ANSI_ARGS_((Tcl_DString *dsPtr)); -EXTERN void Tcl_DStringResult _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_DString *dsPtr)); -EXTERN void Tcl_DStringSetLength _ANSI_ARGS_((Tcl_DString *dsPtr, - int length)); -EXTERN void Tcl_DStringStartSublist _ANSI_ARGS_(( - Tcl_DString *dsPtr)); -EXTERN Tcl_Obj * Tcl_DuplicateObj _ANSI_ARGS_((Tcl_Obj *objPtr)); -EXTERN int Tcl_Eof _ANSI_ARGS_((Tcl_Channel chan)); -EXTERN char * Tcl_ErrnoId _ANSI_ARGS_((void)); -EXTERN char * Tcl_ErrnoMsg _ANSI_ARGS_((int err)); -EXTERN int Tcl_Eval _ANSI_ARGS_((Tcl_Interp *interp, - char *string)); -EXTERN int Tcl_EvalFile _ANSI_ARGS_((Tcl_Interp *interp, - char *fileName)); -EXTERN void Tcl_EventuallyFree _ANSI_ARGS_((ClientData clientData, - Tcl_FreeProc *freeProc)); -EXTERN int Tcl_EvalObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr)); -EXTERN void Tcl_Exit _ANSI_ARGS_((int status)); -EXTERN int Tcl_ExposeCommand _ANSI_ARGS_((Tcl_Interp *interp, - char *hiddenCmdToken, char *cmdName)); -EXTERN int Tcl_ExprBoolean _ANSI_ARGS_((Tcl_Interp *interp, - char *string, int *ptr)); -EXTERN int Tcl_ExprBooleanObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, int *ptr)); -EXTERN int Tcl_ExprDouble _ANSI_ARGS_((Tcl_Interp *interp, - char *string, double *ptr)); -EXTERN int Tcl_ExprDoubleObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, double *ptr)); -EXTERN int Tcl_ExprLong _ANSI_ARGS_((Tcl_Interp *interp, - char *string, long *ptr)); -EXTERN int Tcl_ExprLongObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, long *ptr)); -EXTERN int Tcl_ExprObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr)); -EXTERN int Tcl_ExprString _ANSI_ARGS_((Tcl_Interp *interp, - char *string)); -EXTERN void Tcl_Finalize _ANSI_ARGS_((void)); -EXTERN void Tcl_FindExecutable _ANSI_ARGS_((char *argv0)); -EXTERN Tcl_HashEntry * Tcl_FirstHashEntry _ANSI_ARGS_(( - Tcl_HashTable *tablePtr, - Tcl_HashSearch *searchPtr)); -EXTERN int Tcl_Flush _ANSI_ARGS_((Tcl_Channel chan)); -EXTERN void TclFreeObj _ANSI_ARGS_((Tcl_Obj *objPtr)); -EXTERN void Tcl_FreeResult _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN int Tcl_GetAlias _ANSI_ARGS_((Tcl_Interp *interp, - char *slaveCmd, Tcl_Interp **targetInterpPtr, - char **targetCmdPtr, int *argcPtr, - char ***argvPtr)); -EXTERN int Tcl_GetAliasObj _ANSI_ARGS_((Tcl_Interp *interp, - char *slaveCmd, Tcl_Interp **targetInterpPtr, - char **targetCmdPtr, int *objcPtr, - Tcl_Obj ***objv)); -EXTERN ClientData Tcl_GetAssocData _ANSI_ARGS_((Tcl_Interp *interp, - char *name, Tcl_InterpDeleteProc **procPtr)); -EXTERN int Tcl_GetBoolean _ANSI_ARGS_((Tcl_Interp *interp, - char *string, int *boolPtr)); -EXTERN int Tcl_GetBooleanFromObj _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Obj *objPtr, - int *boolPtr)); -EXTERN Tcl_Channel Tcl_GetChannel _ANSI_ARGS_((Tcl_Interp *interp, - char *chanName, int *modePtr)); -EXTERN int Tcl_GetChannelBufferSize _ANSI_ARGS_(( - Tcl_Channel chan)); -EXTERN int Tcl_GetChannelHandle _ANSI_ARGS_((Tcl_Channel chan, - int direction, ClientData *handlePtr)); -EXTERN ClientData Tcl_GetChannelInstanceData _ANSI_ARGS_(( - Tcl_Channel chan)); -EXTERN int Tcl_GetChannelMode _ANSI_ARGS_((Tcl_Channel chan)); -EXTERN char * Tcl_GetChannelName _ANSI_ARGS_((Tcl_Channel chan)); -EXTERN int Tcl_GetChannelOption _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan, char *optionName, - Tcl_DString *dsPtr)); -EXTERN Tcl_ChannelType * Tcl_GetChannelType _ANSI_ARGS_((Tcl_Channel chan)); -EXTERN int Tcl_GetCommandInfo _ANSI_ARGS_((Tcl_Interp *interp, - char *cmdName, Tcl_CmdInfo *infoPtr)); -EXTERN char * Tcl_GetCommandName _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Command command)); -EXTERN char * Tcl_GetCwd _ANSI_ARGS_((char *buf, int len)); -EXTERN int Tcl_GetDouble _ANSI_ARGS_((Tcl_Interp *interp, - char *string, double *doublePtr)); -EXTERN int Tcl_GetDoubleFromObj _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Obj *objPtr, - double *doublePtr)); -EXTERN int Tcl_GetErrno _ANSI_ARGS_((void)); -EXTERN int Tcl_GetErrorLine _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN char * Tcl_GetHostName _ANSI_ARGS_((void)); -EXTERN int Tcl_GetIndexFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, char **tablePtr, char *msg, - int flags, int *indexPtr)); -EXTERN int Tcl_GetInt _ANSI_ARGS_((Tcl_Interp *interp, - char *string, int *intPtr)); -EXTERN int Tcl_GetInterpPath _ANSI_ARGS_((Tcl_Interp *askInterp, - Tcl_Interp *slaveInterp)); -EXTERN int Tcl_GetIntFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, int *intPtr)); -EXTERN int Tcl_GetLongFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, long *longPtr)); -EXTERN Tcl_Interp * Tcl_GetMaster _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN Tcl_Obj * Tcl_GetObjResult _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN Tcl_ObjType * Tcl_GetObjType _ANSI_ARGS_((char *typeName)); -EXTERN int Tcl_GetOpenFile _ANSI_ARGS_((Tcl_Interp *interp, - char *string, int write, int checkUsage, - ClientData *filePtr)); -EXTERN Tcl_Command Tcl_GetOriginalCommand _ANSI_ARGS_(( - Tcl_Command command)); -EXTERN Tcl_PathType Tcl_GetPathType _ANSI_ARGS_((char *path)); -EXTERN int Tcl_Gets _ANSI_ARGS_((Tcl_Channel chan, - Tcl_DString *dsPtr)); -EXTERN int Tcl_GetsObj _ANSI_ARGS_((Tcl_Channel chan, - Tcl_Obj *objPtr)); -EXTERN int Tcl_GetServiceMode _ANSI_ARGS_((void)); -EXTERN Tcl_Interp * Tcl_GetSlave _ANSI_ARGS_((Tcl_Interp *interp, - char *slaveName)); -EXTERN Tcl_Channel Tcl_GetStdChannel _ANSI_ARGS_((int type)); -EXTERN char * Tcl_GetStringFromObj _ANSI_ARGS_((Tcl_Obj *objPtr, - int *lengthPtr)); -EXTERN char * Tcl_GetStringResult _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN char * Tcl_GetVar _ANSI_ARGS_((Tcl_Interp *interp, - char *varName, int flags)); -EXTERN char * Tcl_GetVar2 _ANSI_ARGS_((Tcl_Interp *interp, - char *part1, char *part2, int flags)); -EXTERN int Tcl_GlobalEval _ANSI_ARGS_((Tcl_Interp *interp, - char *command)); -EXTERN int Tcl_GlobalEvalObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr)); -EXTERN char * Tcl_HashStats _ANSI_ARGS_((Tcl_HashTable *tablePtr)); -EXTERN int Tcl_HideCommand _ANSI_ARGS_((Tcl_Interp *interp, - char *cmdName, char *hiddenCmdToken)); -EXTERN int Tcl_Init _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN void Tcl_InitHashTable _ANSI_ARGS_((Tcl_HashTable *tablePtr, - int keyType)); -EXTERN void Tcl_InitMemory _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN int Tcl_InputBlocked _ANSI_ARGS_((Tcl_Channel chan)); -EXTERN int Tcl_InputBuffered _ANSI_ARGS_((Tcl_Channel chan)); -EXTERN int Tcl_InterpDeleted _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN int Tcl_IsSafe _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN void Tcl_InvalidateStringRep _ANSI_ARGS_(( - Tcl_Obj *objPtr)); -EXTERN char * Tcl_JoinPath _ANSI_ARGS_((int argc, char **argv, - Tcl_DString *resultPtr)); -EXTERN int Tcl_LinkVar _ANSI_ARGS_((Tcl_Interp *interp, - char *varName, char *addr, int type)); -EXTERN int Tcl_ListObjAppendList _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Obj *listPtr, - Tcl_Obj *elemListPtr)); -EXTERN int Tcl_ListObjAppendElement _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Obj *listPtr, - Tcl_Obj *objPtr)); -EXTERN int Tcl_ListObjGetElements _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Obj *listPtr, - int *objcPtr, Tcl_Obj ***objvPtr)); -EXTERN int Tcl_ListObjIndex _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *listPtr, int index, - Tcl_Obj **objPtrPtr)); -EXTERN int Tcl_ListObjLength _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *listPtr, int *intPtr)); -EXTERN int Tcl_ListObjReplace _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *listPtr, int first, int count, - int objc, Tcl_Obj *CONST objv[])); -EXTERN void Tcl_Main _ANSI_ARGS_((int argc, char **argv, - Tcl_AppInitProc *appInitProc)); -EXTERN Tcl_Channel Tcl_MakeFileChannel _ANSI_ARGS_((ClientData handle, - int mode)); -EXTERN int Tcl_MakeSafe _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN Tcl_Channel Tcl_MakeTcpClientChannel _ANSI_ARGS_(( - ClientData tcpSocket)); -EXTERN char * Tcl_Merge _ANSI_ARGS_((int argc, char **argv)); -EXTERN Tcl_HashEntry * Tcl_NextHashEntry _ANSI_ARGS_(( - Tcl_HashSearch *searchPtr)); -EXTERN void Tcl_NotifyChannel _ANSI_ARGS_((Tcl_Channel channel, - int mask)); -EXTERN Tcl_Obj * Tcl_ObjGetVar2 _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, - int flags)); -EXTERN Tcl_Obj * Tcl_ObjSetVar2 _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, - Tcl_Obj *newValuePtr, int flags)); -EXTERN Tcl_Channel Tcl_OpenCommandChannel _ANSI_ARGS_(( - Tcl_Interp *interp, int argc, char **argv, - int flags)); -EXTERN Tcl_Channel Tcl_OpenFileChannel _ANSI_ARGS_((Tcl_Interp *interp, - char *fileName, char *modeString, - int permissions)); -EXTERN Tcl_Channel Tcl_OpenTcpClient _ANSI_ARGS_((Tcl_Interp *interp, - int port, char *address, char *myaddr, - int myport, int async)); -EXTERN Tcl_Channel Tcl_OpenTcpServer _ANSI_ARGS_((Tcl_Interp *interp, - int port, char *host, - Tcl_TcpAcceptProc *acceptProc, - ClientData callbackData)); -EXTERN char * Tcl_ParseVar _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char **termPtr)); -EXTERN int Tcl_PkgProvide _ANSI_ARGS_((Tcl_Interp *interp, - char *name, char *version)); -EXTERN char * Tcl_PkgRequire _ANSI_ARGS_((Tcl_Interp *interp, - char *name, char *version, int exact)); -EXTERN char * Tcl_PosixError _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN void Tcl_Preserve _ANSI_ARGS_((ClientData data)); -EXTERN void Tcl_PrintDouble _ANSI_ARGS_((Tcl_Interp *interp, - double value, char *dst)); -EXTERN int Tcl_PutEnv _ANSI_ARGS_((CONST char *string)); -EXTERN void Tcl_QueueEvent _ANSI_ARGS_((Tcl_Event *evPtr, - Tcl_QueuePosition position)); -EXTERN int Tcl_Read _ANSI_ARGS_((Tcl_Channel chan, - char *bufPtr, int toRead)); -EXTERN void Tcl_ReapDetachedProcs _ANSI_ARGS_((void)); -EXTERN int Tcl_RecordAndEval _ANSI_ARGS_((Tcl_Interp *interp, - char *cmd, int flags)); -EXTERN int Tcl_RecordAndEvalObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *cmdPtr, int flags)); -EXTERN Tcl_RegExp Tcl_RegExpCompile _ANSI_ARGS_((Tcl_Interp *interp, - char *string)); -EXTERN int Tcl_RegExpExec _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_RegExp regexp, char *string, char *start)); -EXTERN int Tcl_RegExpMatch _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *pattern)); -EXTERN void Tcl_RegExpRange _ANSI_ARGS_((Tcl_RegExp regexp, - int index, char **startPtr, char **endPtr)); -EXTERN void Tcl_RegisterChannel _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan)); -EXTERN void Tcl_RegisterObjType _ANSI_ARGS_(( - Tcl_ObjType *typePtr)); -EXTERN void Tcl_Release _ANSI_ARGS_((ClientData clientData)); -EXTERN void Tcl_RestartIdleTimer _ANSI_ARGS_((void)); -EXTERN void Tcl_ResetResult _ANSI_ARGS_((Tcl_Interp *interp)); #define Tcl_Return Tcl_SetResult -EXTERN int Tcl_ScanCountedElement _ANSI_ARGS_((CONST char *string, - int length, int *flagPtr)); -EXTERN int Tcl_ScanElement _ANSI_ARGS_((CONST char *string, - int *flagPtr)); -EXTERN int Tcl_Seek _ANSI_ARGS_((Tcl_Channel chan, - int offset, int mode)); -EXTERN int Tcl_ServiceAll _ANSI_ARGS_((void)); -EXTERN int Tcl_ServiceEvent _ANSI_ARGS_((int flags)); -EXTERN void Tcl_SetAssocData _ANSI_ARGS_((Tcl_Interp *interp, - char *name, Tcl_InterpDeleteProc *proc, - ClientData clientData)); -EXTERN void Tcl_SetBooleanObj _ANSI_ARGS_((Tcl_Obj *objPtr, - int boolValue)); -EXTERN void Tcl_SetChannelBufferSize _ANSI_ARGS_(( - Tcl_Channel chan, int sz)); -EXTERN int Tcl_SetChannelOption _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Channel chan, - char *optionName, char *newValue)); -EXTERN int Tcl_SetCommandInfo _ANSI_ARGS_((Tcl_Interp *interp, - char *cmdName, Tcl_CmdInfo *infoPtr)); -EXTERN void Tcl_SetDoubleObj _ANSI_ARGS_((Tcl_Obj *objPtr, - double doubleValue)); -EXTERN void Tcl_SetErrno _ANSI_ARGS_((int err)); -EXTERN void Tcl_SetErrorCode _ANSI_ARGS_( - TCL_VARARGS(Tcl_Interp *,arg1)); -EXTERN void Tcl_SetIntObj _ANSI_ARGS_((Tcl_Obj *objPtr, - int intValue)); -EXTERN void Tcl_SetListObj _ANSI_ARGS_((Tcl_Obj *objPtr, - int objc, Tcl_Obj *CONST objv[])); -EXTERN void Tcl_SetLongObj _ANSI_ARGS_((Tcl_Obj *objPtr, - long longValue)); -EXTERN void Tcl_SetMaxBlockTime _ANSI_ARGS_((Tcl_Time *timePtr)); -EXTERN void Tcl_SetObjErrorCode _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *errorObjPtr)); -EXTERN void Tcl_SetObjLength _ANSI_ARGS_((Tcl_Obj *objPtr, - int length)); -EXTERN void Tcl_SetObjResult _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *resultObjPtr)); -EXTERN void Tcl_SetPanicProc _ANSI_ARGS_((void (*proc) - _ANSI_ARGS_(TCL_VARARGS(char *, format)))); -EXTERN int Tcl_SetRecursionLimit _ANSI_ARGS_((Tcl_Interp *interp, - int depth)); -EXTERN void Tcl_SetResult _ANSI_ARGS_((Tcl_Interp *interp, - char *string, Tcl_FreeProc *freeProc)); -EXTERN int Tcl_SetServiceMode _ANSI_ARGS_((int mode)); -EXTERN void Tcl_SetStdChannel _ANSI_ARGS_((Tcl_Channel channel, - int type)); -EXTERN void Tcl_SetStringObj _ANSI_ARGS_((Tcl_Obj *objPtr, - char *bytes, int length)); -EXTERN void Tcl_SetTimer _ANSI_ARGS_((Tcl_Time *timePtr)); -EXTERN char * Tcl_SetVar _ANSI_ARGS_((Tcl_Interp *interp, - char *varName, char *newValue, int flags)); -EXTERN char * Tcl_SetVar2 _ANSI_ARGS_((Tcl_Interp *interp, - char *part1, char *part2, char *newValue, - int flags)); -EXTERN char * Tcl_SignalId _ANSI_ARGS_((int sig)); -EXTERN char * Tcl_SignalMsg _ANSI_ARGS_((int sig)); -EXTERN void Tcl_Sleep _ANSI_ARGS_((int ms)); -EXTERN void Tcl_SourceRCFile _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN int Tcl_SplitList _ANSI_ARGS_((Tcl_Interp *interp, - char *list, int *argcPtr, char ***argvPtr)); -EXTERN void Tcl_SplitPath _ANSI_ARGS_((char *path, - int *argcPtr, char ***argvPtr)); -EXTERN void Tcl_StaticPackage _ANSI_ARGS_((Tcl_Interp *interp, - char *pkgName, Tcl_PackageInitProc *initProc, - Tcl_PackageInitProc *safeInitProc)); -EXTERN int Tcl_StringMatch _ANSI_ARGS_((char *string, - char *pattern)); -EXTERN int Tcl_Tell _ANSI_ARGS_((Tcl_Channel chan)); #define Tcl_TildeSubst Tcl_TranslateFileName -EXTERN int Tcl_TraceVar _ANSI_ARGS_((Tcl_Interp *interp, - char *varName, int flags, Tcl_VarTraceProc *proc, - ClientData clientData)); -EXTERN int Tcl_TraceVar2 _ANSI_ARGS_((Tcl_Interp *interp, - char *part1, char *part2, int flags, - Tcl_VarTraceProc *proc, ClientData clientData)); -EXTERN char * Tcl_TranslateFileName _ANSI_ARGS_((Tcl_Interp *interp, - char *name, Tcl_DString *bufferPtr)); -EXTERN int Tcl_Ungets _ANSI_ARGS_((Tcl_Channel chan, char *str, - int len, int atHead)); -EXTERN void Tcl_UnlinkVar _ANSI_ARGS_((Tcl_Interp *interp, - char *varName)); -EXTERN int Tcl_UnregisterChannel _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan)); -EXTERN int Tcl_UnsetVar _ANSI_ARGS_((Tcl_Interp *interp, - char *varName, int flags)); -EXTERN int Tcl_UnsetVar2 _ANSI_ARGS_((Tcl_Interp *interp, - char *part1, char *part2, int flags)); -EXTERN void Tcl_UntraceVar _ANSI_ARGS_((Tcl_Interp *interp, - char *varName, int flags, Tcl_VarTraceProc *proc, - ClientData clientData)); -EXTERN void Tcl_UntraceVar2 _ANSI_ARGS_((Tcl_Interp *interp, - char *part1, char *part2, int flags, - Tcl_VarTraceProc *proc, ClientData clientData)); -EXTERN void Tcl_UpdateLinkedVar _ANSI_ARGS_((Tcl_Interp *interp, - char *varName)); -EXTERN int Tcl_UpVar _ANSI_ARGS_((Tcl_Interp *interp, - char *frameName, char *varName, - char *localName, int flags)); -EXTERN int Tcl_UpVar2 _ANSI_ARGS_((Tcl_Interp *interp, - char *frameName, char *part1, char *part2, - char *localName, int flags)); -EXTERN int Tcl_VarEval _ANSI_ARGS_( - TCL_VARARGS(Tcl_Interp *,interp)); -EXTERN ClientData Tcl_VarTraceInfo _ANSI_ARGS_((Tcl_Interp *interp, - char *varName, int flags, - Tcl_VarTraceProc *procPtr, - ClientData prevClientData)); -EXTERN ClientData Tcl_VarTraceInfo2 _ANSI_ARGS_((Tcl_Interp *interp, - char *part1, char *part2, int flags, - Tcl_VarTraceProc *procPtr, - ClientData prevClientData)); -EXTERN int Tcl_WaitForEvent _ANSI_ARGS_((Tcl_Time *timePtr)); -EXTERN Tcl_Pid Tcl_WaitPid _ANSI_ARGS_((Tcl_Pid pid, int *statPtr, - int options)); -EXTERN int Tcl_Write _ANSI_ARGS_((Tcl_Channel chan, - char *s, int slen)); -EXTERN void Tcl_WrongNumArgs _ANSI_ARGS_((Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[], char *message)); +#define panic Tcl_Panic +#define panicVA Tcl_PanicVA + +/* + * 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 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. + */ + +EXTERN char * Tcl_InitStubs _ANSI_ARGS_((Tcl_Interp *interp, + char *version, int exact)); + +#ifndef USE_TCL_STUBS + +/* + * When not using stubs, make it a macro. + */ + +#define Tcl_InitStubs(interp, version, exact) \ + Tcl_PkgRequire(interp, "Tcl", version, exact) + +#endif + + +/* + * Include the public function declarations that are accessible via + * the stubs table. + */ + +#include "tclDecls.h" + +/* + * Public functions that are not accessible via the stubs table. + */ + +EXTERN void Tcl_Main _ANSI_ARGS_((int argc, char **argv, + Tcl_AppInitProc *appInitProc)); + +/* + * 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 + */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS + +EXTERN int Tcl_AppInit _ANSI_ARGS_((Tcl_Interp *interp)); #endif /* RESOURCE_INCLUDED */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + #endif /* _TCL */ Index: generic/tclAlloc.c ================================================================== --- generic/tclAlloc.c +++ generic/tclAlloc.c @@ -6,21 +6,24 @@ * 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. * - * SCCS: @(#) tclAlloc.c 1.4 97/08/11 18:45:38 + * RCS: @(#) $Id: tclAlloc.c,v 1.1.2.7 1999/03/25 00:34:15 redman Exp $ */ #include "tclInt.h" #include "tclPort.h" + +#if USE_TCLALLOC #ifdef TCL_DEBUG # define DEBUG /* #define MSTATS */ # define RCHECK @@ -27,11 +30,11 @@ #endif typedef unsigned long caddr_t; /* - * The overhead on a block is at least 4 bytes. When free, this space + * 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). @@ -39,25 +42,27 @@ * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern. */ union overhead { union overhead *ov_next; /* when free */ + unsigned char ov_padding[8]; /* Ensure the structure is 8-byte aligned. */ struct { unsigned char ovu_magic0; /* magic number */ unsigned char ovu_index; /* bucket # */ unsigned char ovu_unused; /* unused */ unsigned char ovu_magic1; /* other magic number */ #ifdef RCHECK unsigned short ovu_rmagic; /* range magic number */ unsigned long ovu_size; /* actual block size */ + unsigned short ovu_unused2; /* padding to 8-byte align */ #endif } ovu; #define ov_magic0 ovu.ovu_magic0 #define ov_magic1 ovu.ovu_magic1 #define ov_index ovu.ovu_index #define ov_rmagic ovu.ovu_rmagic -#define ov_size ovu.ovu_size +#define ov_size ovu.ovu_size }; #define MAGIC 0xef /* magic # on accounting info */ #define RMAGIC 0x5555 /* magic # on range info */ @@ -77,10 +82,40 @@ */ #define NBUCKETS 13 #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 TclpMutex allocMutex; +#endif +static int allocInit = 0; + #ifdef MSTATS /* * nmalloc[i] is the difference between the number of mallocs and frees @@ -102,10 +137,93 @@ /* * Prototypes for functions used only in this file. */ static void MoreCore _ANSI_ARGS_((int bucket)); + + +/* + *------------------------------------------------------------------------- + * + * TclInitAlloc -- + * + * Initialize the memory system. + * + * Results: + * None. + * + * Side effects: + * Initialize the mutex used to serialize allocations. + * + *------------------------------------------------------------------------- + */ + +void +TclInitAlloc() +{ + if (!allocInit) { + allocInit = 1; + TclpMutexInit(&allocMutex); + } +} + +/* + *------------------------------------------------------------------------- + * + * 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() +{ + int i; + struct block *blockPtr, *nextPtr; + + TclpMutexLock(&allocMutex); + 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 < NBUCKETS; i++) { + nextf[i] = NULL; +#ifdef MSTATS + nmalloc[i] = 0; +#endif + } +#ifdef MSTATS + nmalloc[i] = 0; +#endif + TclpMutexUnlock(&allocMutex); +} /* *---------------------------------------------------------------------- * * TclpAlloc -- @@ -120,25 +238,45 @@ * *---------------------------------------------------------------------- */ char * -TclpAlloc( - unsigned int nbytes) /* Number of bytes to allocate. */ +TclpAlloc(nbytes) + unsigned int nbytes; /* Number of bytes to allocate. */ { register union overhead *op; register long bucket; register unsigned amt; + struct block *bigBlockPtr; + + if (!allocInit) { + /* + * We have to make the "self initializing" because Tcl_Alloc + * may be used before any other part of Tcl. E.g., see + * main() for tclsh! + */ + allocInit = 1; + TclpMutexInit(&allocMutex); + } + TclpMutexLock(&allocMutex); /* * First the simple case: we simple allocate big blocks directly */ if (nbytes + OVERHEAD >= MAXMALLOC) { - op = (union overhead *)TclpSysAlloc(nbytes+OVERHEAD, 0); - if (op == NULL) { + bigBlockPtr = (struct block *) TclpSysAlloc((unsigned) + (sizeof(struct block) + OVERHEAD + nbytes), 0); + if (bigBlockPtr == NULL) { + TclpMutexUnlock(&allocMutex); return NULL; } + bigBlockPtr->nextPtr = bigBlocks.nextPtr; + bigBlocks.nextPtr = bigBlockPtr; + bigBlockPtr->prevPtr = &bigBlocks; + bigBlockPtr->nextPtr->prevPtr = bigBlockPtr; + + op = (union overhead *) (bigBlockPtr + 1); op->ov_magic0 = op->ov_magic1 = MAGIC; op->ov_index = 0xff; #ifdef MSTATS nmalloc[NBUCKETS]++; #endif @@ -149,10 +287,11 @@ */ op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); op->ov_rmagic = RMAGIC; *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; #endif + TclpMutexUnlock(&allocMutex); return (void *)(op+1); } /* * Convert amount of memory requested into closest block size * stored in hash buckets which satisfies request. @@ -166,10 +305,11 @@ bucket = 1; #endif while (nbytes + OVERHEAD > amt) { amt <<= 1; if (amt == 0) { + TclpMutexUnlock(&allocMutex); return (NULL); } bucket++; } ASSERT( bucket < NBUCKETS ); @@ -179,10 +319,11 @@ * request more memory from the system. */ if ((op = nextf[bucket]) == NULL) { MoreCore(bucket); if ((op = nextf[bucket]) == NULL) { + TclpMutexUnlock(&allocMutex); return (NULL); } } /* * Remove from linked list @@ -200,19 +341,22 @@ */ op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); op->ov_rmagic = RMAGIC; *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; #endif + TclpMutexUnlock(&allocMutex); return ((char *)(op + 1)); } /* *---------------------------------------------------------------------- * * MoreCore -- * * Allocate more memory to the indicated bucket. + * + * Assumes Mutex is already held. * * Results: * None. * * Side effects: @@ -220,17 +364,18 @@ * *---------------------------------------------------------------------- */ static void -MoreCore( - int bucket) /* What bucket to allocat to. */ +MoreCore(bucket) + int bucket; /* What bucket to allocat to. */ { register union overhead *op; register long sz; /* size of desired block */ long amt; /* amount to allocate */ int nblks; /* 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. */ @@ -239,15 +384,20 @@ amt = MAXMALLOC; nblks = amt / sz; ASSERT(nblks*sz == amt); - op = (union overhead *)TclpSysAlloc(amt, 1); + blockPtr = (struct block *) TclpSysAlloc((unsigned) + (sizeof(struct block) + amt), 1); /* no more room! */ - if (op == NULL) { + if (blockPtr == NULL) { return; } + blockPtr->nextPtr = blockList; + blockList = blockPtr; + + op = (union overhead *) (blockPtr + 1); /* * Add new memory allocated to that on * free list for this hash bucket. */ @@ -274,25 +424,28 @@ * *---------------------------------------------------------------------- */ void -TclpFree( - char *cp) /* Pointer to memory to free. */ +TclpFree(cp) + char *cp; /* Pointer to memory to free. */ { register long size; register union overhead *op; + struct block *bigBlockPtr; if (cp == NULL) { return; } + TclpMutexLock(&allocMutex); op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */ ASSERT(op->ov_magic1 == MAGIC); if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) { + TclpMutexUnlock(&allocMutex); return; } RANGE_ASSERT(op->ov_rmagic == RMAGIC); RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); @@ -299,19 +452,24 @@ size = op->ov_index; if ( size == 0xff ) { #ifdef MSTATS nmalloc[NBUCKETS]--; #endif - TclpSysFree(op); + bigBlockPtr = (struct block *) op - 1; + bigBlockPtr->prevPtr->nextPtr = bigBlockPtr->nextPtr; + bigBlockPtr->nextPtr->prevPtr = bigBlockPtr->prevPtr; + TclpSysFree(bigBlockPtr); + TclpMutexUnlock(&allocMutex); return; } ASSERT(size < NBUCKETS); op->ov_next = nextf[size]; /* also clobbers ov_magic */ nextf[size] = op; #ifdef MSTATS nmalloc[size]--; #endif + TclpMutexUnlock(&allocMutex); } /* *---------------------------------------------------------------------- * @@ -327,28 +485,32 @@ * *---------------------------------------------------------------------- */ char * -TclpRealloc( - char *cp, /* Pointer to alloced block. */ - unsigned int nbytes) /* New size of memory. */ +TclpRealloc(cp, nbytes) + char *cp; /* Pointer to alloced block. */ + unsigned int nbytes; /* New size of memory. */ { int i; union overhead *op; + struct block *bigBlockPtr; int expensive; unsigned long maxsize; if (cp == NULL) { return (TclpAlloc(nbytes)); } + + TclpMutexLock(&allocMutex); op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */ ASSERT(op->ov_magic1 == MAGIC); if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) { + TclpMutexUnlock(&allocMutex); return NULL; } RANGE_ASSERT(op->ov_rmagic == RMAGIC); RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); @@ -357,14 +519,32 @@ /* * If the block isn't in a bin, just realloc it. */ if (i == 0xff) { - op = (union overhead *) TclpSysRealloc(op, nbytes+OVERHEAD); - if (op == NULL) { + struct block *prevPtr, *nextPtr; + bigBlockPtr = (struct block *) op - 1; + prevPtr = bigBlockPtr->prevPtr; + nextPtr = bigBlockPtr->nextPtr; + bigBlockPtr = (struct block *) TclpSysRealloc(bigBlockPtr, + sizeof(struct block) + OVERHEAD + nbytes); + if (bigBlockPtr == NULL) { + TclpMutexUnlock(&allocMutex); 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; + } + + op = (union overhead *) (bigBlockPtr + 1); #ifdef MSTATS nmalloc[NBUCKETS]++; #endif #ifdef RCHECK /* @@ -372,10 +552,11 @@ */ op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; #endif + TclpMutexUnlock(&allocMutex); return (char *)(op+1); } maxsize = 1 << (i+3); expensive = 0; if ( nbytes + OVERHEAD > maxsize ) { @@ -384,11 +565,13 @@ expensive = 1; } if (expensive) { void *newp; - + + TclpMutexUnlock(&allocMutex); + newp = TclpAlloc(nbytes); if ( newp == NULL ) { return NULL; } maxsize -= OVERHEAD; @@ -404,10 +587,11 @@ */ #ifdef RCHECK op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; #endif + TclpMutexUnlock(&allocMutex); return(cp); } /* *---------------------------------------------------------------------- @@ -427,18 +611,19 @@ *---------------------------------------------------------------------- */ #ifdef MSTATS void -mstats( - char *s) /* Where to write info. */ +mstats(s) + char *s; /* Where to write info. */ { register int i, j; register union overhead *p; int totfree = 0, totused = 0; + TclpMutexLock(&allocMutex); fprintf(stderr, "Memory allocation statistics %s\nTclpFree:\t", s); for (i = 0; i < NBUCKETS; i++) { for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) fprintf(stderr, " %d", j); totfree += j * (1 << (i + 3)); @@ -450,7 +635,83 @@ } fprintf(stderr, "\n\tTotal small in use: %d, total free: %d\n", totused, totfree); fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %d\n", MAXMALLOC, nmalloc[NBUCKETS]); + TclpMutexUnlock(&allocMutex); } #endif + +#else /* !USE_TCLALLOC */ + +/* + *---------------------------------------------------------------------- + * + * TclpAlloc -- + * + * Allocate more memory. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +char * +TclpAlloc(nbytes) + unsigned int nbytes; /* Number of bytes to allocate. */ +{ + return (char*) malloc(nbytes); +} + +/* + *---------------------------------------------------------------------- + * + * TclpFree -- + * + * Free memory. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TclpFree(cp) + char *cp; /* Pointer to memory to free. */ +{ + free(cp); + return; +} + +/* + *---------------------------------------------------------------------- + * + * TclpRealloc -- + * + * Reallocate memory. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +char * +TclpRealloc(cp, nbytes) + char *cp; /* Pointer to alloced block. */ + unsigned int nbytes; /* New size of memory. */ +{ + return (char*) realloc(cp, nbytes); +} + +#endif /* !USE_TCLALLOC */ Index: generic/tclAsync.c ================================================================== --- generic/tclAsync.c +++ generic/tclAsync.c @@ -10,14 +10,15 @@ * 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. * - * SCCS: @(#) tclAsync.c 1.6 96/02/15 11:46:15 + * RCS: @(#) $Id: tclAsync.c,v 1.1.2.6 1999/03/11 01:50:27 stanton Exp $ */ #include "tclInt.h" +#include "tclPort.h" /* * One of the following structures exists for each asynchronous * handler: */ @@ -39,10 +40,12 @@ */ static AsyncHandler *firstHandler; /* First handler defined for process, * or NULL if none. */ static AsyncHandler *lastHandler; /* Last handler or NULL. */ + +TCL_DECLARE_MUTEX(asyncMutex) /* Process-wide async handler lock */ /* * The variable below 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 @@ -89,16 +92,18 @@ asyncPtr = (AsyncHandler *) ckalloc(sizeof(AsyncHandler)); asyncPtr->ready = 0; asyncPtr->nextPtr = NULL; asyncPtr->proc = proc; asyncPtr->clientData = clientData; + Tcl_MutexLock(&asyncMutex); if (firstHandler == NULL) { firstHandler = asyncPtr; } else { lastHandler->nextPtr = asyncPtr; } lastHandler = asyncPtr; + Tcl_MutexUnlock(&asyncMutex); return (Tcl_AsyncHandler) asyncPtr; } /* *---------------------------------------------------------------------- @@ -121,14 +126,17 @@ void Tcl_AsyncMark(async) Tcl_AsyncHandler async; /* Token for handler. */ { + Tcl_MutexLock(&asyncMutex); ((AsyncHandler *) async)->ready = 1; if (!asyncActive) { asyncReady = 1; + TclpAsyncMark(async); } + Tcl_MutexUnlock(&asyncMutex); } /* *---------------------------------------------------------------------- * @@ -157,12 +165,14 @@ int code; /* If interp is non-NULL, this gives * completion code from command that * just completed. */ { AsyncHandler *asyncPtr; + Tcl_MutexLock(&asyncMutex); if (asyncReady == 0) { + Tcl_MutexUnlock(&asyncMutex); return code; } asyncReady = 0; asyncActive = 1; if (interp == NULL) { @@ -189,13 +199,16 @@ } if (asyncPtr == NULL) { break; } asyncPtr->ready = 0; + Tcl_MutexUnlock(&asyncMutex); code = (*asyncPtr->proc)(asyncPtr->clientData, interp, code); + Tcl_MutexLock(&asyncMutex); } asyncActive = 0; + Tcl_MutexUnlock(&asyncMutex); return code; } /* *---------------------------------------------------------------------- @@ -219,10 +232,11 @@ Tcl_AsyncHandler async; /* Token for handler to delete. */ { AsyncHandler *asyncPtr = (AsyncHandler *) async; AsyncHandler *prevPtr; + Tcl_MutexLock(&asyncMutex); if (firstHandler == asyncPtr) { firstHandler = asyncPtr->nextPtr; if (firstHandler == NULL) { lastHandler = NULL; } @@ -234,10 +248,11 @@ prevPtr->nextPtr = asyncPtr->nextPtr; if (lastHandler == asyncPtr) { lastHandler = prevPtr; } } + Tcl_MutexUnlock(&asyncMutex); ckfree((char *) asyncPtr); } /* *---------------------------------------------------------------------- Index: generic/tclBasic.c ================================================================== --- generic/tclBasic.c +++ generic/tclBasic.c @@ -5,15 +5,16 @@ * including interpreter creation and deletion, command creation * and deletion, and command parsing and 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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclBasic.c 1.305 97/08/13 10:34:43 + * RCS: @(#) $Id: tclBasic.c,v 1.1.2.16 1999/04/14 00:33:20 surles Exp $ */ #include "tclInt.h" #include "tclCompile.h" #ifndef TCL_GENERIC_ONLY @@ -23,12 +24,17 @@ /* * Static procedures in this file: */ static void DeleteInterpProc _ANSI_ARGS_((Tcl_Interp *interp)); -static void HiddenCmdsDeleteProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp)); +static void ProcessUnexpectedResult _ANSI_ARGS_(( + Tcl_Interp *interp, int returnCode)); +static void RecordTracebackInfo _ANSI_ARGS_(( + Tcl_Interp *interp, Tcl_Obj *objPtr, + int numSrcBytes)); + +extern TclStubs tclStubs; /* * The following structure defines the commands in the Tcl core. */ @@ -59,22 +65,24 @@ (CompileProc *) NULL, 1}, {"array", (Tcl_CmdProc *) NULL, Tcl_ArrayObjCmd, (CompileProc *) NULL, 1}, {"binary", (Tcl_CmdProc *) NULL, Tcl_BinaryObjCmd, (CompileProc *) NULL, 1}, - {"break", Tcl_BreakCmd, (Tcl_ObjCmdProc *) NULL, + {"break", (Tcl_CmdProc *) NULL, Tcl_BreakObjCmd, TclCompileBreakCmd, 1}, {"case", (Tcl_CmdProc *) NULL, Tcl_CaseObjCmd, (CompileProc *) NULL, 1}, {"catch", (Tcl_CmdProc *) NULL, Tcl_CatchObjCmd, TclCompileCatchCmd, 1}, {"clock", (Tcl_CmdProc *) NULL, Tcl_ClockObjCmd, (CompileProc *) NULL, 1}, {"concat", (Tcl_CmdProc *) NULL, Tcl_ConcatObjCmd, (CompileProc *) NULL, 1}, - {"continue", Tcl_ContinueCmd, (Tcl_ObjCmdProc *) NULL, + {"continue", (Tcl_CmdProc *) NULL, Tcl_ContinueObjCmd, TclCompileContinueCmd, 1}, + {"encoding", (Tcl_CmdProc *) NULL, Tcl_EncodingObjCmd, + (CompileProc *) NULL, 0}, {"error", (Tcl_CmdProc *) NULL, Tcl_ErrorObjCmd, (CompileProc *) NULL, 1}, {"eval", (Tcl_CmdProc *) NULL, Tcl_EvalObjCmd, (CompileProc *) NULL, 1}, {"exit", (Tcl_CmdProc *) NULL, Tcl_ExitObjCmd, @@ -81,28 +89,26 @@ (CompileProc *) NULL, 0}, {"expr", (Tcl_CmdProc *) NULL, Tcl_ExprObjCmd, TclCompileExprCmd, 1}, {"fcopy", (Tcl_CmdProc *) NULL, Tcl_FcopyObjCmd, (CompileProc *) NULL, 1}, - {"fileevent", Tcl_FileEventCmd, (Tcl_ObjCmdProc *) NULL, + {"fileevent", (Tcl_CmdProc *) NULL, Tcl_FileEventObjCmd, (CompileProc *) NULL, 1}, - {"for", Tcl_ForCmd, (Tcl_ObjCmdProc *) NULL, + {"for", (Tcl_CmdProc *) NULL, Tcl_ForObjCmd, TclCompileForCmd, 1}, {"foreach", (Tcl_CmdProc *) NULL, Tcl_ForeachObjCmd, TclCompileForeachCmd, 1}, {"format", (Tcl_CmdProc *) NULL, Tcl_FormatObjCmd, (CompileProc *) NULL, 1}, {"global", (Tcl_CmdProc *) NULL, Tcl_GlobalObjCmd, (CompileProc *) NULL, 1}, - {"if", Tcl_IfCmd, (Tcl_ObjCmdProc *) NULL, + {"if", (Tcl_CmdProc *) NULL, Tcl_IfObjCmd, TclCompileIfCmd, 1}, - {"incr", Tcl_IncrCmd, (Tcl_ObjCmdProc *) NULL, + {"incr", (Tcl_CmdProc *) NULL, Tcl_IncrObjCmd, TclCompileIncrCmd, 1}, {"info", (Tcl_CmdProc *) NULL, Tcl_InfoObjCmd, (CompileProc *) NULL, 1}, - {"interp", (Tcl_CmdProc *) NULL, Tcl_InterpObjCmd, - (CompileProc *) NULL, 1}, {"join", (Tcl_CmdProc *) NULL, Tcl_JoinObjCmd, (CompileProc *) NULL, 1}, {"lappend", (Tcl_CmdProc *) NULL, Tcl_LappendObjCmd, (CompileProc *) NULL, 1}, {"lindex", (Tcl_CmdProc *) NULL, Tcl_LindexObjCmd, @@ -111,11 +117,11 @@ (CompileProc *) NULL, 1}, {"list", (Tcl_CmdProc *) NULL, Tcl_ListObjCmd, (CompileProc *) NULL, 1}, {"llength", (Tcl_CmdProc *) NULL, Tcl_LlengthObjCmd, (CompileProc *) NULL, 1}, - {"load", Tcl_LoadCmd, (Tcl_ObjCmdProc *) NULL, + {"load", (Tcl_CmdProc *) NULL, Tcl_LoadObjCmd, (CompileProc *) NULL, 0}, {"lrange", (Tcl_CmdProc *) NULL, Tcl_LrangeObjCmd, (CompileProc *) NULL, 1}, {"lreplace", (Tcl_CmdProc *) NULL, Tcl_LreplaceObjCmd, (CompileProc *) NULL, 1}, @@ -123,45 +129,45 @@ (CompileProc *) NULL, 1}, {"lsort", (Tcl_CmdProc *) NULL, Tcl_LsortObjCmd, (CompileProc *) NULL, 1}, {"namespace", (Tcl_CmdProc *) NULL, Tcl_NamespaceObjCmd, (CompileProc *) NULL, 1}, - {"package", Tcl_PackageCmd, (Tcl_ObjCmdProc *) NULL, + {"package", (Tcl_CmdProc *) NULL, Tcl_PackageObjCmd, (CompileProc *) NULL, 1}, {"proc", (Tcl_CmdProc *) NULL, Tcl_ProcObjCmd, (CompileProc *) NULL, 1}, - {"regexp", Tcl_RegexpCmd, (Tcl_ObjCmdProc *) NULL, + {"regexp", (Tcl_CmdProc *) NULL, Tcl_RegexpObjCmd, (CompileProc *) NULL, 1}, - {"regsub", Tcl_RegsubCmd, (Tcl_ObjCmdProc *) NULL, + {"regsub", (Tcl_CmdProc *) NULL, Tcl_RegsubObjCmd, (CompileProc *) NULL, 1}, {"rename", (Tcl_CmdProc *) NULL, Tcl_RenameObjCmd, (CompileProc *) NULL, 1}, {"return", (Tcl_CmdProc *) NULL, Tcl_ReturnObjCmd, (CompileProc *) NULL, 1}, - {"scan", Tcl_ScanCmd, (Tcl_ObjCmdProc *) NULL, + {"scan", (Tcl_CmdProc *) NULL, Tcl_ScanObjCmd, (CompileProc *) NULL, 1}, - {"set", Tcl_SetCmd, (Tcl_ObjCmdProc *) NULL, + {"set", (Tcl_CmdProc *) NULL, Tcl_SetObjCmd, TclCompileSetCmd, 1}, {"split", (Tcl_CmdProc *) NULL, Tcl_SplitObjCmd, (CompileProc *) NULL, 1}, {"string", (Tcl_CmdProc *) NULL, Tcl_StringObjCmd, (CompileProc *) NULL, 1}, - {"subst", Tcl_SubstCmd, (Tcl_ObjCmdProc *) NULL, + {"subst", (Tcl_CmdProc *) NULL, Tcl_SubstObjCmd, (CompileProc *) NULL, 1}, {"switch", (Tcl_CmdProc *) NULL, Tcl_SwitchObjCmd, (CompileProc *) NULL, 1}, - {"trace", Tcl_TraceCmd, (Tcl_ObjCmdProc *) NULL, + {"trace", (Tcl_CmdProc *) NULL, Tcl_TraceObjCmd, (CompileProc *) NULL, 1}, {"unset", (Tcl_CmdProc *) NULL, Tcl_UnsetObjCmd, (CompileProc *) NULL, 1}, {"uplevel", (Tcl_CmdProc *) NULL, Tcl_UplevelObjCmd, (CompileProc *) NULL, 1}, {"upvar", (Tcl_CmdProc *) NULL, Tcl_UpvarObjCmd, (CompileProc *) NULL, 1}, {"variable", (Tcl_CmdProc *) NULL, Tcl_VariableObjCmd, (CompileProc *) NULL, 1}, - {"while", Tcl_WhileCmd, (Tcl_ObjCmdProc *) NULL, + {"while", (Tcl_CmdProc *) NULL, Tcl_WhileObjCmd, TclCompileWhileCmd, 1}, /* * Commands in the UNIX core: */ @@ -175,65 +181,66 @@ (CompileProc *) NULL, 1}, {"eof", (Tcl_CmdProc *) NULL, Tcl_EofObjCmd, (CompileProc *) NULL, 1}, {"fblocked", (Tcl_CmdProc *) NULL, Tcl_FblockedObjCmd, (CompileProc *) NULL, 1}, - {"fconfigure", Tcl_FconfigureCmd, (Tcl_ObjCmdProc *) NULL, + {"fconfigure", (Tcl_CmdProc *) NULL, Tcl_FconfigureObjCmd, (CompileProc *) NULL, 0}, {"file", (Tcl_CmdProc *) NULL, Tcl_FileObjCmd, (CompileProc *) NULL, 0}, {"flush", (Tcl_CmdProc *) NULL, Tcl_FlushObjCmd, (CompileProc *) NULL, 1}, {"gets", (Tcl_CmdProc *) NULL, Tcl_GetsObjCmd, (CompileProc *) NULL, 1}, - {"glob", Tcl_GlobCmd, (Tcl_ObjCmdProc *) NULL, + {"glob", (Tcl_CmdProc *) NULL, Tcl_GlobObjCmd, (CompileProc *) NULL, 0}, - {"open", Tcl_OpenCmd, (Tcl_ObjCmdProc *) NULL, + {"open", (Tcl_CmdProc *) NULL, Tcl_OpenObjCmd, (CompileProc *) NULL, 0}, {"pid", (Tcl_CmdProc *) NULL, Tcl_PidObjCmd, (CompileProc *) NULL, 1}, {"puts", (Tcl_CmdProc *) NULL, Tcl_PutsObjCmd, (CompileProc *) NULL, 1}, - {"pwd", Tcl_PwdCmd, (Tcl_ObjCmdProc *) NULL, + {"pwd", (Tcl_CmdProc *) NULL, Tcl_PwdObjCmd, (CompileProc *) NULL, 0}, {"read", (Tcl_CmdProc *) NULL, Tcl_ReadObjCmd, (CompileProc *) NULL, 1}, - {"seek", Tcl_SeekCmd, (Tcl_ObjCmdProc *) NULL, + {"seek", (Tcl_CmdProc *) NULL, Tcl_SeekObjCmd, (CompileProc *) NULL, 1}, - {"socket", Tcl_SocketCmd, (Tcl_ObjCmdProc *) NULL, + {"socket", (Tcl_CmdProc *) NULL, Tcl_SocketObjCmd, (CompileProc *) NULL, 0}, - {"tell", Tcl_TellCmd, (Tcl_ObjCmdProc *) NULL, + {"tell", (Tcl_CmdProc *) NULL, Tcl_TellObjCmd, (CompileProc *) NULL, 1}, {"time", (Tcl_CmdProc *) NULL, Tcl_TimeObjCmd, (CompileProc *) NULL, 1}, - {"update", Tcl_UpdateCmd, (Tcl_ObjCmdProc *) NULL, + {"update", (Tcl_CmdProc *) NULL, Tcl_UpdateObjCmd, (CompileProc *) NULL, 1}, - {"vwait", Tcl_VwaitCmd, (Tcl_ObjCmdProc *) NULL, + {"vwait", (Tcl_CmdProc *) NULL, Tcl_VwaitObjCmd, (CompileProc *) NULL, 1}, #ifdef MAC_TCL {"beep", (Tcl_CmdProc *) NULL, Tcl_BeepObjCmd, (CompileProc *) NULL, 0}, {"echo", Tcl_EchoCmd, (Tcl_ObjCmdProc *) NULL, (CompileProc *) NULL, 0}, - {"ls", Tcl_LsCmd, (Tcl_ObjCmdProc *) NULL, + {"ls", (Tcl_CmdProc *) NULL, Tcl_LsObjCmd, (CompileProc *) NULL, 0}, {"resource", (Tcl_CmdProc *) NULL, Tcl_ResourceObjCmd, (CompileProc *) NULL, 1}, {"source", (Tcl_CmdProc *) NULL, Tcl_MacSourceObjCmd, (CompileProc *) NULL, 0}, #else - {"exec", Tcl_ExecCmd, (Tcl_ObjCmdProc *) NULL, + {"exec", (Tcl_CmdProc *) NULL, Tcl_ExecObjCmd, (CompileProc *) NULL, 0}, {"source", (Tcl_CmdProc *) NULL, Tcl_SourceObjCmd, (CompileProc *) NULL, 0}, #endif /* MAC_TCL */ #endif /* TCL_GENERIC_ONLY */ {NULL, (Tcl_CmdProc *) NULL, (Tcl_ObjCmdProc *) NULL, (CompileProc *) NULL, 0} }; + /* *---------------------------------------------------------------------- * * Tcl_CreateInterp -- @@ -253,18 +260,27 @@ */ Tcl_Interp * Tcl_CreateInterp() { - register Interp *iPtr; - register Command *cmdPtr; - register CmdInfo *cmdInfoPtr; + Interp *iPtr; + Tcl_Interp *interp; + Command *cmdPtr; + BuiltinFunc *builtinFuncPtr; + MathFunc *mathFuncPtr; + Tcl_HashEntry *hPtr; + CmdInfo *cmdInfoPtr; + int i; union { char c[sizeof(short)]; short s; } order; - int i; +#ifdef TCL_COMPILE_STATS + ByteCodeStats *statsPtr; +#endif /* TCL_COMPILE_STATS */ + + TclInitSubsystems(NULL); /* * Panic if someone updated the CallFrame structure without * also updating the Tcl_CallFrame structure (or vice versa). */ @@ -278,41 +294,50 @@ * 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. */ - TclInitNamespaces(); - iPtr = (Interp *) ckalloc(sizeof(Interp)); - iPtr->result = iPtr->resultSpace; - iPtr->freeProc = 0; - iPtr->objResultPtr = Tcl_NewObj(); /* an empty object */ + interp = (Tcl_Interp *) iPtr; + + iPtr->result = iPtr->resultSpace; + iPtr->freeProc = NULL; + iPtr->errorLine = 0; + iPtr->objResultPtr = Tcl_NewObj(); Tcl_IncrRefCount(iPtr->objResultPtr); - iPtr->errorLine = 0; + iPtr->handle = TclHandleCreate(iPtr); + iPtr->globalNsPtr = NULL; + iPtr->hiddenCmdTablePtr = NULL; + iPtr->interpInfo = NULL; Tcl_InitHashTable(&iPtr->mathFuncTable, TCL_STRING_KEYS); + iPtr->numLevels = 0; iPtr->maxNestingDepth = 1000; iPtr->framePtr = NULL; iPtr->varFramePtr = NULL; iPtr->activeTracePtr = NULL; iPtr->returnCode = TCL_OK; iPtr->errorInfo = NULL; iPtr->errorCode = NULL; + iPtr->appendResult = NULL; iPtr->appendAvl = 0; iPtr->appendUsed = 0; + for (i = 0; i < NUM_REGEXPS; i++) { iPtr->patterns[i] = NULL; iPtr->patLengths[i] = -1; iPtr->regexps[i] = NULL; } Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS); iPtr->packageUnknown = NULL; iPtr->cmdCount = 0; iPtr->termOffset = 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->assocData = (Tcl_HashTable *) NULL; @@ -320,25 +345,68 @@ iPtr->emptyObjPtr = Tcl_NewObj(); /* another empty object */ Tcl_IncrRefCount(iPtr->emptyObjPtr); iPtr->resultSpace[0] = 0; iPtr->globalNsPtr = NULL; /* force creation of global ns below */ - iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace( - (Tcl_Interp *) iPtr, "", (ClientData) NULL, - (Tcl_NamespaceDeleteProc *) NULL); + iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace(interp, "", + (ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL); if (iPtr->globalNsPtr == NULL) { panic("Tcl_CreateInterp: can't create global namespace"); } /* - * Initialize support for code compilation. Do this after initializing - * namespaces since TclCreateExecEnv will try to reference a Tcl - * variable (it links to the Tcl "tcl_traceExec" variable). + * 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); + + /* + * 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; + (VOID *) memset(statsPtr->instructionCount, 0, + sizeof(statsPtr->instructionCount)); + + statsPtr->totalSrcBytes = 0.0; + statsPtr->totalByteCodeBytes = 0.0; + statsPtr->currentSrcBytes = 0.0; + statsPtr->currentByteCodeBytes = 0.0; + (VOID *) memset(statsPtr->srcCount, 0, sizeof(statsPtr->srcCount)); + (VOID *) memset(statsPtr->byteCodeCount, 0, + sizeof(statsPtr->byteCodeCount)); + (VOID *) 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; - iPtr->execEnvPtr = TclCreateExecEnv((Tcl_Interp *) iPtr); + statsPtr->numLiteralsCreated = 0; + statsPtr->totalLitStringBytes = 0.0; + statsPtr->currentLitStringBytes = 0.0; + (VOID *) memset(statsPtr->literalCount, 0, + sizeof(statsPtr->literalCount)); +#endif /* TCL_COMPILE_STATS */ + /* + * Initialise the stub table pointer. + */ + + iPtr->stubTable = &tclStubs; + + /* * 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 @@ -389,75 +457,97 @@ Tcl_SetHashValue(hPtr, cmdPtr); } } /* - * Initialize/Create "errorInfo" and "errorCode" global vars - * (because some part of the C code assume they exists - * and we can get a seg fault otherwise (in multiple - * interps loading of extensions for instance) --dl) - */ - /* - * We can't assume that because we initialize - * the variables here, they won't be unset later. - * so we had 2 choices: - * + Check every place where a GetVar of those is used - * and the NULL result is not checked (like in tclLoad.c) - * + Make SetVar,... NULL friendly - * We choosed the second option because : - * + It is easy and low cost to check for NULL pointer before - * calling strlen() - * + It can be helpfull to other people using those API - * + Passing a NULL value to those closest 'meaning' is empty string - * (specially with the new objects where 0 bytes strings are ok) - * So the following init is commented out: -- dl - */ - /* - (void)Tcl_SetVar2((Tcl_Interp *)iPtr, "errorInfo", (char *) NULL, "", - TCL_GLOBAL_ONLY); - (void)Tcl_SetVar2((Tcl_Interp *)iPtr, "errorCode", (char *) NULL, "NONE", - TCL_GLOBAL_ONLY); - */ - -#ifndef TCL_GENERIC_ONLY - TclSetupEnv((Tcl_Interp *) iPtr); -#endif + * Register the builtin math functions. + */ + + i = 0; + for (builtinFuncPtr = builtinFuncTable; builtinFuncPtr->name != NULL; + builtinFuncPtr++) { + Tcl_CreateMathFunc((Tcl_Interp *) iPtr, builtinFuncPtr->name, + builtinFuncPtr->numArgs, builtinFuncPtr->argTypes, + (Tcl_MathProc *) NULL, (ClientData) 0); + hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, + builtinFuncPtr->name); + if (hPtr == NULL) { + panic("Tcl_CreateInterp: Tcl_CreateMathFunc incorrectly registered '%s'", builtinFuncPtr->name); + return NULL; + } + mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr); + mathFuncPtr->builtinFuncIndex = i; + i++; + } + iPtr->flags |= EXPR_INITIALIZED; /* * Do Multiple/Safe Interps Tcl init stuff */ - (void) TclInterpInit((Tcl_Interp *)iPtr); + + TclInterpInit(interp); /* - * Set up variables such as tcl_version. + * We used to create the "errorInfo" and "errorCode" global vars at this + * point because so much of the Tcl implementation assumes they already + * exist. This is not quite enough, however, since they can be unset + * at any time. + * + * There are 2 choices: + * + Check every place where a GetVar of those is used + * and the NULL result is not checked (like in tclLoad.c) + * + Make SetVar,... NULL friendly + * We choose the second option because : + * + It is easy and low cost to check for NULL pointer before + * calling strlen() + * + It can be helpfull to other people using those API + * + Passing a NULL value to those closest 'meaning' is empty string + * (specially with the new objects where 0 bytes strings are ok) + * So the following init is commented out: -- dl + * + * (void) Tcl_SetVar2((Tcl_Interp *)iPtr, "errorInfo", (char *) NULL, + * "", TCL_GLOBAL_ONLY); + * (void) Tcl_SetVar2((Tcl_Interp *)iPtr, "errorCode", (char *) NULL, + * "NONE", TCL_GLOBAL_ONLY); */ - TclPlatformInit((Tcl_Interp *)iPtr); - Tcl_SetVar((Tcl_Interp *) iPtr, "tcl_patchLevel", TCL_PATCH_LEVEL, - TCL_GLOBAL_ONLY); - Tcl_SetVar((Tcl_Interp *) iPtr, "tcl_version", TCL_VERSION, - TCL_GLOBAL_ONLY); - Tcl_TraceVar2((Tcl_Interp *) iPtr, "tcl_precision", (char *) NULL, - TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - TclPrecTraceProc, (ClientData) NULL); +#ifndef TCL_GENERIC_ONLY + TclSetupEnv(interp); +#endif /* * Compute the byte order of this machine. */ order.s = 1; - Tcl_SetVar2((Tcl_Interp *) iPtr, "tcl_platform", "byteOrder", - (order.c[0] == 1) ? "littleEndian" : "bigEndian", + Tcl_SetVar2(interp, "tcl_platform", "byteOrder", + ((order.c[0] == 1) ? "littleEndian" : "bigEndian"), 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", (char *) NULL, + TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + TclPrecTraceProc, (ClientData) NULL); + TclpSetVariables(interp); + /* * Register Tcl's version number. */ - Tcl_PkgProvide((Tcl_Interp *) iPtr, "Tcl", TCL_VERSION); + Tcl_PkgProvideEx(interp, "Tcl", TCL_VERSION, (ClientData) &tclStubs); - return (Tcl_Interp *) iPtr; +#ifdef Tcl_InitStubs +#undef Tcl_InitStubs +#endif + Tcl_InitStubs(interp, TCL_VERSION, 1); + + return interp; } /* *---------------------------------------------------------------------- * @@ -522,17 +612,22 @@ * is about to be deleted. */ ClientData clientData; /* One-word value to pass to proc. */ { Interp *iPtr = (Interp *) interp; static int assocDataCounter = 0; +#ifdef TCL_THREADS + static Tcl_Mutex assocMutex; +#endif int new; - char buffer[128]; + char buffer[32 + TCL_INTEGER_SPACE]; AssocData *dPtr = (AssocData *) ckalloc(sizeof(AssocData)); Tcl_HashEntry *hPtr; + Tcl_MutexLock(&assocMutex); sprintf(buffer, "Assoc Data Key #%d", assocDataCounter); assocDataCounter++; + Tcl_MutexUnlock(&assocMutex); if (iPtr->assocData == (Tcl_HashTable *) NULL) { iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS); } @@ -723,155 +818,10 @@ } /* *---------------------------------------------------------------------- * - * DeleteInterpProc -- - * - * Helper procedure to delete an interpreter. This procedure is - * called when the last call to Tcl_Preserve on this interpreter - * is matched by a call to Tcl_Release. The procedure 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(interp) - Tcl_Interp *interp; /* Interpreter to delete. */ -{ - Interp *iPtr = (Interp *) interp; - Tcl_HashEntry *hPtr; - Tcl_HashSearch search; - Tcl_HashTable *hTablePtr; - AssocData *dPtr; - int i; - - /* - * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup. - */ - - if (iPtr->numLevels > 0) { - panic("DeleteInterpProc called with active evals"); - } - - /* - * The interpreter should already be marked deleted; otherwise how - * did we get here? - */ - - if (!(iPtr->flags & DELETED)) { - panic("DeleteInterpProc called on interpreter not marked deleted"); - } - - /* - * Dismantle everything in the global namespace except for the - * "errorInfo" and "errorCode" variables. These remain until the - * namespace is actually destroyed, in case any errors occur. - * - * Dismantle the namespace here, before we clear the assocData. If any - * background errors occur here, they will be deleted below. - */ - - TclTeardownNamespace(iPtr->globalNsPtr); - - /* - * Tear down the math function table. - */ - - for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &search); - hPtr != NULL; - hPtr = Tcl_NextHashEntry(&search)) { - ckfree((char *) Tcl_GetHashValue(hPtr)); - } - Tcl_DeleteHashTable(&iPtr->mathFuncTable); - - /* - * Invoke deletion callbacks; note that a callback can create new - * callbacks, so we iterate. - */ - - while (iPtr->assocData != (Tcl_HashTable *) NULL) { - hTablePtr = iPtr->assocData; - iPtr->assocData = (Tcl_HashTable *) NULL; - for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search); - hPtr != NULL; - hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) { - dPtr = (AssocData *) Tcl_GetHashValue(hPtr); - Tcl_DeleteHashEntry(hPtr); - if (dPtr->proc != NULL) { - (*dPtr->proc)(dPtr->clientData, interp); - } - ckfree((char *) dPtr); - } - Tcl_DeleteHashTable(hTablePtr); - ckfree((char *) hTablePtr); - } - - /* - * Finish deleting the global namespace. - */ - - 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); - interp->result = NULL; - Tcl_DecrRefCount(iPtr->objResultPtr); - iPtr->objResultPtr = NULL; - if (iPtr->errorInfo != NULL) { - ckfree(iPtr->errorInfo); - iPtr->errorInfo = NULL; - } - if (iPtr->errorCode != NULL) { - ckfree(iPtr->errorCode); - iPtr->errorCode = NULL; - } - if (iPtr->appendResult != NULL) { - ckfree(iPtr->appendResult); - iPtr->appendResult = NULL; - } - for (i = 0; i < NUM_REGEXPS; i++) { - if (iPtr->patterns[i] == NULL) { - break; - } - ckfree(iPtr->patterns[i]); - ckfree((char *) iPtr->regexps[i]); - iPtr->regexps[i] = NULL; - } - TclFreePackageInfo(iPtr); - while (iPtr->tracePtr != NULL) { - Trace *nextPtr = iPtr->tracePtr->nextPtr; - - ckfree((char *) iPtr->tracePtr); - iPtr->tracePtr = nextPtr; - } - if (iPtr->execEnvPtr != NULL) { - TclDeleteExecEnv(iPtr->execEnvPtr); - } - Tcl_DecrRefCount(iPtr->emptyObjPtr); - iPtr->emptyObjPtr = NULL; - - ckfree((char *) iPtr); -} - -/* - *---------------------------------------------------------------------- - * * Tcl_InterpDeleted -- * * Returns nonzero if the interpreter has been deleted with a call * to Tcl_DeleteInterp. * @@ -944,124 +894,208 @@ } /* *---------------------------------------------------------------------- * - * HiddenCmdsDeleteProc -- + * DeleteInterpProc -- * - * Called on interpreter deletion to delete all the hidden - * commands in an interpreter. + * Helper procedure to delete an interpreter. This procedure is + * called when the last call to Tcl_Preserve on this interpreter + * is matched by a call to Tcl_Release. The procedure cleans up + * all resources used in the interpreter and calls all currently + * registered interpreter deletion callbacks. * * Results: * None. * * Side effects: - * Frees up memory. + * Whatever the interpreter deletion callbacks do. Frees resources + * used by the interpreter. * *---------------------------------------------------------------------- */ static void -HiddenCmdsDeleteProc(clientData, interp) - ClientData clientData; /* The hidden commands hash table. */ - Tcl_Interp *interp; /* The interpreter being deleted. */ +DeleteInterpProc(interp) + Tcl_Interp *interp; /* Interpreter to delete. */ { - Tcl_HashTable *hiddenCmdTblPtr; + Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hPtr; - Tcl_HashSearch hSearch; - Command *cmdPtr; - - hiddenCmdTblPtr = (Tcl_HashTable *) clientData; - for (hPtr = Tcl_FirstHashEntry(hiddenCmdTblPtr, &hSearch); - hPtr != NULL; - hPtr = Tcl_FirstHashEntry(hiddenCmdTblPtr, &hSearch)) { - - /* - * Cannot use Tcl_DeleteCommand because (a) the command is not - * in the command hash table, and (b) that table has already been - * deleted above. Hence we emulate what it does, below. - */ - - cmdPtr = (Command *) Tcl_GetHashValue(hPtr); - - /* - * 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->deleted) { - - /* - * Another deletion is already in progress. Remove the hash - * table entry now, but don't invoke a callback or free the - * command structure. - */ - - Tcl_DeleteHashEntry(cmdPtr->hPtr); - cmdPtr->hPtr = NULL; - continue; - } - cmdPtr->deleted = 1; - if (cmdPtr->deleteProc != NULL) { - (*cmdPtr->deleteProc)(cmdPtr->deleteData); - } - - /* - * Bump the command epoch counter. This will invalidate all cached - * references that refer to this command. - */ - - cmdPtr->cmdEpoch++; - - /* - * 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); - } - - /* - * 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 TclExecuteByteCode looks up the command in the - * command hashtable). - */ - - TclCleanupCommand(cmdPtr); - } - Tcl_DeleteHashTable(hiddenCmdTblPtr); - ckfree((char *) hiddenCmdTblPtr); -} - -/* - *---------------------------------------------------------------------- + Tcl_HashSearch search; + Tcl_HashTable *hTablePtr; + ResolverScheme *resPtr, *nextResPtr; + int i; + + /* + * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup. + */ + + if (iPtr->numLevels > 0) { + panic("DeleteInterpProc called with active evals"); + } + + /* + * The interpreter should already be marked deleted; otherwise how + * did we get here? + */ + + if (!(iPtr->flags & DELETED)) { + panic("DeleteInterpProc called on interpreter not marked deleted"); + } + + TclHandleFree(iPtr->handle); + + /* + * Dismantle everything in the global namespace except for the + * "errorInfo" and "errorCode" variables. These remain until the + * namespace is actually destroyed, in case any errors occur. + * + * Dismantle the namespace here, before we clear the assocData. If any + * background errors occur here, they will be deleted below. + */ + + 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_Command) Tcl_GetHashValue(hPtr)); + } + Tcl_DeleteHashTable(hTablePtr); + ckfree((char *) hTablePtr); + } + /* + * Tear down the math function table. + */ + + for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &search); + hPtr != NULL; + hPtr = Tcl_NextHashEntry(&search)) { + ckfree((char *) Tcl_GetHashValue(hPtr)); + } + Tcl_DeleteHashTable(&iPtr->mathFuncTable); + + /* + * Invoke deletion callbacks; note that a callback can create new + * callbacks, so we iterate. + */ + + while (iPtr->assocData != (Tcl_HashTable *) NULL) { + AssocData *dPtr; + + hTablePtr = iPtr->assocData; + iPtr->assocData = (Tcl_HashTable *) NULL; + for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search); + hPtr != NULL; + hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) { + dPtr = (AssocData *) Tcl_GetHashValue(hPtr); + Tcl_DeleteHashEntry(hPtr); + if (dPtr->proc != NULL) { + (*dPtr->proc)(dPtr->clientData, interp); + } + ckfree((char *) dPtr); + } + Tcl_DeleteHashTable(hTablePtr); + ckfree((char *) hTablePtr); + } + + /* + * Finish deleting the global namespace. + */ + + 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); + interp->result = NULL; + Tcl_DecrRefCount(iPtr->objResultPtr); + iPtr->objResultPtr = NULL; + if (iPtr->errorInfo != NULL) { + ckfree(iPtr->errorInfo); + iPtr->errorInfo = NULL; + } + if (iPtr->errorCode != NULL) { + ckfree(iPtr->errorCode); + iPtr->errorCode = NULL; + } + if (iPtr->appendResult != NULL) { + ckfree(iPtr->appendResult); + iPtr->appendResult = NULL; + } + for (i = 0; i < NUM_REGEXPS; i++) { + if (iPtr->patterns[i] == NULL) { + break; + } + ckfree(iPtr->patterns[i]); + ckfree((char *) iPtr->regexps[i]); + iPtr->regexps[i] = NULL; + } + TclFreePackageInfo(iPtr); + while (iPtr->tracePtr != NULL) { + Trace *nextPtr = iPtr->tracePtr->nextPtr; + + ckfree((char *) iPtr->tracePtr); + iPtr->tracePtr = nextPtr; + } + if (iPtr->execEnvPtr != NULL) { + TclDeleteExecEnv(iPtr->execEnvPtr); + } + Tcl_DecrRefCount(iPtr->emptyObjPtr); + iPtr->emptyObjPtr = NULL; + + resPtr = iPtr->resolverPtr; + while (resPtr) { + nextResPtr = resPtr->nextPtr; + ckfree(resPtr->name); + ckfree((char *) resPtr); + resPtr = nextResPtr; + } + + /* + * Free up literal objects created for scripts compiled by the + * interpreter. + */ + + TclDeleteLiteralTable(interp, &(iPtr->literalTable)); + ckfree((char *) 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 interp->result + * 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(interp, cmdName, hiddenCmdToken) Tcl_Interp *interp; /* Interpreter in which to hide command. */ @@ -1069,11 +1103,11 @@ char *hiddenCmdToken; /* Token name of the to-be-hidden command. */ { Interp *iPtr = (Interp *) interp; Tcl_Command cmd; Command *cmdPtr; - Tcl_HashTable *hTblPtr; + Tcl_HashTable *hiddenCmdTablePtr; Tcl_HashEntry *hPtr; int new; if (iPtr->flags & DELETED) { @@ -1140,27 +1174,25 @@ /* * Initialize the hidden command table if necessary. */ - hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclHiddenCmds", - NULL); - if (hTblPtr == (Tcl_HashTable *) NULL) { - hTblPtr = (Tcl_HashTable *) + hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr; + if (hiddenCmdTablePtr == NULL) { + hiddenCmdTablePtr = (Tcl_HashTable *) ckalloc((unsigned) sizeof(Tcl_HashTable)); - Tcl_InitHashTable(hTblPtr, TCL_STRING_KEYS); - Tcl_SetAssocData(interp, "tclHiddenCmds", HiddenCmdsDeleteProc, - (ClientData) hTblPtr); + 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(hTblPtr, hiddenCmdToken, &new); + hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &new); if (!new) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "hidden command named \"", hiddenCmdToken, "\" already exists", (char *) NULL); return TCL_ERROR; @@ -1216,11 +1248,11 @@ * 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 interp->result. + * in the interp's result. * * Side effects: * Moves commands from one hash table to another. * *---------------------------------------------------------------------- @@ -1235,11 +1267,11 @@ { Interp *iPtr = (Interp *) interp; Command *cmdPtr; Namespace *nsPtr; Tcl_HashEntry *hPtr; - Tcl_HashTable *hTblPtr; + Tcl_HashTable *hiddenCmdTablePtr; int new; if (iPtr->flags & DELETED) { /* * The interpreter is being deleted. Do not create any new @@ -1262,28 +1294,18 @@ (char *) NULL); return TCL_ERROR; } /* - * Find the hash table for the hidden commands; error out if there - * is none. - */ - - hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclHiddenCmds", - NULL); - if (hTblPtr == NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "unknown hidden command \"", hiddenCmdToken, - "\"", (char *) NULL); - return TCL_ERROR; - } - - /* * Get the command from the hidden command table: */ - hPtr = Tcl_FindHashEntry(hTblPtr, hiddenCmdToken); + hPtr = NULL; + hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr; + if (hiddenCmdTablePtr != NULL) { + hPtr = Tcl_FindHashEntry(hiddenCmdTablePtr, hiddenCmdToken); + } if (hPtr == (Tcl_HashEntry *) NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "unknown hidden command \"", hiddenCmdToken, "\"", (char *) NULL); return TCL_ERROR; @@ -1403,15 +1425,17 @@ Tcl_CmdDeleteProc *deleteProc; /* If not NULL, gives a procedure to call * when this command is deleted. */ { Interp *iPtr = (Interp *) interp; + ImportRef *oldRefPtr = NULL; Namespace *nsPtr, *dummy1, *dummy2; - Command *cmdPtr; + Command *cmdPtr, *refCmdPtr; Tcl_HashEntry *hPtr; char *tail; - int new, result; + int new; + 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. @@ -1425,14 +1449,13 @@ * namespace qualifiers, we put it in the specified namespace; * otherwise, we always put it in the global namespace. */ if (strstr(cmdName, "::") != NULL) { - result = TclGetNamespaceForQualName(interp, cmdName, - (Namespace *) NULL, CREATE_NS_IF_UNKNOWN, &nsPtr, - &dummy1, &dummy2, &tail); - if ((result != TCL_OK) || (nsPtr == NULL) || (tail == NULL)) { + TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL, + CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail); + if ((nsPtr == NULL) || (tail == NULL)) { return (Tcl_Command) NULL; } } else { nsPtr = iPtr->globalNsPtr; tail = cmdName; @@ -1440,23 +1463,29 @@ hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new); if (!new) { /* * 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 = (Command *) Tcl_GetHashValue(hPtr); + oldRefPtr = cmdPtr->importRefPtr; + cmdPtr->importRefPtr = NULL; + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr); hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new); if (!new) { /* * 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((char*) cmdPtr); + ckfree((char*) Tcl_GetHashValue(hPtr)); } } cmdPtr = (Command *) ckalloc(sizeof(Command)); Tcl_SetHashValue(hPtr, cmdPtr); cmdPtr->hPtr = hPtr; @@ -1470,10 +1499,25 @@ cmdPtr->clientData = clientData; cmdPtr->deleteProc = deleteProc; cmdPtr->deleteData = clientData; cmdPtr->deleted = 0; cmdPtr->importRefPtr = 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 = (ImportedCmdData*)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 @@ -1491,11 +1535,11 @@ * * 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_NameOfCommand. + * 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 @@ -1527,15 +1571,17 @@ Tcl_CmdDeleteProc *deleteProc; /* If not NULL, gives a procedure to call * when this command is deleted. */ { Interp *iPtr = (Interp *) interp; + ImportRef *oldRefPtr = NULL; Namespace *nsPtr, *dummy1, *dummy2; - Command *cmdPtr; + Command *cmdPtr, *refCmdPtr; Tcl_HashEntry *hPtr; char *tail; - int new, result; + int new; + 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. @@ -1549,14 +1595,13 @@ * namespace qualifiers, we put it in the specified namespace; * otherwise, we always put it in the global namespace. */ if (strstr(cmdName, "::") != NULL) { - result = TclGetNamespaceForQualName(interp, cmdName, - (Namespace *) NULL, CREATE_NS_IF_UNKNOWN, &nsPtr, - &dummy1, &dummy2, &tail); - if ((result != TCL_OK) || (nsPtr == NULL) || (tail == NULL)) { + TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL, + CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail); + if ((nsPtr == NULL) || (tail == NULL)) { return (Tcl_Command) NULL; } } else { nsPtr = iPtr->globalNsPtr; tail = cmdName; @@ -1578,10 +1623,20 @@ cmdPtr->deleteProc = deleteProc; cmdPtr->deleteData = 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. + */ + + oldRefPtr = cmdPtr->importRefPtr; + cmdPtr->importRefPtr = NULL; + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr); hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new); if (!new) { /* * If the deletion callback recreated the command, just throw @@ -1605,11 +1660,34 @@ cmdPtr->clientData = (ClientData) cmdPtr; cmdPtr->deleteProc = deleteProc; cmdPtr->deleteData = clientData; cmdPtr->deleted = 0; cmdPtr->importRefPtr = 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 = (ImportedCmdData*)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; } /* *---------------------------------------------------------------------- @@ -1655,19 +1733,18 @@ /* * Create the string argument array "argv". Make sure argv is large * enough to hold the objc arguments plus 1 extra for the zero * end-of-argv word. - * THIS FAILS IF ANY ARGUMENT OBJECT CONTAINS AN EMBEDDED NULL. */ if ((objc + 1) > NUM_ARGS) { argv = (char **) ckalloc((unsigned)(objc + 1) * sizeof(char *)); } for (i = 0; i < objc; i++) { - argv[i] = Tcl_GetStringFromObj(objv[i], (int *) NULL); + argv[i] = Tcl_GetString(objv[i]); } argv[objc] = 0; /* * Invoke the command's string-based Tcl_CmdProc. @@ -1756,15 +1833,13 @@ result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, argc, objv); /* * Move the interpreter's object result to the string result, * then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULL BYTES. */ - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL), + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), TCL_VOLATILE); /* * Decrement the ref counts for the argument objects created above, * then free the objv array if malloc'ed storage was used. @@ -1850,16 +1925,13 @@ * The rename operation is like creating a command, so we should * automatically create the containing namespaces just like * Tcl_CreateCommand would. */ - result = TclGetNamespaceForQualName(interp, newName, (Namespace *) NULL, - (CREATE_NS_IF_UNKNOWN | TCL_LEAVE_ERR_MSG), - &newNsPtr, &dummy1, &dummy2, &newTail); - if (result != TCL_OK) { - return result; - } + TclGetNamespaceForQualName(interp, newName, (Namespace *) NULL, + CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail); + if ((newNsPtr == NULL) || (newTail == NULL)) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't rename to \"", newName, "\": bad command name", (char *) NULL); return TCL_ERROR; @@ -2334,87 +2406,96 @@ } /* *---------------------------------------------------------------------- * - * Tcl_Eval -- - * - * Execute a Tcl command in a string. - * - * Results: - * The return value is one of the return codes defined in tcl.h - * (such as TCL_OK), and interp->result contains a string value - * to supplement the return code. The value of interp->result - * will persist only until the next call to Tcl_Eval or Tcl_EvalObj: - * you must copy it or lose it! - * - * Side effects: - * The string is compiled to produce a ByteCode object that holds the - * command's bytecode instructions. However, this ByteCode object is - * lost after executing the command. The command's execution will - * almost certainly have side effects. interp->termOffset is set to the - * offset of the character in "string" just after the last one - * successfully compiled or executed. - * - *---------------------------------------------------------------------- - */ - -int -Tcl_Eval(interp, string) - Tcl_Interp *interp; /* Token for command interpreter (returned - * by previous call to Tcl_CreateInterp). */ - char *string; /* Pointer to TCL command to execute. */ -{ - register Tcl_Obj *cmdPtr; - int length = strlen(string); - int result; - - if (length > 0) { - /* - * Initialize a Tcl object from the command string. - */ - - TclNewObj(cmdPtr); - TclInitStringRep(cmdPtr, string, length); - Tcl_IncrRefCount(cmdPtr); - - /* - * Compile and execute the bytecodes. - */ - - result = Tcl_EvalObj(interp, cmdPtr); - - /* - * Move the interpreter's object result to the string result, - * then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS. - */ - - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL), - TCL_VOLATILE); - - /* - * Discard the Tcl object created to hold the command and its code. - */ - - Tcl_DecrRefCount(cmdPtr); - } else { - /* - * An empty string. Just reset the interpreter's result. - */ - - Tcl_ResetResult(interp); - result = TCL_OK; - } - return result; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_EvalObj -- + * Tcl_CreateMathFunc -- + * + * Creates a new math function for expressions in a given + * interpreter. + * + * Results: + * None. + * + * Side effects: + * The 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(interp, name, numArgs, argTypes, proc, clientData) + Tcl_Interp *interp; /* Interpreter in which function is + * to be available. */ + 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; /* Procedure that implements the + * math function. */ + ClientData clientData; /* Additional value to pass to the + * function. */ +{ + Interp *iPtr = (Interp *) interp; + Tcl_HashEntry *hPtr; + MathFunc *mathFuncPtr; + int new, i; + + hPtr = Tcl_CreateHashEntry(&iPtr->mathFuncTable, name, &new); + if (new) { + Tcl_SetHashValue(hPtr, ckalloc(sizeof(MathFunc))); + } + mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr); + + if (!new) { + if (mathFuncPtr->builtinFuncIndex >= 0) { + /* + * We are redefining a builtin math function. Invalidate the + * interpreter's existing code by incrementing its + * compileEpoch member. This field is checked in Tcl_EvalObj + * and ObjInterpProc, and code whose compilation epoch doesn't + * match is recompiled. Newly compiled code will no longer + * treat the function as builtin. + */ + + iPtr->compileEpoch++; + } else { + /* + * A non-builtin function is being redefined. We must invalidate + * existing code if the number of arguments has changed. This + * is because existing code was compiled assuming that number. + */ + + if (numArgs != mathFuncPtr->numArgs) { + iPtr->compileEpoch++; + } + } + } + + mathFuncPtr->builtinFuncIndex = -1; /* can't be a builtin function */ + if (numArgs > MAX_MATH_ARGS) { + numArgs = MAX_MATH_ARGS; + } + mathFuncPtr->numArgs = numArgs; + for (i = 0; i < numArgs; i++) { + mathFuncPtr->argTypes[i] = argTypes[i]; + } + mathFuncPtr->proc = proc; + mathFuncPtr->clientData = clientData; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_EvalObjEx -- * * Execute Tcl commands stored in a Tcl object. These commands are * compiled into bytecodes if necessary. * * Results: @@ -2433,25 +2514,60 @@ * *---------------------------------------------------------------------- */ int -Tcl_EvalObj(interp, objPtr) +Tcl_EvalObjEx(interp, objPtr, flags) Tcl_Interp *interp; /* Token for command interpreter * (returned by a previous call to * Tcl_CreateInterp). */ - Tcl_Obj *objPtr; /* Pointer to object containing + 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. */ { register Interp *iPtr = (Interp *) interp; - int flags; /* Interp->evalFlags value when the + int evalFlags; /* Interp->evalFlags value when the * procedure was called. */ register ByteCode* codePtr; /* Tcl Internal type of bytecode. */ int oldCount = iPtr->cmdCount; /* Used to tell whether any commands * at all were executed. */ - int numSrcChars; - register int result; + int numSrcBytes; + int result; + CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr + * in case TCL_EVAL_GLOBAL was set. */ + Namespace *namespacePtr; + + /* + * Prevent the object from being deleted as a side effect of evaling it. + */ + + Tcl_IncrRefCount(objPtr); + + if ((iPtr->flags & USE_EVAL_DIRECT) || (flags & TCL_EVAL_DIRECT)) { + /* + * We're not supposed to use the compiler or byte-code interpreter. + * Let Tcl_EvalEx evaluate the command directly (and probably + * more slowly). + */ + + char *p; + int length; + + p = Tcl_GetStringFromObj(objPtr, &length); + result = Tcl_EvalEx(interp, p, length, flags); + Tcl_DecrRefCount(objPtr); + return result; + } + + savedVarFramePtr = iPtr->varFramePtr; + if (flags & TCL_EVAL_GLOBAL) { + iPtr->varFramePtr = NULL; + } /* * Reset both the interpreter's string and object results and clear out * any error information. This makes sure that we return an empty * result if there are no commands in the command string. @@ -2466,25 +2582,27 @@ iPtr->numLevels++; if (iPtr->numLevels > iPtr->maxNestingDepth) { iPtr->numLevels--; Tcl_AppendToObj(Tcl_GetObjResult(interp), - "too many nested calls to Tcl_EvalObj (infinite loop?)", -1); - return TCL_ERROR; + "too many nested calls to Tcl_EvalObj (infinite loop?)", -1); + result = TCL_ERROR; + goto done; } /* - * On the Mac, we will never reach the default recursion limit before blowing - * the stack. So we need to do a check here. + * On the Mac, we will never reach the default recursion limit before + * blowing the stack. So we need to do a check here. */ if (TclpCheckStackSpace() == 0) { /*NOTREACHED*/ iPtr->numLevels--; Tcl_AppendToObj(Tcl_GetObjResult(interp), - "too many nested calls to Tcl_EvalObj (infinite loop?)", -1); - return TCL_ERROR; + "too many nested calls to Tcl_EvalObj (infinite loop?)", -1); + result = TCL_ERROR; + goto done; } /* * If the interpreter has been deleted, return an error. */ @@ -2492,61 +2610,88 @@ if (iPtr->flags & DELETED) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "attempt to call eval in deleted interpreter", -1); Tcl_SetErrorCode(interp, "CORE", "IDELETE", - "attempt to call eval in deleted interpreter", (char *) NULL); - iPtr->numLevels--; - return TCL_ERROR; + "attempt to call eval in deleted interpreter", + (char *) NULL); + result = TCL_ERROR; + goto done; } /* * Get the ByteCode from the object. If it exists, make sure it hasn't * been invalidated by, e.g., someone redefining a command with a * compile procedure (this might make the compiled code wrong). If * necessary, convert the object to be a ByteCode object and compile it. * Also, if the code was compiled in/for a different interpreter, - * we recompile it. + * or for a different namespace, or for the same namespace but + * with different name resolution rules, we recompile it. + * + * Precompiled objects, however, are immutable and therefore + * they are not recompiled, even if the epoch has changed. */ + + if (iPtr->varFramePtr != NULL) { + namespacePtr = iPtr->varFramePtr->nsPtr; + } else { + namespacePtr = iPtr->globalNsPtr; + } if (objPtr->typePtr == &tclByteCodeType) { codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; - if ((codePtr->iPtr != iPtr) - || (codePtr->compileEpoch != iPtr->compileEpoch)) { - tclByteCodeType.freeIntRepProc(objPtr); + if (((Interp *) *codePtr->interpHandle != iPtr) + || (codePtr->compileEpoch != iPtr->compileEpoch) + || (codePtr->nsPtr != namespacePtr) + || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) { + if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) { + if ((Interp *) *codePtr->interpHandle != iPtr) { + panic("Tcl_EvalObj: compiled script jumped interps"); + } + codePtr->compileEpoch = iPtr->compileEpoch; + } else { + tclByteCodeType.freeIntRepProc(objPtr); + } } } if (objPtr->typePtr != &tclByteCodeType) { - /* - * First reset any error line number information. - */ - - iPtr->errorLine = 1; /* no correct line # information yet */ + iPtr->errorLine = 1; result = tclByteCodeType.setFromAnyProc(interp, objPtr); if (result != TCL_OK) { - iPtr->numLevels--; - return result; + goto done; + } + } else { + codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; + if (((Interp *) *codePtr->interpHandle != iPtr) + || (codePtr->compileEpoch != iPtr->compileEpoch)) { + (*tclByteCodeType.freeIntRepProc)(objPtr); + iPtr->errorLine = 1; + result = (*tclByteCodeType.setFromAnyProc)(interp, objPtr); + if (result != TCL_OK) { + iPtr->numLevels--; + return result; + } } } codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; /* * Extract then reset the compilation flags in the interpreter. * Resetting the flags must be done after any compilation. */ - flags = iPtr->evalFlags; + evalFlags = iPtr->evalFlags; iPtr->evalFlags = 0; /* * Execute the commands. If the code was compiled from an empty string, * don't bother executing the code. */ - numSrcChars = codePtr->numSrcChars; - if (numSrcChars > 0) { + numSrcBytes = codePtr->numSrcBytes; + if ((numSrcBytes > 0) || (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) { /* * Increment the code's ref count while it is being executed. If * afterwards no references to it remain, free the code. */ @@ -2555,11 +2700,10 @@ codePtr->refCount--; if (codePtr->refCount <= 0) { TclCleanupByteCode(codePtr); } } else { - Tcl_ResetResult(interp); result = TCL_OK; } /* * If no commands at all were executed, check for asynchronous @@ -2566,37 +2710,27 @@ * handlers so that they at least get one change to execute. * This is needed to handle event loops written in Tcl with * empty bodies. */ - if ((oldCount == iPtr->cmdCount) && (Tcl_AsyncReady())) { + if ((oldCount == iPtr->cmdCount) && Tcl_AsyncReady()) { result = Tcl_AsyncInvoke(interp, result); } /* - * Free up any extra resources that were allocated. + * Update the interpreter's evaluation level count. If we are again at + * the top level, process any unusual return code returned by the + * evaluated code. */ - iPtr->numLevels--; - if (iPtr->numLevels == 0) { + if (iPtr->numLevels == 1) { if (result == TCL_RETURN) { result = TclUpdateReturnInfo(iPtr); } if ((result != TCL_OK) && (result != TCL_ERROR) - && !(flags & TCL_ALLOW_EXCEPTIONS)) { - Tcl_ResetResult(interp); - if (result == TCL_BREAK) { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "invoked \"break\" outside of a loop", -1); - } else if (result == TCL_CONTINUE) { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "invoked \"continue\" outside of a loop", -1); - } else { - char buf[50]; - sprintf(buf, "command returned bad code: %d", result); - Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); - } + && ((evalFlags & TCL_ALLOW_EXCEPTIONS) == 0)) { + ProcessUnexpectedResult(interp, result); result = TCL_ERROR; } } /* @@ -2603,70 +2737,145 @@ * If an error occurred, record information about what was being * executed when the error occurred. */ if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { - char buf[200]; - char *ellipsis = ""; - char *bytes; - int length; - - /* - * Figure out how much of the command to print in the error - * message (up to a certain number of characters, or up to - * the first new-line). - * THIS FAILS IF THE OBJECT'S STRING REP CONTAINS A NULL. - */ - - bytes = Tcl_GetStringFromObj(objPtr, &length); - length = TclMin(numSrcChars, length); - if (length > 150) { - length = 150; - ellipsis = " ..."; - } - - if (!(iPtr->flags & ERR_IN_PROGRESS)) { - sprintf(buf, "\n while executing\n\"%.*s%s\"", - length, bytes, ellipsis); - } else { - sprintf(buf, "\n invoked from within\n\"%.*s%s\"", - length, bytes, ellipsis); - } - Tcl_AddObjErrorInfo(interp, buf, -1); + RecordTracebackInfo(interp, objPtr, numSrcBytes); } /* * Set the interpreter's termOffset member to the offset of the * character just after the last one executed. We approximate the offset * of the last character executed by using the number of characters * compiled. */ - iPtr->termOffset = numSrcChars; + iPtr->termOffset = numSrcBytes; iPtr->flags &= ~ERR_ALREADY_LOGGED; + + done: + TclDecrRefCount(objPtr); + iPtr->varFramePtr = savedVarFramePtr; + iPtr->numLevels--; return result; } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- + * + * ProcessUnexpectedResult -- + * + * Procedure 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(interp, returnCode) + Tcl_Interp *interp; /* The interpreter in which the unexpected + * result code was returned. */ + int returnCode; /* The unexpected result code. */ +{ + Tcl_ResetResult(interp); + if (returnCode == TCL_BREAK) { + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "invoked \"break\" outside of a loop", -1); + } else if (returnCode == TCL_CONTINUE) { + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "invoked \"continue\" outside of a loop", -1); + } else { + char buf[30 + TCL_INTEGER_SPACE]; + + sprintf(buf, "command returned bad code: %d", returnCode); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + } +} + +/* + *---------------------------------------------------------------------- + * + * RecordTracebackInfo -- + * + * Procedure called by Tcl_EvalObj to record information about what was + * being executed when the error occurred. + * + * Results: + * None. + * + * Side effects: + * Appends information about the script being evaluated to the + * interpreter's "errorInfo" variable. + * + *---------------------------------------------------------------------- + */ + +static void +RecordTracebackInfo(interp, objPtr, numSrcBytes) + Tcl_Interp *interp; /* The interpreter in which the error + * occurred. */ + Tcl_Obj *objPtr; /* Points to object containing script whose + * evaluation resulted in an error. */ + int numSrcBytes; /* Number of bytes compiled in script. */ +{ + Interp *iPtr = (Interp *) interp; + char buf[200]; + char *ellipsis, *bytes; + int length; + + /* + * Decide how much of the command to print in the error message + * (up to a certain number of bytes). + */ + + bytes = Tcl_GetStringFromObj(objPtr, &length); + length = TclMin(numSrcBytes, length); + + ellipsis = ""; + if (length > 150) { + length = 150; + ellipsis = " ..."; + } + + if (!(iPtr->flags & ERR_IN_PROGRESS)) { + sprintf(buf, "\n while executing\n\"%.*s%s\"", + length, bytes, ellipsis); + } else { + sprintf(buf, "\n invoked from within\n\"%.*s%s\"", + length, bytes, ellipsis); + } + Tcl_AddObjErrorInfo(interp, buf, -1); +} + +/* + *--------------------------------------------------------------------------- * * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean -- * * Procedures to evaluate an expression and return its value in a * particular form. * * Results: * Each of the procedures below returns a standard Tcl result. If an - * error occurs then an error message is left in interp->result. - * Otherwise the value of the expression, in the appropriate form, is - * stored at *ptr. If the expression had a result that was + * 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(interp, string, ptr) Tcl_Interp *interp; /* Context in which to evaluate the @@ -2700,16 +2909,13 @@ Tcl_DecrRefCount(resultPtr); /* discard the result object */ } else { /* * Move the interpreter's object result to the string result, * then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS. */ - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), - (int *) NULL), + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), TCL_VOLATILE); } Tcl_DecrRefCount(exprPtr); /* discard the expression object */ } else { /* @@ -2754,16 +2960,13 @@ Tcl_DecrRefCount(resultPtr); /* discard the result object */ } else { /* * Move the interpreter's object result to the string result, * then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS. */ - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), - (int *) NULL), + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), TCL_VOLATILE); } Tcl_DecrRefCount(exprPtr); /* discard the expression object */ } else { /* @@ -2807,16 +3010,13 @@ } if (result != TCL_OK) { /* * Move the interpreter's object result to the string result, * then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS. */ - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), - (int *) NULL), + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), TCL_VOLATILE); } Tcl_DecrRefCount(exprPtr); /* discard the expression object */ } else { /* @@ -2920,13 +3120,10 @@ *ptr = (resultPtr->internalRep.longValue != 0); } else if (resultPtr->typePtr == &tclDoubleType) { *ptr = (resultPtr->internalRep.doubleValue != 0.0); } else { result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr); - if (result != TCL_OK) { - return result; - } } Tcl_DecrRefCount(resultPtr); /* discard the result object */ } return result; } @@ -2999,15 +3196,13 @@ result = TclObjInvoke(interp, argc, objv, flags); /* * Move the interpreter's object result to the string result, * then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS. */ - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL), + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), TCL_VOLATILE); /* * Decrement the ref counts on the objv elements since we are done * with them. @@ -3091,19 +3286,19 @@ *---------------------------------------------------------------------- */ int TclObjInvokeGlobal(interp, objc, objv, flags) - Tcl_Interp *interp; /* Interpreter in which command is - * to be invoked. */ + Tcl_Interp *interp; /* Interpreter in which command is to be + * invoked. */ int objc; /* Count of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument value objects; objv[0] - * points to the name of the - * command to invoke. */ - int flags; /* Combination of flags controlling - * the call: TCL_INVOKE_HIDDEN and - * TCL_INVOKE_NO_UNKNOWN. */ + 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. */ { register Interp *iPtr = (Interp *) interp; int result; CallFrame *savedVarFramePtr; @@ -3131,19 +3326,19 @@ *---------------------------------------------------------------------- */ int TclObjInvoke(interp, objc, objv, flags) - Tcl_Interp *interp; /* Interpreter in which command is - * to be invoked. */ + Tcl_Interp *interp; /* Interpreter in which command is to be + * invoked. */ int objc; /* Count of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument value objects; objv[0] - * points to the name of the - * command to invoke. */ - int flags; /* Combination of flags controlling - * the call: TCL_INVOKE_HIDDEN and - * TCL_INVOKE_NO_UNKNOWN. */ + 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. */ { register Interp *iPtr = (Interp *) interp; Tcl_HashTable *hTblPtr; /* Table of hidden commands. */ char *cmdName; /* Name of the command from objv[0]. */ register Tcl_HashEntry *hPtr; @@ -3163,39 +3358,28 @@ Tcl_AppendToObj(Tcl_GetObjResult(interp), "illegal argument vector", -1); return TCL_ERROR; } - /* - * THE FOLLOWING CODE FAILS IF THE STRING REP CONTAINS NULLS. - */ - - cmdName = Tcl_GetStringFromObj(objv[0], (int *) NULL); + cmdName = Tcl_GetString(objv[0]); if (flags & TCL_INVOKE_HIDDEN) { /* - * Find the table of hidden commands; error out if none. + * We never invoke "unknown" for hidden commands. */ - - hTblPtr = (Tcl_HashTable *) - Tcl_GetAssocData(interp, "tclHiddenCmds", NULL); - if (hTblPtr == (Tcl_HashTable *) NULL) { - badhiddenCmdToken: + + hPtr = NULL; + hTblPtr = ((Interp *) interp)->hiddenCmdTablePtr; + if (hTblPtr != NULL) { + hPtr = Tcl_FindHashEntry(hTblPtr, cmdName); + } + if (hPtr == NULL) { Tcl_ResetResult(interp); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "invalid hidden command name \"", cmdName, "\"", (char *) NULL); return TCL_ERROR; } - hPtr = Tcl_FindHashEntry(hTblPtr, cmdName); - - /* - * We never invoke "unknown" for hidden commands. - */ - - if (hPtr == NULL) { - goto badhiddenCmdToken; - } cmdPtr = (Command *) Tcl_GetHashValue(hPtr); } else { cmdPtr = NULL; cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY); @@ -3252,11 +3436,13 @@ /* * If an error occurred, record information about what was being * executed when the error occurred. */ - if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { + if ((result == TCL_ERROR) + && ((flags & TCL_INVOKE_NO_TRACEBACK) == 0) + && ((iPtr->flags & ERR_ALREADY_LOGGED) == 0)) { Tcl_DString ds; Tcl_DStringInit(&ds); if (!(iPtr->flags & ERR_IN_PROGRESS)) { Tcl_DStringAppend(&ds, "\n while invoking\n\"", -1); @@ -3284,35 +3470,35 @@ /* * Free any locally allocated storage used to call "unknown". */ if (localObjv != (Tcl_Obj **) NULL) { + Tcl_DecrRefCount(localObjv[0]); ckfree((char *) localObjv); } 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 - * interpreter's result is set to the string value of the - * expression. If the result is TCL_OK, then interp->result - * contains an error message. + * 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(interp, string) Tcl_Interp *interp; /* Context in which to evaluate the @@ -3320,11 +3506,11 @@ char *string; /* Expression to evaluate. */ { register Tcl_Obj *exprPtr; Tcl_Obj *resultPtr; int length = strlen(string); - char buf[100]; + char buf[TCL_DOUBLE_SPACE]; int result = TCL_OK; if (length > 0) { TclNewObj(exprPtr); TclInitStringRep(exprPtr, string, length); @@ -3344,28 +3530,23 @@ resultPtr->internalRep.doubleValue, buf); Tcl_SetResult(interp, buf, TCL_VOLATILE); } else { /* * Set interpreter's string result from the result object. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS. */ - Tcl_SetResult(interp, - TclGetStringFromObj(resultPtr, (int *) NULL), - TCL_VOLATILE); + Tcl_SetResult(interp, TclGetString(resultPtr), + TCL_VOLATILE); } Tcl_DecrRefCount(resultPtr); /* discard the result object */ } else { /* * Move the interpreter's object result to the string result, * then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS. */ - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), - (int *) NULL), + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), TCL_VOLATILE); } Tcl_DecrRefCount(exprPtr); /* discard the expression object */ } else { /* @@ -3411,118 +3592,152 @@ * result is stored if no errors occur. */ { Interp *iPtr = (Interp *) interp; CompileEnv compEnv; /* Compilation environment structure * allocated in frame. */ + LiteralTable *localTablePtr = &(compEnv.localLitTable); register ByteCode *codePtr = NULL; /* Tcl Internal type of bytecode. * Initialized to avoid compiler warning. */ AuxData *auxDataPtr; - Interp dummy; + LiteralEntry *entryPtr; Tcl_Obj *saveObjPtr; char *string; - int result; - int i; + int length, i, result; + + /* + * First handle some common expressions specially. + */ + + string = Tcl_GetStringFromObj(objPtr, &length); + if (length == 1) { + if (*string == '0') { + *resultPtrPtr = Tcl_NewLongObj(0); + Tcl_IncrRefCount(*resultPtrPtr); + return TCL_OK; + } else if (*string == '1') { + *resultPtrPtr = Tcl_NewLongObj(1); + Tcl_IncrRefCount(*resultPtrPtr); + return TCL_OK; + } + } else if ((length == 2) && (*string == '!')) { + if (*(string+1) == '0') { + *resultPtrPtr = Tcl_NewLongObj(1); + Tcl_IncrRefCount(*resultPtrPtr); + return TCL_OK; + } else if (*(string+1) == '1') { + *resultPtrPtr = Tcl_NewLongObj(0); + Tcl_IncrRefCount(*resultPtrPtr); + return TCL_OK; + } + } /* * Get the ByteCode from the object. If it exists, make sure it hasn't * been invalidated by, e.g., someone redefining a command with a * compile procedure (this might make the compiled code wrong). If * necessary, convert the object to be a ByteCode object and compile it. * Also, if the code was compiled in/for a different interpreter, we * recompile it. - * THIS FAILS IF THE OBJECT'S STRING REP HAS A NULL BYTE. + * + * Precompiled expressions, however, are immutable and therefore + * they are not recompiled, even if the epoch has changed. + * */ if (objPtr->typePtr == &tclByteCodeType) { codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; - if ((codePtr->iPtr != iPtr) + if (((Interp *) *codePtr->interpHandle != iPtr) || (codePtr->compileEpoch != iPtr->compileEpoch)) { - tclByteCodeType.freeIntRepProc(objPtr); - objPtr->typePtr = (Tcl_ObjType *) NULL; + if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) { + if ((Interp *) *codePtr->interpHandle != iPtr) { + panic("Tcl_ExprObj: compiled expression jumped interps"); + } + codePtr->compileEpoch = iPtr->compileEpoch; + } else { + (*tclByteCodeType.freeIntRepProc)(objPtr); + objPtr->typePtr = (Tcl_ObjType *) NULL; + } } } if (objPtr->typePtr != &tclByteCodeType) { - int length; - string = Tcl_GetStringFromObj(objPtr, &length); - TclInitCompileEnv(interp, &compEnv, string); - result = TclCompileExpr(interp, string, string + length, - /*flags*/ 0, &compEnv); - if (result == TCL_OK) { - /* - * If the expression yielded no instructions (e.g., was empty), - * push an integer zero object as the expressions's result. - */ - - if (compEnv.codeNext == NULL) { - int objIndex = TclObjIndexForString("0", 0, - /*allocStrRep*/ 0, /*inHeap*/ 0, &compEnv); - Tcl_Obj *objPtr = compEnv.objArrayPtr[objIndex]; - - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.longValue = 0; - objPtr->typePtr = &tclIntType; - - TclEmitPush(objIndex, &compEnv); - } - - /* - * Add done instruction at the end of the instruction sequence. - */ - - TclEmitOpcode(INST_DONE, &compEnv); - - TclInitByteCodeObj(objPtr, &compEnv); - codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; - if (tclTraceCompile == 2) { - TclPrintByteCodeObj(interp, objPtr); - } - TclFreeCompileEnv(&compEnv); - } else { - /* - * Compilation errors. Decrement the ref counts on any objects - * in the object array before freeing the compilation - * environment. - */ - - for (i = 0; i < compEnv.objArrayNext; i++) { - Tcl_Obj *elemPtr = compEnv.objArrayPtr[i]; - Tcl_DecrRefCount(elemPtr); - } - + TclInitCompileEnv(interp, &compEnv, string, length); + result = TclCompileExpr(interp, string, length, &compEnv); + + /* + * Free the compilation environment's literal table bucket array if + * it was dynamically allocated. + */ + + if (localTablePtr->buckets != localTablePtr->staticBuckets) { + ckfree((char *) localTablePtr->buckets); + } + + if (result != TCL_OK) { + /* + * Compilation errors. Free storage allocated for compilation. + */ + +#ifdef TCL_COMPILE_DEBUG + TclVerifyLocalLiteralTable(&compEnv); +#endif /*TCL_COMPILE_DEBUG*/ + entryPtr = compEnv.literalArrayPtr; + for (i = 0; i < compEnv.literalArrayNext; i++) { + TclReleaseLiteral(interp, entryPtr->objPtr); + entryPtr++; + } +#ifdef TCL_COMPILE_DEBUG + TclVerifyGlobalLiteralTable(iPtr); +#endif /*TCL_COMPILE_DEBUG*/ + auxDataPtr = compEnv.auxDataArrayPtr; for (i = 0; i < compEnv.auxDataArrayNext; i++) { - if (auxDataPtr->freeProc != NULL) { - auxDataPtr->freeProc(auxDataPtr->clientData); + if (auxDataPtr->type->freeProc != NULL) { + auxDataPtr->type->freeProc(auxDataPtr->clientData); } auxDataPtr++; } TclFreeCompileEnv(&compEnv); return result; } + + /* + * Successful compilation. If the expression yielded no + * instructions, push an zero object as the expression's result. + */ + + if (compEnv.codeNext == compEnv.codeStart) { + TclEmitPush(TclRegisterLiteral(&compEnv, "0", 1, /*onHeap*/ 0), + &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. + */ + + compEnv.numSrcBytes = iPtr->termOffset; + TclEmitOpcode(INST_DONE, &compEnv); + TclInitByteCodeObj(objPtr, &compEnv); + TclFreeCompileEnv(&compEnv); + codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; +#ifdef TCL_COMPILE_DEBUG + if (tclTraceCompile == 2) { + TclPrintByteCodeObj(interp, objPtr); + } +#endif /* TCL_COMPILE_DEBUG */ } /* * Execute the expression after first saving the interpreter's result. */ - dummy.objResultPtr = Tcl_NewObj(); - Tcl_IncrRefCount(dummy.objResultPtr); - if (interp->freeProc == 0) { - dummy.freeProc = (Tcl_FreeProc *) 0; - dummy.result = ""; - Tcl_SetResult((Tcl_Interp *) &dummy, interp->result, - TCL_VOLATILE); - } else { - dummy.freeProc = interp->freeProc; - dummy.result = interp->result; - interp->freeProc = (Tcl_FreeProc *) 0; - } - saveObjPtr = Tcl_GetObjResult(interp); Tcl_IncrRefCount(saveObjPtr); - + Tcl_ResetResult(interp); + /* * Increment the code's ref count while it is being executed. If * afterwards no references to it remain, free the code. */ @@ -3529,10 +3744,12 @@ codePtr->refCount++; result = TclExecuteByteCode(interp, codePtr); codePtr->refCount--; if (codePtr->refCount <= 0) { TclCleanupByteCode(codePtr); + objPtr->typePtr = NULL; + objPtr->internalRep.otherValuePtr = NULL; } /* * If the expression evaluated successfully, store a pointer to its * value object in resultPtrPtr then restore the old interpreter result. @@ -3544,21 +3761,13 @@ if (result == TCL_OK) { *resultPtrPtr = iPtr->objResultPtr; Tcl_IncrRefCount(iPtr->objResultPtr); - Tcl_SetResult(interp, dummy.result, - ((dummy.freeProc == 0) ? TCL_VOLATILE : dummy.freeProc)); - Tcl_DecrRefCount(iPtr->objResultPtr); - iPtr->objResultPtr = saveObjPtr; - } else { - Tcl_DecrRefCount(saveObjPtr); - Tcl_FreeResult((Tcl_Interp *) &dummy); - } - - Tcl_DecrRefCount(dummy.objResultPtr); - dummy.objResultPtr = NULL; + Tcl_SetObjResult(interp, saveObjPtr); + } + Tcl_DecrRefCount(saveObjPtr); return result; } /* *---------------------------------------------------------------------- @@ -3709,11 +3918,11 @@ void Tcl_AddErrorInfo(interp, message) Tcl_Interp *interp; /* Interpreter to which error information * pertains. */ - char *message; /* Message to record. */ + CONST char *message; /* Message to record. */ { Tcl_AddObjErrorInfo(interp, message, -1); } /* @@ -3741,33 +3950,30 @@ void Tcl_AddObjErrorInfo(interp, message, length) Tcl_Interp *interp; /* Interpreter to which error information * pertains. */ - char *message; /* Points to the first byte of an array of + CONST char *message; /* Points to the first byte of an array of * bytes of the message. */ - register int length; /* The number of bytes in 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; - Tcl_Obj *namePtr, *messagePtr; + Tcl_Obj *messagePtr; /* * If we are just starting to log an error, errorInfo is initialized * from the error message in the interpreter's result. */ - namePtr = Tcl_NewStringObj("errorInfo", -1); - Tcl_IncrRefCount(namePtr); - if (!(iPtr->flags & ERR_IN_PROGRESS)) { /* just starting to log error */ iPtr->flags |= ERR_IN_PROGRESS; if (iPtr->result[0] == 0) { - (void) Tcl_ObjSetVar2(interp, namePtr, (Tcl_Obj *) NULL, - iPtr->objResultPtr, TCL_GLOBAL_ONLY); + (void) Tcl_SetVar2Ex(interp, "errorInfo", NULL, iPtr->objResultPtr, + TCL_GLOBAL_ONLY); } else { /* use the string result */ Tcl_SetVar2(interp, "errorInfo", (char *) NULL, interp->result, TCL_GLOBAL_ONLY); } @@ -3787,16 +3993,62 @@ */ if (length != 0) { messagePtr = Tcl_NewStringObj(message, length); Tcl_IncrRefCount(messagePtr); - Tcl_ObjSetVar2(interp, namePtr, (Tcl_Obj *) NULL, messagePtr, + Tcl_SetVar2Ex(interp, "errorInfo", NULL, messagePtr, (TCL_GLOBAL_ONLY | TCL_APPEND_VALUE)); Tcl_DecrRefCount(messagePtr); /* free msg object appended above */ } +} + +/* + *--------------------------------------------------------------------------- + * + * 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 (interp, argList) + 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); + } - Tcl_DecrRefCount(namePtr); /* free the name object */ + result = Tcl_Eval(interp, Tcl_DStringValue(&buf)); + Tcl_DStringFree(&buf); + return result; } /* *---------------------------------------------------------------------- * @@ -3816,57 +4068,39 @@ */ /* VARARGS2 */ /* ARGSUSED */ int Tcl_VarEval TCL_VARARGS_DEF(Tcl_Interp *,arg1) { - va_list argList; - Tcl_DString buf; - char *string; Tcl_Interp *interp; + va_list argList; 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. - */ - interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList); - Tcl_DStringInit(&buf); - while (1) { - string = va_arg(argList, char *); - if (string == NULL) { - break; - } - Tcl_DStringAppend(&buf, string, -1); - } + result = Tcl_VarEvalVA(interp, argList); va_end(argList); - result = Tcl_Eval(interp, Tcl_DStringValue(&buf)); - Tcl_DStringFree(&buf); return result; } /* - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- * * Tcl_GlobalEval -- * * Evaluate a command at global level in an interpreter. * * Results: - * A standard Tcl result is returned, and interp->result is + * 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 * procedures active), just as if an "uplevel #0" command were * being executed. * - *---------------------------------------------------------------------- + --------------------------------------------------------------------------- */ int Tcl_GlobalEval(interp, command) Tcl_Interp *interp; /* Interpreter in which to evaluate command. */ @@ -3877,55 +4111,10 @@ CallFrame *savedVarFramePtr; savedVarFramePtr = iPtr->varFramePtr; iPtr->varFramePtr = NULL; result = Tcl_Eval(interp, command); - iPtr->varFramePtr = savedVarFramePtr; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_GlobalEvalObj -- - * - * Execute Tcl commands stored in a Tcl object at global level in - * an interpreter. These commands are compiled into bytecodes if - * necessary. - * - * Results: - * A standard Tcl result is returned, and the interpreter's result - * contains a Tcl object 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. - * - * The commands are executed in interp, and the execution - * is carried out in the variable context of global level (no - * procedures active), just as if an "uplevel #0" command were - * being executed. - * - *---------------------------------------------------------------------- - */ - -int -Tcl_GlobalEvalObj(interp, objPtr) - Tcl_Interp *interp; /* Interpreter in which to evaluate - * commands. */ - Tcl_Obj *objPtr; /* Pointer to object containing commands - * to execute. */ -{ - register Interp *iPtr = (Interp *) interp; - int result; - CallFrame *savedVarFramePtr; - - savedVarFramePtr = iPtr->varFramePtr; - iPtr->varFramePtr = NULL; - result = Tcl_EvalObj(interp, objPtr); iPtr->varFramePtr = savedVarFramePtr; return result; } /* @@ -3988,5 +4177,44 @@ 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(major, minor, patchLevel, type) + int *major; + int *minor; + int *patchLevel; + int *type; +{ + if (major != NULL) { + *major = TCL_MAJOR_VERSION; + } + if (minor != NULL) { + *minor = TCL_MINOR_VERSION; + } + if (patchLevel != NULL) { + *patchLevel = TCL_RELEASE_SERIAL; + } + if (type != NULL) { + *type = TCL_RELEASE_LEVEL; + } +} + Index: generic/tclBinary.c ================================================================== --- generic/tclBinary.c +++ generic/tclBinary.c @@ -1,17 +1,18 @@ /* * tclBinary.c -- * * This file contains the implementation of the "binary" Tcl built-in - * command . + * 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. * - * SCCS: @(#) tclBinary.c 1.26 97/11/05 13:02:05 + * RCS: @(#) $Id: tclBinary.c,v 1.1.2.4 1999/03/10 06:49:14 stanton Exp $ */ #include #include "tclInt.h" #include "tclPort.h" @@ -26,15 +27,501 @@ /* * Prototypes for local procedures defined in this file: */ +static void DupByteArrayInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, + Tcl_Obj *copyPtr)); +static int FormatNumber _ANSI_ARGS_((Tcl_Interp *interp, int type, + Tcl_Obj *src, unsigned char **cursorPtr)); +static void FreeByteArrayInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr)); static int GetFormatSpec _ANSI_ARGS_((char **formatPtr, char *cmdPtr, int *countPtr)); -static int FormatNumber _ANSI_ARGS_((Tcl_Interp *interp, int type, - Tcl_Obj *src, char **cursorPtr)); -static Tcl_Obj * ScanNumber _ANSI_ARGS_((char *buffer, int type)); +static Tcl_Obj * ScanNumber _ANSI_ARGS_((unsigned char *buffer, int type)); +static int SetByteArrayFromAny _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *objPtr)); +static void UpdateStringOfByteArray _ANSI_ARGS_((Tcl_Obj *listPtr)); + + +/* + * 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. + */ + +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[4]; /* The array of bytes. The actual size of + * this field depends on the 'allocated' field + * above. */ +} ByteArray; + +#define BYTEARRAY_SIZE(len) \ + ((unsigned) (sizeof(ByteArray) - 4 + (len))) +#define GET_BYTEARRAY(objPtr) \ + ((ByteArray *) (objPtr)->internalRep.otherValuePtr) +#define SET_BYTEARRAY(objPtr, baPtr) \ + (objPtr)->internalRep.otherValuePtr = (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. + * + *--------------------------------------------------------------------------- + */ + +#ifdef TCL_MEM_DEBUG +#undef Tcl_NewByteArrayObj + + +Tcl_Obj * +Tcl_NewByteArrayObj(bytes, length) + 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. */ +{ + return Tcl_DbNewByteArrayObj(bytes, length, "unknown", 0); +} + +#else /* if not TCL_MEM_DEBUG */ + +Tcl_Obj * +Tcl_NewByteArrayObj(bytes, length) + 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. */ +{ + 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 checkmem 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. + * + *--------------------------------------------------------------------------- + */ + +#ifdef TCL_MEM_DEBUG + +Tcl_Obj * +Tcl_DbNewByteArrayObj(bytes, length, file, line) + 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. */ + 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. */ +{ + Tcl_Obj *objPtr; + + TclDbNewObj(objPtr, file, line); + Tcl_SetByteArrayObj(objPtr, bytes, length); + return objPtr; +} + +#else /* if not TCL_MEM_DEBUG */ + +Tcl_Obj * +Tcl_DbNewByteArrayObj(bytes, length, file, line) + 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. */ + 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. */ +{ + 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(objPtr, bytes, length) + Tcl_Obj *objPtr; /* Object to initialize as a ByteArray. */ + unsigned char *bytes; /* The array of bytes to use as the new + * value. */ + int length; /* Length of the array of bytes, which must + * be >= 0. */ +{ + Tcl_ObjType *typePtr; + ByteArray *byteArrayPtr; + + if (Tcl_IsShared(objPtr)) { + panic("Tcl_SetByteArrayObj called with shared object"); + } + typePtr = objPtr->typePtr; + if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { + (*typePtr->freeIntRepProc)(objPtr); + } + Tcl_InvalidateStringRep(objPtr); + + byteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length)); + byteArrayPtr->used = length; + byteArrayPtr->allocated = length; + memcpy((VOID *) byteArrayPtr->bytes, (VOID *) 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(objPtr, lengthPtr) + 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; + + 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(objPtr, length) + Tcl_Obj *objPtr; /* The ByteArray object. */ + int length; /* New length for internal byte array. */ +{ + ByteArray *byteArrayPtr, *newByteArrayPtr; + + if (Tcl_IsShared(objPtr)) { + panic("Tcl_SetObjLength called with shared object"); + } + if (objPtr->typePtr != &tclByteArrayType) { + SetByteArrayFromAny(NULL, objPtr); + } + + byteArrayPtr = GET_BYTEARRAY(objPtr); + if (length > byteArrayPtr->allocated) { + newByteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length)); + newByteArrayPtr->used = length; + newByteArrayPtr->allocated = length; + memcpy((VOID *) newByteArrayPtr->bytes, + (VOID *) byteArrayPtr->bytes, (size_t) byteArrayPtr->used); + ckfree((char *) byteArrayPtr); + byteArrayPtr = newByteArrayPtr; + SET_BYTEARRAY(objPtr, byteArrayPtr); + } + Tcl_InvalidateStringRep(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(interp, objPtr) + Tcl_Interp *interp; /* Not used. */ + Tcl_Obj *objPtr; /* The object to convert to type ByteArray. */ +{ + Tcl_ObjType *typePtr; + int length; + char *src, *srcEnd; + unsigned char *dst; + ByteArray *byteArrayPtr; + Tcl_UniChar ch; + + typePtr = objPtr->typePtr; + if (typePtr != &tclByteArrayType) { + src = Tcl_GetStringFromObj(objPtr, &length); + srcEnd = src + length; + + byteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length)); + for (dst = byteArrayPtr->bytes; src < srcEnd; ) { + src += Tcl_UtfToUniChar(src, &ch); + *dst++ = (unsigned char) ch; + } + + byteArrayPtr->used = dst - byteArrayPtr->bytes; + byteArrayPtr->allocated = length; + + if ((typePtr != NULL) && (typePtr->freeIntRepProc) != NULL) { + (*typePtr->freeIntRepProc)(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(objPtr) + Tcl_Obj *objPtr; /* Object with internal rep to free. */ +{ + ckfree((char *) GET_BYTEARRAY(objPtr)); +} + +/* + *--------------------------------------------------------------------------- + * + * 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(srcPtr, copyPtr) + 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 = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length)); + copyArrayPtr->used = length; + copyArrayPtr->allocated = length; + memcpy((VOID *) copyArrayPtr->bytes, (VOID *) srcArrayPtr->bytes, + (size_t) length); + SET_BYTEARRAY(copyPtr, copyArrayPtr); +} + +/* + *--------------------------------------------------------------------------- + * + * 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(objPtr) + 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; i++) { + if ((src[i] == 0) || (src[i] > 127)) { + size++; + } + } + + dst = (char *) ckalloc((unsigned) (size + 1)); + objPtr->bytes = dst; + objPtr->length = size; + + if (size == length) { + memcpy((VOID *) dst, (VOID *) src, (size_t) size); + dst[size] = '\0'; + } else { + for (i = 0; i < length; i++) { + dst += Tcl_UniCharToUtf(src[i], dst); + } + *dst = '\0'; + } +} /* *---------------------------------------------------------------------- * * Tcl_BinaryObjCmd -- @@ -63,67 +550,73 @@ char cmd; /* Current format character. */ int count; /* Count associated with current format * character. */ char *format; /* Pointer to current position in format * string. */ - char *cursor; /* Current position within result buffer. */ - char *maxPos; /* Greatest position within result buffer that + Tcl_Obj *resultPtr; /* 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.*/ - char *buffer; /* Start of data buffer. */ char *errorString, *errorValue, *str; - int offset, size, length; - Tcl_Obj *resultPtr; - - static char *subCmds[] = { "format", "scan", (char *) NULL }; - enum { BinaryFormat, BinaryScan } index; + int offset, size, length, index; + static char *options[] = { + "format", "scan", NULL + }; + enum options { + BINARY_FORMAT, BINARY_SCAN + }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], subCmds, "option", 0, - (int *) &index) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, + &index) != TCL_OK) { return TCL_ERROR; } - switch (index) { - case BinaryFormat: + switch ((enum options) index) { + case BINARY_FORMAT: { if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "formatString ?arg 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 = Tcl_GetStringFromObj(objv[2], NULL); + format = Tcl_GetString(objv[2]); arg = 3; - offset = length = 0; - while (*format != 0) { + offset = 0; + length = 0; + while (*format != '\0') { + str = format; if (!GetFormatSpec(&format, &cmd, &count)) { break; } switch (cmd) { case 'a': case 'A': case 'b': case 'B': case 'h': - case 'H': + case 'H': { /* * For string-type specifiers, the count corresponds - * to the number of characters in a single argument. + * to the number of bytes in a single argument. */ if (arg >= objc) { goto badIndex; } if (count == BINARY_ALL) { - (void)Tcl_GetStringFromObj(objv[arg], &count); + Tcl_GetByteArrayFromObj(objv[arg], &count); } else if (count == BINARY_NOCOUNT) { count = 1; } arg++; if (cmd == 'a' || cmd == 'A') { @@ -132,28 +625,33 @@ offset += (count + 7) / 8; } else { offset += (count + 1) / 2; } break; - - case 'c': + } + case 'c': { size = 1; goto doNumbers; + } case 's': - case 'S': + case 'S': { size = 2; goto doNumbers; + } case 'i': - case 'I': + case 'I': { size = 4; goto doNumbers; - case 'f': + } + case 'f': { size = sizeof(float); goto doNumbers; - case 'd': + } + case 'd': { size = sizeof(double); - doNumbers: + + doNumbers: if (arg >= objc) { goto badIndex; } /* @@ -174,27 +672,32 @@ return TCL_ERROR; } if (count == BINARY_ALL) { count = listc; } else if (count > listc) { - errorString = "number of elements in list does not match count"; - goto error; + Tcl_AppendResult(interp, + "number of elements in list does not match count", + (char *) NULL); + return TCL_ERROR; } } offset += count*size; break; - - case 'x': + } + case 'x': { if (count == BINARY_ALL) { - errorString = "cannot use \"*\" in format string with \"x\""; - goto error; + Tcl_AppendResult(interp, + "cannot use \"*\" in format string with \"x\"", + (char *) NULL); + return TCL_ERROR; } else if (count == BINARY_NOCOUNT) { count = 1; } offset += count; break; - case 'X': + } + case 'X': { if (count == BINARY_NOCOUNT) { count = 1; } if ((count > offset) || (count == BINARY_ALL)) { count = offset; @@ -202,11 +705,12 @@ if (offset > length) { length = offset; } offset -= count; break; - case '@': + } + case '@': { if (offset > length) { length = offset; } if (count == BINARY_ALL) { offset = length; @@ -214,19 +718,14 @@ goto badCount; } else { offset = count; } break; + } default: { - char buf[2]; - - Tcl_ResetResult(interp); - buf[0] = cmd; - buf[1] = '\0'; - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "bad field specifier \"", buf, "\"", NULL); - return TCL_ERROR; + errorString = str; + goto badfield; } } } if (offset > length) { length = offset; @@ -239,22 +738,21 @@ * Prepare the result object by preallocating the caclulated * number of bytes and filling with nulls. */ resultPtr = Tcl_GetObjResult(interp); - Tcl_SetObjLength(resultPtr, length); - buffer = Tcl_GetStringFromObj(resultPtr, NULL); - memset(buffer, 0, (size_t) length); + buffer = Tcl_SetByteArrayLength(resultPtr, length); + memset((VOID *) 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 = 3; - format = Tcl_GetStringFromObj(objv[2], NULL); + format = Tcl_GetString(objv[2]); cursor = buffer; maxPos = cursor; while (*format != 0) { if (!GetFormatSpec(&format, &cmd, &count)) { break; @@ -265,33 +763,34 @@ } switch (cmd) { case 'a': case 'A': { char pad = (char) (cmd == 'a' ? '\0' : ' '); + unsigned char *bytes; - str = Tcl_GetStringFromObj(objv[arg++], &length); + bytes = Tcl_GetByteArrayFromObj(objv[arg++], &length); if (count == BINARY_ALL) { count = length; } else if (count == BINARY_NOCOUNT) { count = 1; } if (length >= count) { - memcpy((VOID *) cursor, (VOID *) str, + memcpy((VOID *) cursor, (VOID *) bytes, (size_t) count); } else { - memcpy((VOID *) cursor, (VOID *) str, + memcpy((VOID *) cursor, (VOID *) bytes, (size_t) length); - memset(cursor+length, pad, + memset((VOID *) (cursor + length), pad, (size_t) (count - length)); } cursor += count; break; } case 'b': case 'B': { - char *last; + unsigned char *last; str = Tcl_GetStringFromObj(objv[arg++], &length); if (count == BINARY_ALL) { count = length; } else if (count == BINARY_NOCOUNT) { @@ -311,11 +810,11 @@ } else if (str[offset] != '0') { errorValue = str; goto badValue; } if (((offset + 1) % 8) == 0) { - *cursor++ = (char)(value & 0xff); + *cursor++ = (unsigned char) value; value = 0; } } } else { for (offset = 0; offset < count; offset++) { @@ -325,11 +824,11 @@ } else if (str[offset] != '0') { errorValue = str; goto badValue; } if (!((offset + 1) % 8)) { - *cursor++ = (char)(value & 0xff); + *cursor++ = (unsigned char) value; value = 0; } } } if ((offset % 8) != 0) { @@ -336,20 +835,20 @@ if (cmd == 'B') { value <<= 8 - (offset % 8); } else { value >>= 8 - (offset % 8); } - *cursor++ = (char)(value & 0xff); + *cursor++ = (unsigned char) value; } while (cursor < last) { *cursor++ = '\0'; } break; } case 'h': case 'H': { - char *last; + unsigned char *last; int c; str = Tcl_GetStringFromObj(objv[arg++], &length); if (count == BINARY_ALL) { count = length; @@ -363,38 +862,45 @@ value = 0; errorString = "hexadecimal"; if (cmd == 'H') { for (offset = 0; offset < count; offset++) { value <<= 4; - c = tolower(((unsigned char *) str)[offset]); - if ((c >= 'a') && (c <= 'f')) { - value |= ((c - 'a' + 10) & 0xf); - } else if ((c >= '0') && (c <= '9')) { - value |= (c - '0') & 0xf; - } else { + if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */ errorValue = str; 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; - c = tolower(((unsigned char *) str)[offset]); - if ((c >= 'a') && (c <= 'f')) { - value |= ((c - 'a' + 10) << 4) & 0xf0; - } else if ((c >= '0') && (c <= '9')) { - value |= ((c - '0') << 4) & 0xf0; - } else { + + if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */ errorValue = str; 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++ = (char)(value & 0xff); + *cursor++ = (unsigned char)(value & 0xff); value = 0; } } } if (offset % 2) { @@ -401,11 +907,11 @@ if (cmd == 'H') { value <<= 4; } else { value >>= 4; } - *cursor++ = (char) value; + *cursor++ = (unsigned char) value; } while (cursor < last) { *cursor++ = '\0'; } @@ -445,18 +951,19 @@ return TCL_ERROR; } } break; } - case 'x': + case 'x': { if (count == BINARY_NOCOUNT) { count = 1; } memset(cursor, 0, (size_t) count); cursor += count; break; - case 'X': + } + case 'X': { if (cursor > maxPos) { maxPos = cursor; } if (count == BINARY_NOCOUNT) { count = 1; @@ -466,45 +973,50 @@ cursor = buffer; } else { cursor -= count; } break; - case '@': + } + case '@': { if (cursor > maxPos) { maxPos = cursor; } if (count == BINARY_ALL) { cursor = maxPos; } else { cursor = buffer + count; } break; + } } } break; - - case BinaryScan: { + } + case BINARY_SCAN: { int i; Tcl_Obj *valuePtr, *elementPtr; if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, "value formatString ?varName varName ...?"); return TCL_ERROR; } - buffer = Tcl_GetStringFromObj(objv[2], &length); - format = Tcl_GetStringFromObj(objv[3], NULL); + buffer = Tcl_GetByteArrayFromObj(objv[2], &length); + format = Tcl_GetString(objv[3]); cursor = buffer; arg = 4; offset = 0; - while (*format != 0) { + while (*format != '\0') { + str = format; if (!GetFormatSpec(&format, &cmd, &count)) { goto done; } switch (cmd) { case 'a': - case 'A': + case 'A': { + unsigned char *src; + if (arg >= objc) { goto badIndex; } if (count == BINARY_ALL) { count = length - offset; @@ -515,80 +1027,82 @@ if (count > (length - offset)) { goto done; } } - str = buffer + offset; + src = buffer + offset; size = count; /* * Trim trailing nulls and spaces, if necessary. */ if (cmd == 'A') { while (size > 0) { - if (str[size-1] != '\0' && str[size-1] != ' ') { + if (src[size-1] != '\0' && src[size-1] != ' ') { break; } size--; } } - valuePtr = Tcl_NewStringObj(str, size); - resultPtr = Tcl_ObjSetVar2(interp, objv[arg++], NULL, - valuePtr, - TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1); + valuePtr = Tcl_NewByteArrayObj(src, size); + resultPtr = Tcl_ObjSetVar2(interp, objv[arg], + NULL, valuePtr, TCL_LEAVE_ERR_MSG); + arg++; if (resultPtr == NULL) { Tcl_DecrRefCount(valuePtr); /* unneeded */ return TCL_ERROR; } offset += count; break; + } case 'b': case 'B': { + unsigned char *src; char *dest; if (arg >= objc) { goto badIndex; } if (count == BINARY_ALL) { - count = (length - offset)*8; + count = (length - offset) * 8; } else { if (count == BINARY_NOCOUNT) { count = 1; } - if (count > (length - offset)*8) { + if (count > (length - offset) * 8) { goto done; } } - str = buffer + offset; + src = buffer + offset; valuePtr = Tcl_NewObj(); Tcl_SetObjLength(valuePtr, count); - dest = Tcl_GetStringFromObj(valuePtr, NULL); + dest = Tcl_GetString(valuePtr); if (cmd == 'b') { for (i = 0; i < count; i++) { if (i % 8) { value >>= 1; } else { - value = *str++; + value = *src++; } *dest++ = (char) ((value & 1) ? '1' : '0'); } } else { for (i = 0; i < count; i++) { if (i % 8) { value <<= 1; } else { - value = *str++; + value = *src++; } *dest++ = (char) ((value & 0x80) ? '1' : '0'); } } - resultPtr = Tcl_ObjSetVar2(interp, objv[arg++], NULL, - valuePtr, - TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1); + resultPtr = Tcl_ObjSetVar2(interp, objv[arg], + NULL, valuePtr, TCL_LEAVE_ERR_MSG); + arg++; if (resultPtr == NULL) { Tcl_DecrRefCount(valuePtr); /* unneeded */ return TCL_ERROR; } offset += (count + 7 ) / 8; @@ -595,10 +1109,11 @@ break; } case 'h': case 'H': { char *dest; + unsigned char *src; int i; static char hexdigit[] = "0123456789abcdef"; if (arg >= objc) { goto badIndex; @@ -611,63 +1126,70 @@ } if (count > (length - offset)*2) { goto done; } } - str = buffer + offset; + src = buffer + offset; valuePtr = Tcl_NewObj(); Tcl_SetObjLength(valuePtr, count); - dest = Tcl_GetStringFromObj(valuePtr, NULL); + dest = Tcl_GetString(valuePtr); if (cmd == 'h') { for (i = 0; i < count; i++) { if (i % 2) { value >>= 4; } else { - value = *str++; + value = *src++; } *dest++ = hexdigit[value & 0xf]; } } else { for (i = 0; i < count; i++) { if (i % 2) { value <<= 4; } else { - value = *str++; + value = *src++; } *dest++ = hexdigit[(value >> 4) & 0xf]; } } - resultPtr = Tcl_ObjSetVar2(interp, objv[arg++], NULL, - valuePtr, - TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1); + resultPtr = Tcl_ObjSetVar2(interp, objv[arg], + NULL, valuePtr, TCL_LEAVE_ERR_MSG); + arg++; if (resultPtr == NULL) { Tcl_DecrRefCount(valuePtr); /* unneeded */ return TCL_ERROR; } offset += (count + 1) / 2; break; } - case 'c': + case 'c': { size = 1; goto scanNumber; + } case 's': - case 'S': + case 'S': { size = 2; goto scanNumber; + } case 'i': - case 'I': + case 'I': { size = 4; goto scanNumber; - case 'f': + } + case 'f': { size = sizeof(float); goto scanNumber; - case 'd': + } + case 'd': { + unsigned char *src; + size = sizeof(double); /* fall through */ - scanNumber: + + scanNumber: if (arg >= objc) { goto badIndex; } if (count == BINARY_NOCOUNT) { if ((length - offset) < size) { @@ -681,29 +1203,30 @@ } if ((length - offset) < (count * size)) { goto done; } valuePtr = Tcl_NewObj(); - str = buffer+offset; + src = buffer+offset; for (i = 0; i < count; i++) { - elementPtr = ScanNumber(str, cmd); - str += size; + elementPtr = ScanNumber(src, cmd); + src += size; Tcl_ListObjAppendElement(NULL, valuePtr, elementPtr); } offset += count*size; } - resultPtr = Tcl_ObjSetVar2(interp, objv[arg++], NULL, - valuePtr, - TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1); + resultPtr = Tcl_ObjSetVar2(interp, objv[arg], + NULL, valuePtr, TCL_LEAVE_ERR_MSG); + arg++; if (resultPtr == NULL) { Tcl_DecrRefCount(valuePtr); /* unneeded */ return TCL_ERROR; } break; - case 'x': + } + case 'x': { if (count == BINARY_NOCOUNT) { count = 1; } if ((count == BINARY_ALL) || (count > (length - offset))) { @@ -710,39 +1233,36 @@ offset = length; } else { offset += count; } break; - case 'X': + } + case 'X': { if (count == BINARY_NOCOUNT) { count = 1; } if ((count == BINARY_ALL) || (count > offset)) { offset = 0; } else { offset -= count; } break; - case '@': + } + case '@': { if (count == BINARY_NOCOUNT) { goto badCount; } if ((count == BINARY_ALL) || (count > length)) { offset = length; } else { offset = count; } break; + } default: { - char buf[2]; - - Tcl_ResetResult(interp); - buf[0] = cmd; - buf[1] = '\0'; - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "bad field specifier \"", buf, "\"", NULL); - return TCL_ERROR; + errorString = str; + goto badfield; } } } /* @@ -768,14 +1288,23 @@ 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_AppendResult(interp, "bad field specifier \"", buf, "\"", NULL); + return TCL_ERROR; + } error: - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), errorString, -1); + Tcl_AppendResult(interp, errorString, NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -827,11 +1356,11 @@ *cmdPtr = **formatPtr; (*formatPtr)++; if (**formatPtr == '*') { (*formatPtr)++; (*countPtr) = BINARY_ALL; - } else if (isdigit(**formatPtr)) { + } else if (isdigit(UCHAR(**formatPtr))) { /* INTL: digit */ (*countPtr) = strtoul(*formatPtr, formatPtr, 10); } else { (*countPtr) = BINARY_NOCOUNT; } return 1; @@ -858,28 +1387,27 @@ FormatNumber(interp, type, src, cursorPtr) Tcl_Interp *interp; /* Current interpreter, used to report * errors. */ int type; /* Type of number to format. */ Tcl_Obj *src; /* Number to format. */ - char **cursorPtr; /* Pointer to index into destination buffer. */ + unsigned char **cursorPtr; /* Pointer to index into destination buffer. */ { int value; double dvalue; - char cmd = (char)type; - if (cmd == 'd' || cmd == 'f') { + if ((type == 'd') || (type == 'f')) { /* * For floating point types, we need to copy the data using * memcpy to avoid alignment issues. */ if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) { return TCL_ERROR; } - if (cmd == 'd') { - memcpy((*cursorPtr), &dvalue, sizeof(double)); - (*cursorPtr) += sizeof(double); + if (type == 'd') { + memcpy((VOID *) *cursorPtr, (VOID *) &dvalue, sizeof(double)); + *cursorPtr += sizeof(double); } else { float fvalue; /* * Because some compilers will generate floating point exceptions @@ -890,35 +1418,35 @@ if (fabs(dvalue) > (double)FLT_MAX) { fvalue = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX; } else { fvalue = (float) dvalue; } - memcpy((*cursorPtr), &fvalue, sizeof(float)); - (*cursorPtr) += sizeof(float); + memcpy((VOID *) *cursorPtr, (VOID *) &fvalue, sizeof(float)); + *cursorPtr += sizeof(float); } } else { if (Tcl_GetIntFromObj(interp, src, &value) != TCL_OK) { return TCL_ERROR; } - if (cmd == 'c') { - *(*cursorPtr)++ = (char)(value & 0xff); - } else if (cmd == 's') { - *(*cursorPtr)++ = (char)(value & 0xff); - *(*cursorPtr)++ = (char)((value >> 8) & 0xff); - } else if (cmd == 'S') { - *(*cursorPtr)++ = (char)((value >> 8) & 0xff); - *(*cursorPtr)++ = (char)(value & 0xff); - } else if (cmd == 'i') { - *(*cursorPtr)++ = (char)(value & 0xff); - *(*cursorPtr)++ = (char)((value >> 8) & 0xff); - *(*cursorPtr)++ = (char)((value >> 16) & 0xff); - *(*cursorPtr)++ = (char)((value >> 24) & 0xff); - } else if (cmd == 'I') { - *(*cursorPtr)++ = (char)((value >> 24) & 0xff); - *(*cursorPtr)++ = (char)((value >> 16) & 0xff); - *(*cursorPtr)++ = (char)((value >> 8) & 0xff); - *(*cursorPtr)++ = (char)(value & 0xff); + if (type == 'c') { + *(*cursorPtr)++ = (unsigned char) value; + } else if (type == 's') { + *(*cursorPtr)++ = (unsigned char) value; + *(*cursorPtr)++ = (unsigned char) (value >> 8); + } else if (type == 'S') { + *(*cursorPtr)++ = (unsigned char) (value >> 8); + *(*cursorPtr)++ = (unsigned char) value; + } else if (type == 'i') { + *(*cursorPtr)++ = (unsigned char) value; + *(*cursorPtr)++ = (unsigned char) (value >> 8); + *(*cursorPtr)++ = (unsigned char) (value >> 16); + *(*cursorPtr)++ = (unsigned char) (value >> 24); + } else if (type == 'I') { + *(*cursorPtr)++ = (unsigned char) (value >> 24); + *(*cursorPtr)++ = (unsigned char) (value >> 16); + *(*cursorPtr)++ = (unsigned char) (value >> 8); + *(*cursorPtr)++ = (unsigned char) value; } } return TCL_OK; } @@ -940,54 +1468,62 @@ *---------------------------------------------------------------------- */ static Tcl_Obj * ScanNumber(buffer, type) - char *buffer; /* Buffer to scan number from. */ + unsigned char *buffer; /* Buffer to scan number from. */ int type; /* Format character from "binary scan" */ { - int value; + long value; /* * 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. */ - switch ((char) type) { - case 'c': - value = buffer[0]; + 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 (value & 0x80) { value |= -0x100; } return Tcl_NewLongObj((long)value); - case 's': - value = (((unsigned char)buffer[0]) - + ((unsigned char)buffer[1] << 8)); + } + case 's': { + value = (long) (buffer[0] + (buffer[1] << 8)); goto shortValue; - case 'S': - value = (((unsigned char)buffer[1]) - + ((unsigned char)buffer[0] << 8)); + } + case 'S': { + value = (long) (buffer[1] + (buffer[0] << 8)); shortValue: if (value & 0x8000) { value |= -0x10000; } - return Tcl_NewLongObj((long)value); - case 'i': - value = (((unsigned char)buffer[0]) - + ((unsigned char)buffer[1] << 8) - + ((unsigned char)buffer[2] << 16) - + ((unsigned char)buffer[3] << 24)); + return Tcl_NewLongObj(value); + } + case 'i': { + value = (long) (buffer[0] + + (buffer[1] << 8) + + (buffer[2] << 16) + + (buffer[3] << 24)); goto intValue; - case 'I': - value = (((unsigned char)buffer[3]) - + ((unsigned char)buffer[2] << 8) - + ((unsigned char)buffer[1] << 16) - + ((unsigned char)buffer[0] << 24)); + } + case 'I': { + value = (long) (buffer[3] + + (buffer[2] << 8) + + (buffer[1] << 16) + + (buffer[0] << 24)); intValue: /* * Check to see if the value was sign extended properly on * systems where an int is more than 32-bits. */ @@ -994,20 +1530,20 @@ if ((value & (((unsigned int)1)<<31)) && (value > 0)) { value -= (((unsigned int)1)<<31); value -= (((unsigned int)1)<<31); } - - return Tcl_NewLongObj((long)value); + return Tcl_NewLongObj(value); + } case 'f': { float fvalue; - memcpy(&fvalue, buffer, sizeof(float)); + memcpy((VOID *) &fvalue, (VOID *) buffer, sizeof(float)); return Tcl_NewDoubleObj(fvalue); } case 'd': { double dvalue; - memcpy(&dvalue, buffer, sizeof(double)); + memcpy((VOID *) &dvalue, (VOID *) buffer, sizeof(double)); return Tcl_NewDoubleObj(dvalue); } } return NULL; } Index: generic/tclCkalloc.c ================================================================== --- generic/tclCkalloc.c +++ generic/tclCkalloc.c @@ -3,18 +3,19 @@ * * 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-1996 Sun Microsystems, Inc. + * 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 * - * SCCS: @(#) tclCkalloc.c 1.28 97/04/30 12:09:04 + * RCS: @(#) $Id: tclCkalloc.c,v 1.1.2.4 1999/03/10 06:49:14 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" @@ -99,19 +100,60 @@ 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 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 TclpMutex ckallocMutex; +static int ckallocInit = 0; + /* * Prototypes for procedures defined in this file: */ +static int CheckmemCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char *argv[])); static int MemoryCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv)); static void ValidateMemory _ANSI_ARGS_(( struct mem_header *memHeaderP, char *file, int line, int nukeGuards)); + +/* + *---------------------------------------------------------------------- + * + * TclInitDbCkalloc -- + * Initialize the locks used by the allocator. + * This is only appropriate to call in a single threaded environtment, + * such as during TclInitSubsystems. + * + *---------------------------------------------------------------------- + */ +void +TclInitDbCkalloc() +{ + if (!ckallocInit) { + ckallocInit = 1; + TclpMutexInit(&ckallocMutex); + } +} /* *---------------------------------------------------------------------- * * TclDumpMemoryInfo -- @@ -162,11 +204,11 @@ if (byte != GUARD_VALUE) { guard_failed = TRUE; fflush(stdout); byte &= 0xff; fprintf(stderr, "low guard byte %d is 0x%x \t%c\n", idx, byte, - (isprint(UCHAR(byte)) ? byte : ' ')); + (isprint(UCHAR(byte)) ? byte : ' ')); /* INTL: bytes */ } } if (guard_failed) { TclDumpMemoryInfo (stderr); fprintf(stderr, "low guard failed at %lx, %s %d\n", @@ -183,11 +225,11 @@ if (byte != GUARD_VALUE) { guard_failed = TRUE; fflush (stdout); byte &= 0xff; fprintf(stderr, "hi guard byte %d is 0x%x \t%c\n", idx, byte, - (isprint(UCHAR(byte)) ? byte : ' ')); + (isprint(UCHAR(byte)) ? byte : ' ')); /* INTL: bytes */ } } if (guard_failed) { TclDumpMemoryInfo (stderr); @@ -220,13 +262,19 @@ char *file; int line; { struct mem_header *memScanP; - for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) + if (!ckallocInit) { + ckallocInit = 1; + TclpMutexInit(&ckallocMutex); + } + TclpMutexLock(&ckallocMutex); + for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) { ValidateMemory(memScanP, file, line, FALSE); - + } + TclpMutexUnlock(&ckallocMutex); } /* *---------------------------------------------------------------------- * @@ -244,24 +292,34 @@ { FILE *fileP; struct mem_header *memScanP; char *address; - fileP = fopen(fileName, "w"); - if (fileP == NULL) - return TCL_ERROR; + if (fileName == NULL) { + fileP = stdout; + } else { + fileP = fopen(fileName, "w"); + if (fileP == NULL) { + return TCL_ERROR; + } + } + TclpMutexLock(&ckallocMutex); for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) { address = &memScanP->body [0]; fprintf(fileP, "%8lx - %8lx %7ld @ %s %d %s", (long unsigned int) address, (long unsigned int) address + memScanP->length - 1, memScanP->length, memScanP->file, memScanP->line, (memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string); (void) fputc('\n', fileP); } - fclose (fileP); + TclpMutexUnlock(&ckallocMutex); + + if (fileP != stderr) { + fclose (fileP); + } return TCL_OK; } /* *---------------------------------------------------------------------- @@ -311,19 +369,25 @@ size + sizeof(struct mem_header) + HIGH_GUARD_SIZE); } else { memset ((char *) result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE); memset (result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE); } + if (!ckallocInit) { + ckallocInit = 1; + TclpMutexInit(&ckallocMutex); + } + TclpMutexLock(&ckallocMutex); 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++; @@ -354,10 +418,12 @@ 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; + + TclpMutexUnlock(&ckallocMutex); return result->body; } /* @@ -401,10 +467,11 @@ (long unsigned int) memp->body, memp->length, file, line); if (validate_memory) Tcl_ValidateAllMemory(file, line); + TclpMutexLock(&ckallocMutex); ValidateMemory(memp, file, line, TRUE); if (init_malloced_bodies) { memset((VOID *) ptr, GUARD_VALUE, (size_t) memp->length); } @@ -427,10 +494,12 @@ if (memp->blink != NULL) memp->blink->flink = memp->flink; if (allocHead == memp) allocHead = memp->flink; TclpFree((char *) memp); + TclpMutexUnlock(&ckallocMutex); + return 0; } /* *-------------------------------------------------------------------- @@ -578,11 +647,18 @@ return TCL_ERROR; } return TCL_OK; } if (strcmp(argv[1],"info") == 0) { - TclDumpMemoryInfo(stdout); + char buffer[400]; + sprintf(buffer, "%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n", + "total mallocs", total_mallocs, "total frees", total_frees, + "current packets allocated", current_malloc_packets, + "current bytes allocated", current_bytes_malloced, + "maximum packets allocated", maximum_malloc_packets, + "maximum bytes allocated", maximum_bytes_malloced); + Tcl_SetResult(interp, buffer, TCL_VOLATILE); return TCL_OK; } if (strcmp(argv[1],"init") == 0) { if (argc != 3) { goto bad_suboption; @@ -646,24 +722,68 @@ } /* *---------------------------------------------------------------------- * + * 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, interp, argc, argv) + ClientData clientData; /* Not used. */ + Tcl_Interp *interp; /* Interpreter for evaluation. */ + int argc; /* Number of arguments. */ + char *argv[]; /* String values of arguments. */ +{ + if (argc != 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " fileName\"", (char *) NULL); + return TCL_ERROR; + } + tclMemDumpFileName = dumpFile; + strcpy(tclMemDumpFileName, argv[1]); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * Tcl_InitMemory -- * Initialize the memory command. * *---------------------------------------------------------------------- */ void Tcl_InitMemory(interp) Tcl_Interp *interp; { + TclInitDbCkalloc(); Tcl_CreateCommand (interp, "memory", MemoryCmd, (ClientData) NULL, + (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateCommand(interp, "checkmem", CheckmemCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); } -#else + +#else /* TCL_MEM_DEBUG */ + +#undef Tcl_InitMemory +#undef Tcl_DumpActiveMemory +#undef Tcl_ValidateAllMemory /* *---------------------------------------------------------------------- * @@ -789,17 +909,10 @@ Tcl_InitMemory(interp) Tcl_Interp *interp; { } -#undef Tcl_DumpActiveMemory -#undef Tcl_ValidateAllMemory - -extern int Tcl_DumpActiveMemory _ANSI_ARGS_((char *fileName)); -extern void Tcl_ValidateAllMemory _ANSI_ARGS_((char *file, - int line)); - int Tcl_DumpActiveMemory(fileName) char *fileName; { return TCL_OK; @@ -810,6 +923,52 @@ char *file; int line; { } +void +TclDumpMemoryInfo(outFile) + FILE *outFile; +{ +} + +#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() +{ +#ifdef TCL_MEM_DEBUG + TclpMutexLock(&ckallocMutex); + if (tclMemDumpFileName != NULL) { + Tcl_DumpActiveMemory(tclMemDumpFileName); + } + if (curTagPtr != NULL) { + TclpFree((char *) curTagPtr); + } + allocHead = NULL; + TclpMutexUnlock(&ckallocMutex); +#endif + +#if USE_TCLALLOC + TclFinalizeAllocSubsystem(); #endif +} Index: generic/tclClock.c ================================================================== --- generic/tclClock.c +++ generic/tclClock.c @@ -9,17 +9,23 @@ * 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. * - * SCCS: @(#) tclClock.c 1.37 97/07/29 10:29:58 + * RCS: @(#) $Id: tclClock.c,v 1.1.2.6 1999/03/10 06:49:14 stanton Exp $ */ #include "tcl.h" #include "tclInt.h" #include "tclPort.h" +/* + * The date parsing stuff uses lexx and has tons o statics. + */ + +TCL_DECLARE_MUTEX(clockMutex) + /* * Function prototypes for local procedures in this file: */ static int FormatClock _ANSI_ARGS_((Tcl_Interp *interp, @@ -170,17 +176,20 @@ } else { zone = TclpGetTimeZone((unsigned long) baseClock); } scanStr = Tcl_GetStringFromObj(objv[2], &dummy); + Tcl_MutexLock(&clockMutex); if (TclGetDate(scanStr, (unsigned long) baseClock, zone, (unsigned long *) &clockVal) < 0) { + Tcl_MutexUnlock(&clockMutex); Tcl_AppendStringsToObj(resultPtr, "unable to convert date-time string \"", scanStr, "\"", (char *) NULL); return TCL_ERROR; } + Tcl_MutexUnlock(&clockMutex); Tcl_SetLongObj(resultPtr, (long) clockVal); return TCL_OK; case 3: /* seconds */ if (objc != 2) { @@ -220,35 +229,39 @@ { struct tm *timeDataPtr; Tcl_DString buffer; int bufSize; char *p; -#ifdef TCL_USE_TIMEZONE_VAR - int savedTimeZone; - char *savedTZEnv; -#endif Tcl_Obj *resultPtr; + int result; +#ifndef HAVE_TM_ZONE + int savedTimeZone = 0; /* lint. */ + char *savedTZEnv = NULL; /* lint. */ +#endif resultPtr = Tcl_GetObjResult(interp); #ifdef HAVE_TZSET /* * Some systems forgot to call tzset in localtime, make sure its done. */ static int calledTzset = 0; + Tcl_MutexLock(&clockMutex); if (!calledTzset) { tzset(); calledTzset = 1; } + Tcl_MutexUnlock(&clockMutex); #endif -#ifdef TCL_USE_TIMEZONE_VAR +#ifndef HAVE_TM_ZONE /* - * This is a horrible kludge for systems not having the timezone in - * struct tm. No matter what was specified, they use the global time - * zone. (Thanks Solaris). + * This is a kludge for systems not having the timezone string in + * struct tm. No matter what was specified, they use the local + * timezone string. */ + if (useGMT) { char *varValue; varValue = Tcl_GetVar2(interp, "env", "TZ", TCL_GLOBAL_ONLY); if (varValue != NULL) { @@ -261,11 +274,11 @@ timezone = 0; tzset(); } #endif - timeDataPtr = TclpGetDate((time_t *) &clockVal, useGMT); + timeDataPtr = TclpGetDate((TclpTime_t) &clockVal, useGMT); /* * Make a guess at the upper limit on the substituted string size * based on the number of percents in the string. */ @@ -278,18 +291,16 @@ } } Tcl_DStringInit(&buffer); Tcl_DStringSetLength(&buffer, bufSize); - if ((TclStrftime(buffer.string, (unsigned int) bufSize, format, - timeDataPtr) == 0) && (*format != '\0')) { - Tcl_AppendStringsToObj(resultPtr, "bad format string \"", - format, "\"", (char *) NULL); - return TCL_ERROR; - } - -#ifdef TCL_USE_TIMEZONE_VAR + Tcl_MutexLock(&clockMutex); + result = TclpStrftime(buffer.string, (unsigned int) bufSize, format, + timeDataPtr); + Tcl_MutexUnlock(&clockMutex); + +#ifndef HAVE_TM_ZONE if (useGMT) { if (savedTZEnv != NULL) { Tcl_SetVar2(interp, "env", "TZ", savedTZEnv, TCL_GLOBAL_ONLY); ckfree(savedTZEnv); } else { @@ -297,11 +308,16 @@ } timezone = savedTimeZone; tzset(); } #endif + if ((result == 0) && (*format != '\0')) { + Tcl_AppendStringsToObj(resultPtr, "bad format string \"", format, + "\"", (char *) NULL); + return TCL_ERROR; + } Tcl_SetStringObj(resultPtr, buffer.string, -1); Tcl_DStringFree(&buffer); return TCL_OK; } Index: generic/tclCmdAH.c ================================================================== --- generic/tclCmdAH.c +++ generic/tclCmdAH.c @@ -9,28 +9,40 @@ * 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. * - * SCCS: @(#) tclCmdAH.c 1.159 97/10/31 13:06:07 + * RCS: @(#) $Id: tclCmdAH.c,v 1.1.2.12 1999/04/14 00:33:21 surles Exp $ */ #include "tclInt.h" #include "tclPort.h" +#include + +typedef int (StatProc)_ANSI_ARGS_((CONST char *path, struct stat *buf)); /* * Prototypes for local procedures defined in this file: */ +static int CheckAccess _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *objPtr, int mode)); +static int GetStatBuf _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *objPtr, StatProc *statProc, + struct stat *statPtr)); static char * GetTypeFromMode _ANSI_ARGS_((int mode)); +static int SplitPath _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *objPtr, int *argcPtr, char ***argvPtr)); static int StoreStatData _ANSI_ARGS_((Tcl_Interp *interp, char *varName, struct stat *statPtr)); +static char ** StringifyObjects _ANSI_ARGS_((int objc, + Tcl_Obj *CONST objv[])); /* *---------------------------------------------------------------------- * - * Tcl_BreakCmd -- + * 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 @@ -46,19 +58,18 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_BreakCmd(dummy, interp, argc, argv) +Tcl_BreakObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { - if (argc != 1) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], "\"", (char *) NULL); + if (objc != 1) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } return TCL_BREAK; } @@ -88,28 +99,24 @@ Tcl_Obj *CONST objv[]; /* Argument objects. */ { register int i; int body, result; char *string, *arg; - int argLen, caseObjc; + int caseObjc; Tcl_Obj *CONST *caseObjv; Tcl_Obj *armPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "string ?in? patList body ... ?default body?"); return TCL_ERROR; } - /* - * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE. - */ - - string = Tcl_GetStringFromObj(objv[1], &argLen); + string = Tcl_GetString(objv[1]); body = -1; - arg = Tcl_GetStringFromObj(objv[2], &argLen); + arg = Tcl_GetString(objv[2]); if (strcmp(arg, "in") == 0) { i = 3; } else { i = 2; } @@ -117,11 +124,10 @@ caseObjv = objv + i; /* * If all of the pattern/command pairs are lumped into a single * argument, split them out again. - * THIS FAILS IF THE ARG'S STRING REP CONTAINS A NULL */ if (caseObjc == 1) { Tcl_Obj **newObjv; @@ -131,13 +137,13 @@ for (i = 0; i < caseObjc; i += 2) { int patObjc, j; char **patObjv; char *pat; - register char *p; + unsigned char *p; - if (i == (caseObjc-1)) { + if (i == (caseObjc - 1)) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "extra case pattern with no body", -1); return TCL_ERROR; } @@ -145,22 +151,22 @@ /* * Check for special case of single pattern (no list) with * no backslash sequences. */ - pat = Tcl_GetStringFromObj(caseObjv[i], &argLen); - for (p = pat; *p != 0; p++) { /* FAILS IF NULL BYTE */ - if (isspace(UCHAR(*p)) || (*p == '\\')) { + pat = Tcl_GetString(caseObjv[i]); + for (p = (unsigned char *) pat; *p != '\0'; p++) { + if (isspace(*p) || (*p == '\\')) { /* INTL: ISO space, UCHAR */ break; } } - if (*p == 0) { + if (*p == '\0') { if ((*pat == 'd') && (strcmp(pat, "default") == 0)) { - body = i+1; + body = i + 1; } if (Tcl_StringMatch(string, pat)) { - body = i+1; + body = i + 1; goto match; } continue; } @@ -174,11 +180,11 @@ if (result != TCL_OK) { return result; } for (j = 0; j < patObjc; j++) { if (Tcl_StringMatch(string, patObjv[j])) { - body = i+1; + body = i + 1; break; } } ckfree((char *) patObjv); if (j < patObjc) { @@ -186,17 +192,18 @@ } } match: if (body != -1) { - armPtr = caseObjv[body-1]; - result = Tcl_EvalObj(interp, caseObjv[body]); + armPtr = caseObjv[body - 1]; + result = Tcl_EvalObjEx(interp, caseObjv[body], 0); if (result == TCL_ERROR) { - char msg[100]; + char msg[100 + TCL_INTEGER_SPACE]; - arg = Tcl_GetStringFromObj(armPtr, &argLen); - sprintf(msg, "\n (\"%.*s\" arm line %d)", argLen, arg, + arg = Tcl_GetString(armPtr); + sprintf(msg, + "\n (\"%.50s\" arm line %d)", arg, interp->errorLine); Tcl_AddObjErrorInfo(interp, msg, -1); } return result; } @@ -249,15 +256,15 @@ if (objc == 3) { varNamePtr = objv[2]; } - result = Tcl_EvalObj(interp, objv[1]); + result = Tcl_EvalObjEx(interp, objv[1], 0); if (objc == 3) { if (Tcl_ObjSetVar2(interp, varNamePtr, NULL, - Tcl_GetObjResult(interp), TCL_PARSE_PART1) == NULL) { + Tcl_GetObjResult(interp), 0) == NULL) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "couldn't save command result in variable", -1); return TCL_ERROR; } @@ -299,40 +306,45 @@ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { char *dirName; - int dirLength; - Tcl_DString buffer; + Tcl_DString ds; int result; if (objc > 2) { - Tcl_WrongNumArgs(interp, 1, objv, "dirName"); + Tcl_WrongNumArgs(interp, 1, objv, "?dirName?"); return TCL_ERROR; } if (objc == 2) { - dirName = Tcl_GetStringFromObj(objv[1], &dirLength); + dirName = Tcl_GetString(objv[1]); } else { dirName = "~"; } - dirName = Tcl_TranslateFileName(interp, dirName, &buffer); - if (dirName == NULL) { + if (Tcl_TranslateFileName(interp, dirName, &ds) == NULL) { + return TCL_ERROR; + } + + result = Tcl_Chdir(Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); + + if (result != 0) { + Tcl_AppendResult(interp, "couldn't change working directory to \"", + dirName, "\": ", Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } - result = TclChdir(interp, dirName); - Tcl_DStringFree(&buffer); - return result; + return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ConcatObjCmd -- * * This object-based procedure is invoked to process the "concat" Tcl - * command. See the user documentation for details on what it does/ + * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: @@ -356,11 +368,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_ContinueCmd - + * 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 @@ -376,23 +388,147 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_ContinueCmd(dummy, interp, argc, argv) +Tcl_ContinueObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { - if (argc != 1) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - "\"", (char *) NULL); + 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(dummy, interp, objc, objv) + ClientData dummy; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + int index, length; + Tcl_Encoding encoding; + char *string; + Tcl_DString ds; + Tcl_Obj *resultPtr; + + static char *optionStrings[] = { + "convertfrom", "convertto", "names", "system", + NULL + }; + enum options { + ENC_CONVERTFROM, ENC_CONVERTTO, 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: { + char *name; + Tcl_Obj *data; + if (objc == 3) { + name = NULL; + data = objv[2]; + } else if (objc == 4) { + name = Tcl_GetString(objv[2]); + data = objv[3]; + } else { + Tcl_WrongNumArgs(interp, 2, objv, "?encoding? data"); + return TCL_ERROR; + } + + encoding = Tcl_GetEncoding(interp, name); + if (!encoding) { + return TCL_ERROR; + } + + if ((enum options) index == ENC_CONVERTFROM) { + /* + * Treat the string as binary data. + */ + + string = (char *) Tcl_GetByteArrayFromObj(data, &length); + Tcl_ExternalToUtfDString(encoding, string, length, &ds); + + /* + * Note that we cannot use Tcl_DStringResult here because + * it will truncate the string at the first null byte. + */ + + Tcl_SetStringObj(Tcl_GetObjResult(interp), + Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + } else { + /* + * Store the result as binary data. + */ + + string = Tcl_GetStringFromObj(data, &length); + Tcl_UtfToExternalDString(encoding, string, length, &ds); + resultPtr = Tcl_GetObjResult(interp); + Tcl_SetByteArrayObj(resultPtr, + (unsigned char *) Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + } + + Tcl_FreeEncoding(encoding); + break; + } + 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_SetResult(interp, Tcl_GetEncodingName(NULL), TCL_STATIC); + } else { + return Tcl_SetSystemEncoding(interp, + Tcl_GetStringFromObj(objv[2], NULL)); + } + break; + } + } + return TCL_OK; +} /* *---------------------------------------------------------------------- * * Tcl_ErrorObjCmd -- @@ -416,11 +552,10 @@ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { Interp *iPtr = (Interp *) interp; - register Tcl_Obj *namePtr; char *info; int infoLen; if ((objc < 2) || (objc > 4)) { Tcl_WrongNumArgs(interp, 1, objv, "message ?errorInfo? ?errorCode?"); @@ -434,15 +569,12 @@ iPtr->flags |= ERR_ALREADY_LOGGED; } } if (objc == 4) { - namePtr = Tcl_NewStringObj("errorCode", -1); - Tcl_ObjSetVar2(interp, namePtr, (Tcl_Obj *) NULL, objv[3], - TCL_GLOBAL_ONLY); + Tcl_SetVar2Ex(interp, "errorCode", NULL, objv[3], TCL_GLOBAL_ONLY); iPtr->flags |= ERROR_CODE_SET; - Tcl_DecrRefCount(namePtr); /* we're done with name object */ } Tcl_SetObjResult(interp, objv[1]); return TCL_ERROR; } @@ -479,23 +611,25 @@ Tcl_WrongNumArgs(interp, 1, objv, "arg ?arg ...?"); return TCL_ERROR; } if (objc == 2) { - result = Tcl_EvalObj(interp, objv[1]); + result = Tcl_EvalObjEx(interp, objv[1], 0); } else { /* * More than one argument: concatenate them together with spaces * between, then evaluate the result. */ objPtr = Tcl_ConcatObj(objc-1, objv+1); - result = Tcl_EvalObj(interp, objPtr); - Tcl_DecrRefCount(objPtr); /* we're done with the object */ + Tcl_IncrRefCount(objPtr); + result = Tcl_EvalObjEx(interp, objPtr, 0); + Tcl_DecrRefCount(objPtr); } if (result == TCL_ERROR) { - char msg[60]; + char msg[32 + TCL_INTEGER_SPACE]; + sprintf(msg, "\n (\"eval\" body line %d)", interp->errorLine); Tcl_AddObjErrorInfo(interp, msg, -1); } return result; } @@ -571,11 +705,11 @@ Tcl_ExprObjCmd(dummy, interp, objc, objv) 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 *resultPtr; register char *bytes; int length, i, result; @@ -593,11 +727,10 @@ return result; } /* * Create a new object holding the concatenated argument strings. - * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE. */ bytes = Tcl_GetStringFromObj(objv[1], &length); objPtr = Tcl_NewStringObj(bytes, length); Tcl_IncrRefCount(objPtr); @@ -650,205 +783,271 @@ ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - char *fileName, *extension, *errorString; - int statOp = 0; /* Init. to avoid compiler warning. */ - int length; - int mode = 0; /* Initialized only to prevent - * compiler warning message. */ - struct stat statBuf; - Tcl_DString buffer; Tcl_Obj *resultPtr; - int index, result; + int index; /* * This list of constants should match the fileOption string array below. */ -enum {FILE_ATIME, FILE_ATTRIBUTES, FILE_COPY, FILE_DELETE, FILE_DIRNAME, - FILE_EXECUTABLE, FILE_EXISTS, FILE_EXTENSION, FILE_ISDIRECTORY, - FILE_ISFILE, FILE_JOIN, FILE_LSTAT, FILE_MTIME, FILE_MKDIR, - FILE_NATIVENAME, FILE_OWNED, FILE_PATHTYPE, FILE_READABLE, - FILE_READLINK, FILE_RENAME, FILE_ROOTNAME, FILE_SIZE, FILE_SPLIT, - FILE_STAT, FILE_TAIL, FILE_TYPE, FILE_VOLUMES, FILE_WRITABLE}; - - - static char *fileOptions[] = {"atime", "attributes", "copy", "delete", - "dirname", "executable", "exists", "extension", "isdirectory", - "isfile", "join", "lstat", "mtime", "mkdir", "nativename", - "owned", "pathtype", "readable", "readlink", "rename", - "rootname", "size", "split", "stat", "tail", "type", "volumes", - "writable", (char *) NULL}; + static char *fileOptions[] = { + "atime", "attributes", "copy", "delete", + "dirname", "executable", "exists", "extension", + "isdirectory", "isfile", "join", "lstat", + "mtime", "mkdir", "nativename", "owned", + "pathtype", "readable", "readlink", "rename", + "rootname", "size", "split", "stat", + "tail", "type", "volumes", "writable", + (char *) NULL + }; + enum options { + FILE_ATIME, FILE_ATTRIBUTES, FILE_COPY, FILE_DELETE, + FILE_DIRNAME, FILE_EXECUTABLE, FILE_EXISTS, FILE_EXTENSION, + FILE_ISDIRECTORY, FILE_ISFILE, FILE_JOIN, FILE_LSTAT, + FILE_MTIME, FILE_MKDIR, FILE_NATIVENAME, FILE_OWNED, + FILE_PATHTYPE, FILE_READABLE, FILE_READLINK, FILE_RENAME, + FILE_ROOTNAME, FILE_SIZE, FILE_SPLIT, FILE_STAT, + FILE_TAIL, FILE_TYPE, FILE_VOLUMES, FILE_WRITABLE + }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } - - if (Tcl_GetIndexFromObj(interp, objv[1], fileOptions, "option", 0, &index) - != TCL_OK) { - return TCL_ERROR; - } - - result = TCL_OK; - /* - * First, do the volumes command, since it is the only one that - * has objc == 2. - */ - - if ( index == FILE_VOLUMES) { - if ( objc != 2 ) { - Tcl_WrongNumArgs(interp, 1, objv, "volumes"); - return TCL_ERROR; - } - result = TclpListVolumes(interp); - return result; - } - - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "name ?arg ...?"); - return TCL_ERROR; - } - - Tcl_DStringInit(&buffer); - resultPtr = Tcl_GetObjResult(interp); - - - /* - * Handle operations on the file name. - */ - - switch (index) { - case FILE_ATTRIBUTES: - result = TclFileAttrsCmd(interp, objc - 2, objv + 2); - goto done; - case FILE_DIRNAME: { - int pargc; - char **pargv; - - if (objc != 3) { - errorString = "dirname name"; - goto not3Args; - } - - fileName = Tcl_GetStringFromObj(objv[2], &length); - - /* - * If there is only one element, and it starts with a tilde, - * perform tilde substitution and resplit the path. - */ - - Tcl_SplitPath(fileName, &pargc, &pargv); - if ((pargc == 1) && (*fileName == '~')) { - ckfree((char*) pargv); - fileName = Tcl_TranslateFileName(interp, fileName, &buffer); - if (fileName == NULL) { - result = TCL_ERROR; - goto done; - } - Tcl_SplitPath(fileName, &pargc, &pargv); - Tcl_DStringSetLength(&buffer, 0); + if (Tcl_GetIndexFromObj(interp, objv[1], fileOptions, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + + resultPtr = Tcl_GetObjResult(interp); + switch ((enum options) index) { + case FILE_ATIME: { + struct stat buf; + + if (objc != 3) { + goto only3Args; + } + if (GetStatBuf(interp, objv[2], TclpStat, &buf) != TCL_OK) { + return TCL_ERROR; + } + Tcl_SetLongObj(resultPtr, (long) buf.st_atime); + return TCL_OK; + } + case FILE_ATTRIBUTES: { + return TclFileAttrsCmd(interp, objc, objv); + } + case FILE_COPY: { + int result; + char **argv; + + argv = StringifyObjects(objc, objv); + result = TclFileCopyCmd(interp, objc, argv); + ckfree((char *) argv); + return result; + } + case FILE_DELETE: { + int result; + char **argv; + + argv = StringifyObjects(objc, objv); + result = TclFileDeleteCmd(interp, objc, argv); + ckfree((char *) argv); + return result; + } + case FILE_DIRNAME: { + int argc; + char **argv; + + if (objc != 3) { + goto only3Args; + } + if (SplitPath(interp, objv[2], &argc, &argv) != TCL_OK) { + return TCL_ERROR; } /* * 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 (pargc > 1) { - Tcl_JoinPath(pargc-1, pargv, &buffer); - Tcl_SetStringObj(resultPtr, Tcl_DStringValue(&buffer), - buffer.length); - } else if ((pargc == 0) - || (Tcl_GetPathType(pargv[0]) == TCL_PATH_RELATIVE)) { - Tcl_SetStringObj(resultPtr, (tclPlatform == TCL_PLATFORM_MAC) - ? ":" : ".", 1); - } else { - Tcl_SetStringObj(resultPtr, pargv[0], -1); } - ckfree((char *)pargv); - goto done; - } - case FILE_TAIL: { - int pargc; - char **pargv; - - if (objc != 3) { - errorString = "tail name"; - goto not3Args; - } - - fileName = Tcl_GetStringFromObj(objv[2], &length); - - /* - * If there is only one element, and it starts with a tilde, - * perform tilde substitution and resplit the path. - */ - - Tcl_SplitPath(fileName, &pargc, &pargv); - if ((pargc == 1) && (*fileName == '~')) { - ckfree((char*) pargv); - fileName = Tcl_TranslateFileName(interp, fileName, &buffer); - if (fileName == NULL) { - result = TCL_ERROR; - goto done; - } - Tcl_SplitPath(fileName, &pargc, &pargv); - Tcl_DStringSetLength(&buffer, 0); - } - - /* - * Return the last component, unless it is the only component, - * and it is the root of an absolute path. - */ - - if (pargc > 0) { - if ((pargc > 1) - || (Tcl_GetPathType(pargv[0]) == TCL_PATH_RELATIVE)) { - Tcl_SetStringObj(resultPtr, pargv[pargc - 1], -1); - } - } - ckfree((char *)pargv); - goto done; - } - case FILE_ROOTNAME: { - char *fileName; - - if (objc != 3) { - errorString = "rootname name"; - goto not3Args; - } - - fileName = Tcl_GetStringFromObj(objv[2], &length); - extension = TclGetExtension(fileName); - if (extension == NULL) { - Tcl_SetObjResult(interp, objv[2]); - } else { - Tcl_SetStringObj(resultPtr, fileName, - (int) (length - strlen(extension))); - } - goto done; - } - case FILE_EXTENSION: - if (objc != 3) { - errorString = "extension name"; - goto not3Args; - } - extension = TclGetExtension(Tcl_GetStringFromObj(objv[2],&length)); - - if (extension != NULL) { - Tcl_SetStringObj(resultPtr, extension, (int)strlen(extension)); - } - goto done; - case FILE_PATHTYPE: - if (objc != 3) { - errorString = "pathtype name"; - goto not3Args; - } - switch (Tcl_GetPathType(Tcl_GetStringFromObj(objv[2], &length))) { + if (argc > 1) { + Tcl_DString ds; + + Tcl_DStringInit(&ds); + Tcl_JoinPath(argc - 1, argv, &ds); + Tcl_SetStringObj(resultPtr, Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + } else if ((argc == 0) + || (Tcl_GetPathType(argv[0]) == TCL_PATH_RELATIVE)) { + Tcl_SetStringObj(resultPtr, + ((tclPlatform == TCL_PLATFORM_MAC) ? ":" : "."), 1); + } else { + Tcl_SetStringObj(resultPtr, argv[0], -1); + } + ckfree((char *) argv); + return TCL_OK; + } + case FILE_EXECUTABLE: { + if (objc != 3) { + goto only3Args; + } + return CheckAccess(interp, objv[2], X_OK); + } + case FILE_EXISTS: { + if (objc != 3) { + goto only3Args; + } + return CheckAccess(interp, objv[2], F_OK); + } + case FILE_EXTENSION: { + char *fileName, *extension; + if (objc != 3) { + goto only3Args; + } + fileName = Tcl_GetString(objv[2]); + extension = TclGetExtension(fileName); + if (extension != NULL) { + Tcl_SetStringObj(resultPtr, extension, -1); + } + return TCL_OK; + } + case FILE_ISDIRECTORY: { + int value; + struct stat buf; + + if (objc != 3) { + goto only3Args; + } + value = 0; + if (GetStatBuf(NULL, objv[2], TclpStat, &buf) == TCL_OK) { + value = S_ISDIR(buf.st_mode); + } + Tcl_SetBooleanObj(resultPtr, value); + return TCL_OK; + } + case FILE_ISFILE: { + int value; + struct stat buf; + + if (objc != 3) { + goto only3Args; + } + value = 0; + if (GetStatBuf(NULL, objv[2], TclpStat, &buf) == TCL_OK) { + value = S_ISREG(buf.st_mode); + } + Tcl_SetBooleanObj(resultPtr, value); + return TCL_OK; + } + case FILE_JOIN: { + char **argv; + Tcl_DString ds; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "name ?name ...?"); + return TCL_ERROR; + } + argv = StringifyObjects(objc - 2, objv + 2); + Tcl_DStringInit(&ds); + Tcl_JoinPath(objc - 2, argv, &ds); + Tcl_SetStringObj(resultPtr, Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + ckfree((char *) argv); + return TCL_OK; + } + case FILE_LSTAT: { + char *varName; + struct stat buf; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "name varName"); + return TCL_ERROR; + } + if (GetStatBuf(interp, objv[2], TclpLstat, &buf) != TCL_OK) { + return TCL_ERROR; + } + varName = Tcl_GetString(objv[3]); + return StoreStatData(interp, varName, &buf); + } + case FILE_MTIME: { + struct stat buf; + + if (objc != 3) { + goto only3Args; + } + if (GetStatBuf(interp, objv[2], TclpStat, &buf) != TCL_OK) { + return TCL_ERROR; + } + Tcl_SetLongObj(resultPtr, (long) buf.st_mtime); + return TCL_OK; + } + case FILE_MKDIR: { + char **argv; + int result; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "name ?name ...?"); + return TCL_ERROR; + } + argv = StringifyObjects(objc, objv); + result = TclFileMakeDirsCmd(interp, objc, argv); + ckfree((char *) argv); + return result; + } + case FILE_NATIVENAME: { + char *fileName; + Tcl_DString ds; + + if (objc != 3) { + goto only3Args; + } + fileName = Tcl_GetString(objv[2]); + fileName = Tcl_TranslateFileName(interp, fileName, &ds); + if (fileName == NULL) { + return TCL_ERROR; + } + Tcl_SetStringObj(resultPtr, fileName, Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + return TCL_OK; + } + case FILE_OWNED: { + int value; + struct stat buf; + + if (objc != 3) { + goto only3Args; + } + value = 0; + if (GetStatBuf(NULL, objv[2], TclpStat, &buf) == TCL_OK) { + /* + * For Windows and Macintosh, there are no user ids + * associated with a file, so we always return 1. + */ + +#if (defined(__WIN32__) || defined(MAC_TCL)) + value = 1; +#else + value = (geteuid() == buf.st_uid); +#endif + } + Tcl_SetBooleanObj(resultPtr, value); + return TCL_OK; + } + case FILE_PATHTYPE: { + char *fileName; + + if (objc != 3) { + goto only3Args; + } + fileName = Tcl_GetString(objv[2]); + switch (Tcl_GetPathType(fileName)) { case TCL_PATH_ABSOLUTE: Tcl_SetStringObj(resultPtr, "absolute", -1); break; case TCL_PATH_RELATIVE: Tcl_SetStringObj(resultPtr, "relative", -1); @@ -855,228 +1054,30 @@ break; case TCL_PATH_VOLUME_RELATIVE: Tcl_SetStringObj(resultPtr, "volumerelative", -1); break; } - goto done; - case FILE_SPLIT: { - int pargc, i; - char **pargvList; - Tcl_Obj *listObjPtr; - - if (objc != 3) { - errorString = "split name"; - goto not3Args; - } - - Tcl_SplitPath(Tcl_GetStringFromObj(objv[2], &length), &pargc, - &pargvList); - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - for (i = 0; i < pargc; i++) { - Tcl_ListObjAppendElement(interp, listObjPtr, - Tcl_NewStringObj(pargvList[i], -1)); - } - ckfree((char *) pargvList); - Tcl_SetObjResult(interp, listObjPtr); - goto done; - } - case FILE_JOIN: { - char **pargv = (char **) ckalloc((objc - 2) * sizeof(char *)); - int i; - - for (i = 2; i < objc; i++) { - pargv[i - 2] = Tcl_GetStringFromObj(objv[i], &length); - } - Tcl_JoinPath(objc - 2, pargv, &buffer); - Tcl_SetStringObj(resultPtr, Tcl_DStringValue(&buffer), - buffer.length); - ckfree((char *) pargv); - Tcl_DStringFree(&buffer); - goto done; - } - case FILE_RENAME: { - char **pargv = (char **) ckalloc(objc * sizeof(char *)); - int i; - - for (i = 0; i < objc; i++) { - pargv[i] = Tcl_GetStringFromObj(objv[i], &length); - } - result = TclFileRenameCmd(interp, objc, pargv); - ckfree((char *) pargv); - goto done; - } - case FILE_MKDIR: { - char **pargv = (char **) ckalloc(objc * sizeof(char *)); - int i; - - for (i = 0; i < objc; i++) { - pargv[i] = Tcl_GetStringFromObj(objv[i], &length); - } - result = TclFileMakeDirsCmd(interp, objc, pargv); - ckfree((char *) pargv); - goto done; - } - case FILE_DELETE: { - char **pargv = (char **) ckalloc(objc * sizeof(char *)); - int i; - - for (i = 0; i < objc; i++) { - pargv[i] = Tcl_GetStringFromObj(objv[i], &length); - } - result = TclFileDeleteCmd(interp, objc, pargv); - ckfree((char *) pargv); - goto done; - } - case FILE_COPY: { - char **pargv = (char **) ckalloc(objc * sizeof(char *)); - int i; - - for (i = 0; i < objc; i++) { - pargv[i] = Tcl_GetStringFromObj(objv[i], &length); - } - result = TclFileCopyCmd(interp, objc, pargv); - ckfree((char *) pargv); - goto done; - } - case FILE_NATIVENAME: - fileName = Tcl_TranslateFileName(interp, - Tcl_GetStringFromObj(objv[2], &length), &buffer); - if (fileName == NULL) { - result = TCL_ERROR ; - } else { - Tcl_SetStringObj(resultPtr, fileName, -1); - } - goto done; - } - - /* - * Next, handle operations that can be satisfied with the "access" - * kernel call. - */ - - fileName = Tcl_TranslateFileName(interp, - Tcl_GetStringFromObj(objv[2], &length), &buffer); - - switch (index) { - case FILE_READABLE: - if (objc != 3) { - errorString = "readable name"; - goto not3Args; - } - mode = R_OK; -checkAccess: - /* - * The result might have been set within Tcl_TranslateFileName - * (like no such user "blah" for file exists ~blah) - * but we don't want to flag an error in that case. - */ - if (fileName == NULL) { - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); - } else { - Tcl_SetBooleanObj(resultPtr, (access(fileName, mode) != -1)); - } - goto done; - case FILE_WRITABLE: - if (objc != 3) { - errorString = "writable name"; - goto not3Args; - } - mode = W_OK; - goto checkAccess; - case FILE_EXECUTABLE: - if (objc != 3) { - errorString = "executable name"; - goto not3Args; - } - mode = X_OK; - goto checkAccess; - case FILE_EXISTS: - if (objc != 3) { - errorString = "exists name"; - goto not3Args; - } - mode = F_OK; - goto checkAccess; - } - - - /* - * Lastly, check stuff that requires the file to be stat-ed. - */ - - if (fileName == NULL) { - result = TCL_ERROR; - goto done; - } - - switch (index) { - case FILE_ATIME: - if (objc != 3) { - errorString = "atime name"; - goto not3Args; - } - - if (stat(fileName, &statBuf) == -1) { - goto badStat; - } - Tcl_SetLongObj(resultPtr, (long) statBuf.st_atime); - goto done; - case FILE_ISDIRECTORY: - if (objc != 3) { - errorString = "isdirectory name"; - goto not3Args; - } - statOp = 2; - break; - case FILE_ISFILE: - if (objc != 3) { - errorString = "isfile name"; - goto not3Args; - } - statOp = 1; - break; - case FILE_LSTAT: - if (objc != 4) { - Tcl_WrongNumArgs(interp, 1, objv, "lstat name varName"); - result = TCL_ERROR; - goto done; - } - - if (lstat(fileName, &statBuf) == -1) { - Tcl_AppendStringsToObj(resultPtr, "couldn't lstat \"", - Tcl_GetStringFromObj(objv[2], &length), "\": ", - Tcl_PosixError(interp), (char *) NULL); - result = TCL_ERROR; - goto done; - } - result = StoreStatData(interp, Tcl_GetStringFromObj(objv[3], - &length), &statBuf); - goto done; - case FILE_MTIME: - if (objc != 3) { - errorString = "mtime name"; - goto not3Args; - } - if (stat(fileName, &statBuf) == -1) { - goto badStat; - } - Tcl_SetLongObj(resultPtr, (long) statBuf.st_mtime); - goto done; - case FILE_OWNED: - if (objc != 3) { - errorString = "owned name"; - goto not3Args; - } - statOp = 0; - break; - case FILE_READLINK: { - char linkValue[MAXPATHLEN + 1]; - int linkLength; - - if (objc != 3) { - errorString = "readlink name"; - goto not3Args; + return TCL_OK; + } + case FILE_READABLE: { + if (objc != 3) { + goto only3Args; + } + return CheckAccess(interp, objv[2], R_OK); + } + case FILE_READLINK: { + char *fileName, *contents; + Tcl_DString name, link; + + if (objc != 3) { + goto only3Args; + } + + fileName = Tcl_GetString(objv[2]); + fileName = Tcl_TranslateFileName(interp, fileName, &name); + if (fileName == NULL) { + return TCL_ERROR; } /* * If S_IFLNK isn't defined it means that the machine doesn't * support symbolic links, so the file can't possibly be a @@ -1084,101 +1085,305 @@ * happens on machines that do support symbolic links when * you invoke readlink on a file that isn't a symbolic link. */ #ifndef S_IFLNK - linkLength = -1; + contents = NULL; errno = EINVAL; #else - linkLength = readlink(fileName, linkValue, sizeof(linkValue) - 1); + contents = TclpReadlink(fileName, &link); #endif /* S_IFLNK */ - if (linkLength == -1) { - Tcl_AppendStringsToObj(resultPtr, "couldn't readlink \"", - Tcl_GetStringFromObj(objv[2], &length), "\": ", + + Tcl_DStringFree(&name); + if (contents == NULL) { + Tcl_AppendResult(interp, "could not readlink \"", + Tcl_GetString(objv[2]), "\": ", Tcl_PosixError(interp), (char *) NULL); - result = TCL_ERROR; - goto done; - } - linkValue[linkLength] = 0; - Tcl_SetStringObj(resultPtr, linkValue, linkLength); - goto done; - } - case FILE_SIZE: + return TCL_ERROR; + } + Tcl_DStringResult(interp, &link); + return TCL_OK; + } + case FILE_RENAME: { + int result; + char **argv; + + argv = StringifyObjects(objc, objv); + result = TclFileRenameCmd(interp, objc, argv); + ckfree((char *) argv); + return result; + } + case FILE_ROOTNAME: { + int length; + char *fileName, *extension; + + if (objc != 3) { + goto only3Args; + } + fileName = Tcl_GetStringFromObj(objv[2], &length); + extension = TclGetExtension(fileName); + if (extension == NULL) { + Tcl_SetObjResult(interp, objv[2]); + } else { + Tcl_SetStringObj(resultPtr, fileName, + (int) (length - strlen(extension))); + } + return TCL_OK; + } + case FILE_SIZE: { + struct stat buf; + + if (objc != 3) { + goto only3Args; + } + if (GetStatBuf(interp, objv[2], TclpStat, &buf) != TCL_OK) { + return TCL_ERROR; + } + Tcl_SetLongObj(resultPtr, (long) buf.st_size); + return TCL_OK; + } + case FILE_SPLIT: { + int i, argc; + char **argv; + char *fileName; + Tcl_Obj *objPtr; + if (objc != 3) { - errorString = "size name"; - goto not3Args; - } - if (stat(fileName, &statBuf) == -1) { - goto badStat; - } - Tcl_SetLongObj(resultPtr, (long) statBuf.st_size); - goto done; - case FILE_STAT: + goto only3Args; + } + fileName = Tcl_GetString(objv[2]); + Tcl_SplitPath(fileName, &argc, &argv); + for (i = 0; i < argc; i++) { + objPtr = Tcl_NewStringObj(argv[i], -1); + Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); + } + ckfree((char *) argv); + return TCL_OK; + } + case FILE_STAT: { + char *varName; + struct stat buf; + if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "stat name varName"); - result = TCL_ERROR; - goto done; - } - - if (stat(fileName, &statBuf) == -1) { -badStat: - Tcl_AppendStringsToObj(resultPtr, "couldn't stat \"", - Tcl_GetStringFromObj(objv[2], &length), - "\": ", Tcl_PosixError(interp), (char *) NULL); - result = TCL_ERROR; - goto done; - } - result = StoreStatData(interp, Tcl_GetStringFromObj(objv[3], - &length), &statBuf); - goto done; - case FILE_TYPE: + return TCL_ERROR; + } + if (GetStatBuf(interp, objv[2], TclpStat, &buf) != TCL_OK) { + return TCL_ERROR; + } + varName = Tcl_GetString(objv[3]); + return StoreStatData(interp, varName, &buf); + } + case FILE_TAIL: { + int argc; + char **argv; + if (objc != 3) { - errorString = "type name"; - goto not3Args; - } - if (lstat(fileName, &statBuf) == -1) { - goto badStat; - } - errorString = GetTypeFromMode((int) statBuf.st_mode); - Tcl_SetStringObj(resultPtr, errorString, -1); - goto done; - } - - if (stat(fileName, &statBuf) == -1) { - Tcl_SetBooleanObj(resultPtr, 0); - goto done; - } - switch (statOp) { - case 0: + goto only3Args; + } + if (SplitPath(interp, objv[2], &argc, &argv) != TCL_OK) { + return TCL_ERROR; + } + /* - * For Windows and Macintosh, there are no user ids - * associated with a file, so we always return 1. + * Return the last component, unless it is the only component, + * and it is the root of an absolute path. */ -#if (defined(__WIN32__) || defined(MAC_TCL)) - mode = 1; -#else - mode = (geteuid() == statBuf.st_uid); -#endif - break; - case 1: - mode = S_ISREG(statBuf.st_mode); - break; - case 2: - mode = S_ISDIR(statBuf.st_mode); - break; - } - Tcl_SetBooleanObj(resultPtr, mode); - -done: - Tcl_DStringFree(&buffer); - return result; - -not3Args: - Tcl_WrongNumArgs(interp, 1, objv, errorString); - result = TCL_ERROR; - goto done; + if (argc > 0) { + if ((argc > 1) + || (Tcl_GetPathType(argv[0]) == TCL_PATH_RELATIVE)) { + Tcl_SetStringObj(resultPtr, argv[argc - 1], -1); + } + } + ckfree((char *) argv); + return TCL_OK; + } + case FILE_TYPE: { + struct stat buf; + + if (objc != 3) { + goto only3Args; + } + if (GetStatBuf(interp, objv[2], TclpLstat, &buf) != TCL_OK) { + return TCL_ERROR; + } + Tcl_SetStringObj(resultPtr, + GetTypeFromMode((unsigned short) buf.st_mode), -1); + return TCL_OK; + } + case FILE_VOLUMES: { + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; + } + return TclpListVolumes(interp); + } + case FILE_WRITABLE: { + if (objc != 3) { + goto only3Args; + } + return CheckAccess(interp, objv[2], W_OK); + } + } + + only3Args: + Tcl_WrongNumArgs(interp, 2, objv, "name"); + return TCL_ERROR; +} + +/* + *--------------------------------------------------------------------------- + * + * SplitPath -- + * + * Utility procedure used by Tcl_FileObjCmd() to split a path. + * Differs from standard Tcl_SplitPath in its handling of home + * directories; Tcl_SplitPath preserves the "~" while this + * procedure computes the actual full path name. + * + * Results: + * The return value is TCL_OK if the path could be split, TCL_ERROR + * otherwise. If TCL_ERROR was returned, an error message is left + * in interp. If TCL_OK was returned, *argvPtr is set to a newly + * allocated array of strings that represent the individual + * directories in the specified path, and *argcPtr is filled with + * the length of that array. + * + * Side effects: + * Memory allocated. The caller must eventually free this memory + * by calling ckfree() on *argvPtr. + * + *--------------------------------------------------------------------------- + */ + +static int +SplitPath(interp, objPtr, argcPtr, argvPtr) + Tcl_Interp *interp; /* Interp for error return. May be NULL. */ + Tcl_Obj *objPtr; /* Path to be split. */ + int *argcPtr; /* Filled with length of following array. */ + char ***argvPtr; /* Filled with array of strings representing + * the elements of the specified path. */ +{ + char *fileName; + + fileName = Tcl_GetString(objPtr); + + /* + * If there is only one element, and it starts with a tilde, + * perform tilde substitution and resplit the path. + */ + + Tcl_SplitPath(fileName, argcPtr, argvPtr); + if ((*argcPtr == 1) && (fileName[0] == '~')) { + Tcl_DString ds; + + ckfree((char *) *argvPtr); + fileName = Tcl_TranslateFileName(interp, fileName, &ds); + if (fileName == NULL) { + return TCL_ERROR; + } + Tcl_SplitPath(fileName, argcPtr, argvPtr); + Tcl_DStringFree(&ds); + } + 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(interp, objPtr, mode) + Tcl_Interp *interp; /* Interp for status return. Must not be + * NULL. */ + Tcl_Obj *objPtr; /* Name of file to check. */ + int mode; /* Attribute to check; passed as argument to + * access(). */ +{ + int value; + char *fileName; + Tcl_DString ds; + + fileName = Tcl_GetString(objPtr); + fileName = Tcl_TranslateFileName(interp, fileName, &ds); + if (fileName == NULL) { + value = 0; + } else { + value = (TclAccess(fileName, mode) == 0); + Tcl_DStringFree(&ds); + } + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), 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(interp, objPtr, statProc, statPtr) + Tcl_Interp *interp; /* Interp for error return. May be NULL. */ + Tcl_Obj *objPtr; /* Path name to examine. */ + StatProc *statProc; /* Either stat() or lstat() depending on + * desired behavior. */ + struct stat *statPtr; /* Filled with info about file obtained by + * calling (*statProc)(). */ +{ + char *fileName; + Tcl_DString ds; + int status; + + fileName = Tcl_GetString(objPtr); + fileName = Tcl_TranslateFileName(interp, fileName, &ds); + if (fileName == NULL) { + return TCL_ERROR; + } + + status = (*statProc)(Tcl_DStringValue(&ds), statPtr); + Tcl_DStringFree(&ds); + + if (status < 0) { + if (interp != NULL) { + Tcl_AppendResult(interp, "could not read \"", + Tcl_GetString(objPtr), "\": ", + Tcl_PosixError(interp), (char *) NULL); + } + return TCL_ERROR; + } + return TCL_OK; } /* *---------------------------------------------------------------------- * @@ -1188,11 +1393,11 @@ * "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->result. + * a message is left in interp's result. * * Side effects: * Elements of the associative array given by "varName" are modified. * *---------------------------------------------------------------------- @@ -1204,65 +1409,65 @@ char *varName; /* Name of associative array variable * in which to store stat results. */ struct stat *statPtr; /* Pointer to buffer containing * stat data to store in varName. */ { - char string[30]; + char string[TCL_INTEGER_SPACE]; - sprintf(string, "%ld", (long) statPtr->st_dev); + TclFormatInt(string, (long) statPtr->st_dev); if (Tcl_SetVar2(interp, varName, "dev", string, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } - sprintf(string, "%ld", (long) statPtr->st_ino); + TclFormatInt(string, (long) statPtr->st_ino); if (Tcl_SetVar2(interp, varName, "ino", string, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } - sprintf(string, "%ld", (long) statPtr->st_mode); + TclFormatInt(string, (unsigned short) statPtr->st_mode); if (Tcl_SetVar2(interp, varName, "mode", string, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } - sprintf(string, "%ld", (long) statPtr->st_nlink); + TclFormatInt(string, (long) statPtr->st_nlink); if (Tcl_SetVar2(interp, varName, "nlink", string, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } - sprintf(string, "%ld", (long) statPtr->st_uid); + TclFormatInt(string, (long) statPtr->st_uid); if (Tcl_SetVar2(interp, varName, "uid", string, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } - sprintf(string, "%ld", (long) statPtr->st_gid); + TclFormatInt(string, (long) statPtr->st_gid); if (Tcl_SetVar2(interp, varName, "gid", string, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } sprintf(string, "%lu", (unsigned long) statPtr->st_size); if (Tcl_SetVar2(interp, varName, "size", string, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } - sprintf(string, "%ld", (long) statPtr->st_atime); + TclFormatInt(string, (long) statPtr->st_atime); if (Tcl_SetVar2(interp, varName, "atime", string, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } - sprintf(string, "%ld", (long) statPtr->st_mtime); + TclFormatInt(string, (long) statPtr->st_mtime); if (Tcl_SetVar2(interp, varName, "mtime", string, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } - sprintf(string, "%ld", (long) statPtr->st_ctime); + TclFormatInt(string, (long) statPtr->st_ctime); if (Tcl_SetVar2(interp, varName, "ctime", string, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } if (Tcl_SetVar2(interp, varName, "type", - GetTypeFromMode((int) statPtr->st_mode), TCL_LEAVE_ERR_MSG) - == NULL) { + GetTypeFromMode((unsigned short) statPtr->st_mode), + TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } return TCL_OK; } @@ -1310,11 +1515,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_ForCmd -- + * Tcl_FoObjCmd -- * * 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 @@ -1331,49 +1536,49 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_ForCmd(dummy, interp, argc, argv) +Tcl_ForObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { int result, value; - if (argc != 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " start test next command\"", (char *) NULL); + if (objc != 5) { + Tcl_WrongNumArgs(interp, 1, objv, "start test next command"); return TCL_ERROR; } - result = Tcl_Eval(interp, argv[1]); + result = Tcl_EvalObjEx(interp, objv[1], 0); if (result != TCL_OK) { if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (\"for\" initial command)"); } return result; } while (1) { - result = Tcl_ExprBoolean(interp, argv[2], &value); + result = Tcl_ExprBooleanObj(interp, objv[2], &value); if (result != TCL_OK) { return result; } if (!value) { break; } - result = Tcl_Eval(interp, argv[4]); + result = Tcl_EvalObjEx(interp, objv[4], 0); if ((result != TCL_OK) && (result != TCL_CONTINUE)) { if (result == TCL_ERROR) { - char msg[60]; + char msg[32 + TCL_INTEGER_SPACE]; + sprintf(msg, "\n (\"for\" body line %d)",interp->errorLine); Tcl_AddErrorInfo(interp, msg); } break; } - result = Tcl_Eval(interp, argv[3]); + result = Tcl_EvalObjEx(interp, objv[3], 0); if (result == TCL_BREAK) { break; } else if (result != TCL_OK) { if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (\"for\" loop-end command)"); @@ -1488,11 +1693,10 @@ argvList[i] = (Tcl_Obj **) NULL; } /* * Break up the value lists and variable lists into elements - * THIS FAILS IF THE OBJECT'S STRING REP HAS A NULL BYTE. */ maxj = 0; for (i = 0; i < numLists; i++) { result = Tcl_ListObjGetElements(interp, argObjv[1+i*2], @@ -1560,37 +1764,37 @@ valuePtr = argvList[i][k]; } else { valuePtr = Tcl_NewObj(); /* empty string */ isEmptyObj = 1; } - varValuePtr = Tcl_ObjSetVar2(interp, varvList[i][v], NULL, - valuePtr, TCL_PARSE_PART1); + varValuePtr = Tcl_ObjSetVar2(interp, varvList[i][v], + NULL, valuePtr, 0); if (varValuePtr == NULL) { if (isEmptyObj) { Tcl_DecrRefCount(valuePtr); } Tcl_ResetResult(interp); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "couldn't set loop variable: \"", - Tcl_GetStringFromObj(varvList[i][v], (int *) NULL), - "\"", (char *) NULL); + Tcl_GetString(varvList[i][v]), "\"", (char *) NULL); result = TCL_ERROR; goto done; } } } - result = Tcl_EvalObj(interp, bodyPtr); + result = Tcl_EvalObjEx(interp, bodyPtr, 0); if (result != TCL_OK) { if (result == TCL_CONTINUE) { result = TCL_OK; } else if (result == TCL_BREAK) { result = TCL_OK; break; } else if (result == TCL_ERROR) { - char msg[100]; + char msg[32 + TCL_INTEGER_SPACE]; + sprintf(msg, "\n (\"foreach\" body line %d)", interp->errorLine); Tcl_AddObjErrorInfo(interp, msg, -1); break; } else { @@ -1641,14 +1845,14 @@ ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - register char *format; /* Used to read characters from the format + char *format; /* Used to read characters from the format * string. */ int formatLen; /* The length of the format string */ - char *endPtr; /* Points to the last char in format array */ + char *endPtr; /* Points to the last char in format array */ char newFormat[40]; /* A new format specifier is generated here. */ int width; /* Field width from field specifier, or 0 if * no width given. */ int precision; /* Field precision from field specifier, or 0 * if no precision given. */ @@ -1664,12 +1868,14 @@ int whichValue; /* Indicates which of intValue, ptrValue, * or doubleValue has the value to pass to * sprintf, according to the following * definitions: */ # define INT_VALUE 0 -# define PTR_VALUE 1 -# define DOUBLE_VALUE 2 +# define CHAR_VALUE 1 +# define PTR_VALUE 2 +# define DOUBLE_VALUE 3 +# define STRING_VALUE 4 # define MAX_FLOAT_SIZE 320 Tcl_Obj *resultPtr; /* Where result is stored finally. */ char staticBuf[MAX_FLOAT_SIZE + 1]; /* A static buffer to copy the format results @@ -1686,39 +1892,45 @@ int gotSequential = 0; /* Non-zero means that a regular sequential * (non-XPG3) conversion specifier has been * seen. */ int useShort; /* Value to be printed is short (half word). */ char *end; /* Used to locate end of numerical fields. */ + int stringLen = 0; /* Length of string in characters rather + * than bytes. Used for %s substitution. */ + int gotMinus; /* Non-zero indicates that a minus flag has + * been seen in the current field. */ + int gotPrecision; /* Non-zero indicates that a precision has + * been set for the current field. */ /* * This procedure is a bit nasty. The goal is to use sprintf to * do most of the dirty work. There are several problems: * 1. this procedure can't trust its arguments. * 2. we must be able to provide a large enough result area to hold * whatever's generated. This is hard to estimate. - * 2. there's no way to move the arguments from objv to the call + * 3. there's no way to move the arguments from objv to the call * to sprintf in a reasonable way. This is particularly nasty * because some of the arguments may be two-word values (doubles). * So, what happens here is to scan the format string one % group * at a time, making many individual calls to sprintf. */ if (objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, - "formatString ?arg arg ...?"); + Tcl_WrongNumArgs(interp, 1, objv, "formatString ?arg arg ...?"); return TCL_ERROR; } - format = Tcl_GetStringFromObj(objv[1], &formatLen); + format = (char *) Tcl_GetStringFromObj(objv[1], &formatLen); endPtr = format + formatLen; resultPtr = Tcl_NewObj(); objIndex = 2; while (format < endPtr) { register char *newPtr = newFormat; width = precision = noPercent = useShort = 0; + gotMinus = gotPrecision = 0; whichValue = PTR_VALUE; /* * Get rid of any characters before the next field specifier. */ @@ -1746,20 +1958,20 @@ * "*" size specifiers. */ *newPtr = '%'; newPtr++; format++; - if (isdigit(UCHAR(*format))) { + if (isdigit(UCHAR(*format))) { /* INTL: Tcl source. */ int tmp; /* * 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. */ - tmp = strtoul(format, &end, 10); + tmp = strtoul(format, &end, 10); /* INTL: "C" locale. */ if (*end != '$') { goto notXpg; } format = end+1; gotXpg = 1; @@ -1780,24 +1992,33 @@ } xpgCheckDone: while ((*format == '-') || (*format == '#') || (*format == '0') || (*format == ' ') || (*format == '+')) { + if (*format == '-') { + gotMinus = 1; + } *newPtr = *format; newPtr++; format++; } - if (isdigit(UCHAR(*format))) { - width = strtoul(format, &end, 10); + if (isdigit(UCHAR(*format))) { /* INTL: Tcl source. */ + width = strtoul(format, &end, 10); /* INTL: Tcl source. */ format = end; } else if (*format == '*') { if (objIndex >= objc) { goto badIndex; } - if (Tcl_GetIntFromObj(interp, objv[objIndex], - &width) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, /* INTL: Tcl source. */ + objv[objIndex], &width) != TCL_OK) { goto fmtError; + } + if (width < 0) { + width = -width; + *newPtr = '-'; + gotMinus = 1; + newPtr++; } objIndex++; format++; } if (width > 100000) { @@ -1810,36 +2031,37 @@ width = 100000; } else if (width < 0) { width = 0; } if (width != 0) { - TclFormatInt(newPtr, width); + TclFormatInt(newPtr, width); /* INTL: printf format. */ while (*newPtr != 0) { newPtr++; } } if (*format == '.') { *newPtr = '.'; newPtr++; format++; + gotPrecision = 1; } - if (isdigit(UCHAR(*format))) { - precision = strtoul(format, &end, 10); + if (isdigit(UCHAR(*format))) { /* INTL: Tcl source. */ + precision = strtoul(format, &end, 10); /* INTL: "C" locale. */ format = end; } else if (*format == '*') { if (objIndex >= objc) { goto badIndex; } - if (Tcl_GetIntFromObj(interp, objv[objIndex], - &precision) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, /* INTL: Tcl source. */ + objv[objIndex], &precision) != TCL_OK) { goto fmtError; } objIndex++; format++; } - if (precision != 0) { - TclFormatInt(newPtr, precision); + if (gotPrecision) { + TclFormatInt(newPtr, precision); /* INTL: printf format. */ while (*newPtr != 0) { newPtr++; } } if (*format == 'l') { @@ -1862,35 +2084,51 @@ case 'd': case 'o': case 'u': case 'x': case 'X': - if (Tcl_GetIntFromObj(interp, objv[objIndex], - (int *) &intValue) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, /* INTL: Tcl source. */ + objv[objIndex], &intValue) != TCL_OK) { goto fmtError; } whichValue = INT_VALUE; size = 40 + precision; break; case 's': + /* + * Compute the length of the string in characters and add + * any additional space required by the field width. All of + * the extra characters will be spaces, so one byte per + * character is adequate. + */ + + whichValue = STRING_VALUE; ptrValue = Tcl_GetStringFromObj(objv[objIndex], &size); + stringLen = Tcl_NumUtfChars(ptrValue, size); + if (gotPrecision && (precision < stringLen)) { + stringLen = precision; + } + size = Tcl_UtfAtIndex(ptrValue, stringLen) - ptrValue; + if (width > stringLen) { + size += (width - stringLen); + } break; case 'c': - if (Tcl_GetIntFromObj(interp, objv[objIndex], - (int *) &intValue) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, /* INTL: Tcl source. */ + objv[objIndex], &intValue) != TCL_OK) { goto fmtError; } - whichValue = INT_VALUE; - size = 1; + whichValue = CHAR_VALUE; + size = width + TCL_UTF_MAX; break; case 'e': case 'E': case 'f': case 'g': case 'G': - if (Tcl_GetDoubleFromObj(interp, objv[objIndex], - &doubleValue) != TCL_OK) { + if (Tcl_GetDoubleFromObj(interp, /* INTL: Tcl source. */ + objv[objIndex], &doubleValue) != TCL_OK) { goto fmtError; } whichValue = DOUBLE_VALUE; size = MAX_FLOAT_SIZE; if (precision > 10) { @@ -1900,17 +2138,16 @@ case 0: Tcl_SetResult(interp, "format string ended in middle of field specifier", TCL_STATIC); goto fmtError; - default: - { - char buf[40]; - sprintf(buf, "bad field specifier \"%c\"", *format); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - goto fmtError; - } + default: { + char buf[40]; + sprintf(buf, "bad field specifier \"%c\"", *format); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + goto fmtError; + } } objIndex++; format++; /* @@ -1930,21 +2167,72 @@ ckfree(dst); } dst = (char *) ckalloc((unsigned) (size + 1)); dstSize = size; } - - if (whichValue == DOUBLE_VALUE) { - sprintf(dst, newFormat, doubleValue); - } else if (whichValue == INT_VALUE) { - if (useShort) { - sprintf(dst, newFormat, (short) intValue); - } else { - sprintf(dst, newFormat, intValue); - } - } else { - sprintf(dst, newFormat, ptrValue); + switch (whichValue) { + case DOUBLE_VALUE: { + sprintf(dst, newFormat, doubleValue); /* INTL: user locale. */ + break; + } + case INT_VALUE: { + if (useShort) { + sprintf(dst, newFormat, (short) intValue); + } else { + sprintf(dst, newFormat, intValue); + } + break; + } + case CHAR_VALUE: { + char *ptr; + ptr = dst; + if (!gotMinus) { + for ( ; --width > 0; ptr++) { + *ptr = ' '; + } + } + ptr += Tcl_UniCharToUtf(intValue, ptr); + for ( ; --width > 0; ptr++) { + *ptr = ' '; + } + *ptr = '\0'; + break; + } + case STRING_VALUE: { + char *ptr; + int pad; + + ptr = dst; + if (width > stringLen) { + pad = width - stringLen; + } else { + pad = 0; + } + + if (!gotMinus) { + while (pad > 0) { + *ptr++ = ' '; + pad--; + } + } + + size = Tcl_UtfAtIndex(ptrValue, stringLen) - ptrValue; + if (size) { + memcpy(ptr, ptrValue, (size_t) size); + ptr += size; + } + while (pad > 0) { + *ptr++ = ' '; + pad--; + } + *ptr = '\0'; + break; + } + default: { + sprintf(dst, newFormat, ptrValue); + break; + } } Tcl_AppendToObj(resultPtr, dst, -1); } } @@ -1973,5 +2261,45 @@ ckfree(dst); } Tcl_DecrRefCount(resultPtr); return TCL_ERROR; } + +/* + *--------------------------------------------------------------------------- + * + * StringifyObjects -- + * + * Helper function to bridge the gap between an object-based procedure + * and an older string-based procedure. + * + * Given an array of objects, allocate an array that consists of the + * string representations of those objects. + * + * Results: + * The return value is a pointer to the newly allocated array of + * strings. Elements 0 to (objc-1) of the string array point to the + * string representation of the corresponding element in the source + * object array; element objc of the string array is NULL. + * + * Side effects: + * Memory allocated. The caller must eventually free this memory + * by calling ckfree() on the return value. + * + *--------------------------------------------------------------------------- + */ + +static char ** +StringifyObjects(objc, objv) + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + int i; + char **argv; + + argv = (char **) ckalloc((objc + 1) * sizeof(char *)); + for (i = 0; i < objc; i++) { + argv[i] = Tcl_GetString(objv[i]); + } + argv[i] = NULL; + return argv; +} Index: generic/tclCmdIL.c ================================================================== --- generic/tclCmdIL.c +++ generic/tclCmdIL.c @@ -7,28 +7,22 @@ * (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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclCmdIL.c 1.173 97/11/18 13:55:01 + * RCS: @(#) $Id: tclCmdIL.c,v 1.1.2.11 1999/04/02 23:44:54 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" - -/* - * The following variable holds the full path name of the binary - * from which this application was executed, or NULL if it isn't - * know. The value of the variable is set by the procedure - * Tcl_FindExecutable. The storage space is dynamically allocated. - */ - -char *tclExecutableName = NULL; +#include "tclCompile.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. @@ -50,11 +44,11 @@ typedef struct SortInfo { int isIncreasing; /* Nonzero means sort in increasing order. */ int sortMode; /* The sort mode. One of SORTMODE_* * values defined below */ - Tcl_DString compareCmd; /* The Tcl comparison command when sortMode + Tcl_Obj *compareCmdPtr; /* The Tcl comparison command when sortMode * is SORTMODE_COMMAND. Pre-initialized to * hold base of command.*/ int index; /* If the -index option was specified, this * holds the index of the list element * to extract for comparison. If -index @@ -79,10 +73,13 @@ /* * Forward declarations for procedures defined in this file: */ +static void AppendLocals _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *listPtr, char *pattern, + int includeLinks)); static int DictionaryCompare _ANSI_ARGS_((char *left, char *right)); static int InfoArgsCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); @@ -151,11 +148,11 @@ Tcl_Obj *second, SortInfo *infoPtr)); /* *---------------------------------------------------------------------- * - * Tcl_IfCmd -- + * 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 @@ -171,60 +168,75 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_IfCmd(dummy, interp, argc, argv) +Tcl_IfObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { + int thenScriptIndex = 0; /* then script to be evaled after syntax check */ int i, result, value; - + char *clause; i = 1; while (1) { /* - * At this point in the loop, argv and argc refer to an expression + * 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 >= argc) { - Tcl_AppendResult(interp, "wrong # args: no expression after \"", - argv[i-1], "\" argument", (char *) NULL); - return TCL_ERROR; - } - result = Tcl_ExprBoolean(interp, argv[i], &value); - if (result != TCL_OK) { - return result; - } - i++; - if ((i < argc) && (strcmp(argv[i], "then") == 0)) { - i++; - } - if (i >= argc) { - Tcl_AppendResult(interp, "wrong # args: no script following \"", - argv[i-1], "\" argument", (char *) NULL); - return TCL_ERROR; - } - if (value) { - return Tcl_Eval(interp, argv[i]); + if (i >= objc) { + clause = Tcl_GetString(objv[i-1]); + Tcl_AppendResult(interp, "wrong # args: no expression after \"", + clause, "\" argument", (char *) NULL); + return TCL_ERROR; + } + if (!thenScriptIndex) { + result = Tcl_ExprBooleanObj(interp, objv[i], &value); + if (result != TCL_OK) { + return result; + } + } + i++; + if (i >= objc) { + missingScript: + clause = Tcl_GetString(objv[i-1]); + Tcl_AppendResult(interp, "wrong # args: no script following \"", + clause, "\" argument", (char *) NULL); + return TCL_ERROR; + } + clause = Tcl_GetString(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 >= argc) { + if (i >= objc) { + if (thenScriptIndex) { + return Tcl_EvalObjEx(interp, objv[thenScriptIndex], 0); + } return TCL_OK; } - if ((argv[i][0] == 'e') && (strcmp(argv[i], "elseif") == 0)) { + clause = Tcl_GetString(objv[i]); + if ((clause[0] == 'e') && (strcmp(clause, "elseif") == 0)) { i++; continue; } break; } @@ -233,26 +245,35 @@ * 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(argv[i], "else") == 0) { + if (strcmp(clause, "else") == 0) { i++; - if (i >= argc) { + if (i >= objc) { Tcl_AppendResult(interp, "wrong # args: no script following \"else\" argument", (char *) NULL); return TCL_ERROR; } } - return Tcl_Eval(interp, argv[i]); + if (i < objc - 1) { + Tcl_AppendResult(interp, + "wrong # args: extra words after \"else\" clause in \"if\" command", + (char *) NULL); + return TCL_ERROR; + } + if (thenScriptIndex) { + return Tcl_EvalObjEx(interp, objv[thenScriptIndex], 0); + } + return Tcl_EvalObjEx(interp, objv[i], 0); } /* *---------------------------------------------------------------------- * - * Tcl_IncrCmd -- + * 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 @@ -268,58 +289,53 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_IncrCmd(dummy, interp, argc, argv) - ClientData dummy; /* Not used. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ -{ - int value; - char *oldString, *result; - char newString[30]; - - if ((argc != 2) && (argc != 3)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " varName ?increment?\"", (char *) NULL); - return TCL_ERROR; - } - - oldString = Tcl_GetVar(interp, argv[1], TCL_LEAVE_ERR_MSG); - if (oldString == NULL) { - return TCL_ERROR; - } - if (Tcl_GetInt(interp, oldString, &value) != TCL_OK) { - Tcl_AddErrorInfo(interp, - "\n (reading value of variable to increment)"); - return TCL_ERROR; - } - if (argc == 2) { - value += 1; - } else { - int increment; - - if (Tcl_GetInt(interp, argv[2], &increment) != TCL_OK) { - Tcl_AddErrorInfo(interp, - "\n (reading increment)"); - return TCL_ERROR; - } - value += increment; - } - TclFormatInt(newString, value); - result = Tcl_SetVar(interp, argv[1], newString, TCL_LEAVE_ERR_MSG); - if (result == NULL) { - return TCL_ERROR; - } - - /* - * Copy the result since the variable's value might change. - */ - - Tcl_SetResult(interp, result, TCL_VOLATILE); +Tcl_IncrObjCmd(dummy, interp, objc, objv) + ClientData dummy; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + long incrAmount; + Tcl_Obj *newValuePtr; + + if ((objc != 2) && (objc != 3)) { + Tcl_WrongNumArgs(interp, 1, objv, "varName ?increment?"); + return TCL_ERROR; + } + + /* + * Calculate the amount to increment by. + */ + + if (objc == 2) { + incrAmount = 1; + } else { + if (Tcl_GetLongFromObj(interp, objv[2], &incrAmount) != TCL_OK) { + Tcl_AddErrorInfo(interp, "\n (reading increment)"); + return TCL_ERROR; + } + } + + /* + * Increment the variable's value. + */ + + newValuePtr = TclIncrVar2(interp, objv[1], (Tcl_Obj *) NULL, incrAmount, + TCL_LEAVE_ERR_MSG); + 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; } /* *---------------------------------------------------------------------- @@ -357,12 +373,12 @@ IArgsIdx, IBodyIdx, ICmdCountIdx, ICommandsIdx, ICompleteIdx, IDefaultIdx, IExistsIdx, IGlobalsIdx, IHostnameIdx, ILevelIdx, ILibraryIdx, ILoadedIdx, ILocalsIdx, INameOfExecutableIdx, IPatchLevelIdx, IProcsIdx, IScriptIdx, ISharedLibExtensionIdx, ITclVersionIdx, IVarsIdx - } index; - int result; + }; + int index, result; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; } @@ -474,11 +490,11 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "procname"); return TCL_ERROR; } - name = Tcl_GetStringFromObj(objv[2], (int *) NULL); + name = Tcl_GetString(objv[2]); procPtr = TclFindProc(iPtr, name); if (procPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "\"", name, "\" isn't a procedure", (char *) NULL); return TCL_ERROR; @@ -489,11 +505,11 @@ */ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; localPtr = localPtr->nextPtr) { - if (localPtr->isArg) { + if (TclIsVarArgument(localPtr)) { Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj(localPtr->name, -1)); } } Tcl_SetObjResult(interp, listObjPtr); @@ -528,24 +544,45 @@ Tcl_Obj *CONST objv[]; /* Argument objects. */ { register Interp *iPtr = (Interp *) interp; char *name; Proc *procPtr; - + Tcl_Obj *bodyPtr, *resultPtr; + if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "procname"); return TCL_ERROR; } - name = Tcl_GetStringFromObj(objv[2], (int *) NULL); + name = Tcl_GetString(objv[2]); procPtr = TclFindProc(iPtr, name); if (procPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "\"", name, "\" isn't a procedure", (char *) NULL); return TCL_ERROR; } - Tcl_SetObjResult(interp, procPtr->bodyPtr); + + /* + * we need to check if the body from this procedure had been generated + * from a precompiled body. If that is the case, then the bodyPtr's + * string representation is bogus, since sources are not available. + * In order to make sure that later manipulations of the object do not + * invalidate the internal representation, we make a copy of the string + * representation and return that one, instead. + */ + + bodyPtr = procPtr->bodyPtr; + resultPtr = bodyPtr; + if (bodyPtr->typePtr == &tclByteCodeType) { + ByteCode *codePtr = (ByteCode *) bodyPtr->internalRep.otherValuePtr; + + if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) { + resultPtr = Tcl_NewStringObj(bodyPtr->bytes, bodyPtr->length); + } + } + + Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -624,11 +661,10 @@ 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 result; /* * Get the pattern and find the "effective namespace" in which to * list commands. */ @@ -646,17 +682,15 @@ * return an empty list since no commands there can be found. */ Namespace *dummy1NsPtr, *dummy2NsPtr; - pattern = Tcl_GetStringFromObj(objv[2], (int *) NULL); - result = TclGetNamespaceForQualName(interp, pattern, - (Namespace *) NULL, /*flags*/ TCL_LEAVE_ERR_MSG, - &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern); - if (result != TCL_OK) { - return TCL_ERROR; - } + + pattern = Tcl_GetString(objv[2]); + TclGetNamespaceForQualName(interp, pattern, (Namespace *) 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, 2, objv, "?pattern?"); @@ -744,23 +778,21 @@ ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - char *command; - if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "command"); return TCL_ERROR; } - command = Tcl_GetStringFromObj(objv[2], (int *) NULL); - if (Tcl_CommandComplete(command)) { + if (TclObjCommandComplete(objv[2])) { Tcl_SetIntObj(Tcl_GetObjResult(interp), 1); } else { Tcl_SetIntObj(Tcl_GetObjResult(interp), 0); } + return TCL_OK; } /* *---------------------------------------------------------------------- @@ -799,12 +831,12 @@ if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "procname arg varname"); return TCL_ERROR; } - procName = Tcl_GetStringFromObj(objv[2], (int *) NULL); - argName = Tcl_GetStringFromObj(objv[3], (int *) NULL); + procName = Tcl_GetString(objv[2]); + argName = Tcl_GetString(objv[3]); procPtr = TclFindProc(iPtr, procName); if (procPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "\"", procName, "\" isn't a procedure", (char *) NULL); @@ -811,27 +843,28 @@ return TCL_ERROR; } for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; localPtr = localPtr->nextPtr) { - if ((localPtr->isArg) && (strcmp(argName, localPtr->name) == 0)) { + if (TclIsVarArgument(localPtr) + && (strcmp(argName, localPtr->name) == 0)) { if (localPtr->defValuePtr != NULL) { valueObjPtr = Tcl_ObjSetVar2(interp, objv[4], NULL, - localPtr->defValuePtr, 0); + localPtr->defValuePtr, 0); if (valueObjPtr == NULL) { defStoreError: - varName = Tcl_GetStringFromObj(objv[4], (int *) NULL); + varName = Tcl_GetString(objv[4]); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "couldn't store default value in variable \"", varName, "\"", (char *) NULL); return TCL_ERROR; } Tcl_SetIntObj(Tcl_GetObjResult(interp), 1); } else { Tcl_Obj *nullObjPtr = Tcl_NewObj(); valueObjPtr = Tcl_ObjSetVar2(interp, objv[4], NULL, - nullObjPtr, 0); + nullObjPtr, 0); if (valueObjPtr == NULL) { Tcl_DecrRefCount(nullObjPtr); /* free unneeded obj */ goto defStoreError; } Tcl_SetIntObj(Tcl_GetObjResult(interp), 0); @@ -879,13 +912,13 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "varName"); return TCL_ERROR; } - varName = Tcl_GetStringFromObj(objv[2], (int *) NULL); + varName = Tcl_GetString(objv[2]); varPtr = TclLookupVar(interp, varName, (char *) NULL, - TCL_PARSE_PART1, "access", + 0, "access", /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); if ((varPtr != NULL) && !TclIsVarUndefined(varPtr)) { Tcl_SetIntObj(Tcl_GetObjResult(interp), 1); } else { Tcl_SetIntObj(Tcl_GetObjResult(interp), 0); @@ -929,11 +962,11 @@ Tcl_Obj *listPtr; if (objc == 2) { pattern = NULL; } else if (objc == 3) { - pattern = Tcl_GetStringFromObj(objv[2], (int *) NULL); + pattern = Tcl_GetString(objv[2]); } else { Tcl_WrongNumArgs(interp, 2, objv, "?pattern?"); return TCL_ERROR; } @@ -1050,11 +1083,11 @@ if (level <= 0) { if (iPtr->varFramePtr == NULL) { levelError: Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad level \"", - Tcl_GetStringFromObj(objv[2], (int *) NULL), + Tcl_GetString(objv[2]), "\"", (char *) NULL); return TCL_ERROR; } level += iPtr->varFramePtr->level; } @@ -1159,11 +1192,11 @@ } if (objc == 2) { /* get loaded pkgs in all interpreters */ interpName = NULL; } else { /* get pkgs just in specified interp */ - interpName = Tcl_GetStringFromObj(objv[2], (int *) NULL); + interpName = Tcl_GetString(objv[2]); } result = TclGetLoadedPackages(interp, interpName); return result; } @@ -1194,71 +1227,108 @@ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { Interp *iPtr = (Interp *) interp; - Var *varPtr; - char *varName, *pattern; - int i, localVarCt; - Tcl_HashTable *localVarTablePtr; - register Tcl_HashEntry *entryPtr; - Tcl_HashSearch search; + char *pattern; Tcl_Obj *listPtr; if (objc == 2) { pattern = NULL; } else if (objc == 3) { - pattern = Tcl_GetStringFromObj(objv[2], (int *) NULL); + pattern = Tcl_GetString(objv[2]); } else { Tcl_WrongNumArgs(interp, 2, objv, "?pattern?"); return TCL_ERROR; } - if (iPtr->varFramePtr == NULL) { + if (iPtr->varFramePtr == NULL || !iPtr->varFramePtr->isProcCallFrame) { return TCL_OK; } - localVarTablePtr = iPtr->varFramePtr->varTablePtr; /* * 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, (Tcl_Obj **) NULL); - + AppendLocals(interp, listPtr, pattern, 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(interp, listPtr, pattern, includeLinks) + Tcl_Interp *interp; /* Current interpreter. */ + Tcl_Obj *listPtr; /* List object to append names to. */ + char *pattern; /* Pattern to match against. */ + int includeLinks; /* 1 if upvars should be included, else 0. */ +{ + Interp *iPtr = (Interp *) interp; + CompiledLocal *localPtr; + Var *varPtr; + int i, localVarCt; + char *varName; + Tcl_HashTable *localVarTablePtr; + register Tcl_HashEntry *entryPtr; + Tcl_HashSearch search; + + localPtr = iPtr->varFramePtr->procPtr->firstLocalPtr; localVarCt = iPtr->varFramePtr->numCompiledLocals; - for (i = 0, varPtr = iPtr->varFramePtr->compiledLocals; - i < localVarCt; - i++, varPtr++) { - if (!TclIsVarUndefined(varPtr)) { + varPtr = iPtr->varFramePtr->compiledLocals; + localVarTablePtr = iPtr->varFramePtr->varTablePtr; + + for (i = 0; i < localVarCt; i++) { + /* + * Skip nameless (temporary) variables and undefined variables + */ + + if (!TclIsVarTemporary(localPtr) && !TclIsVarUndefined(varPtr)) { varName = varPtr->name; if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) { Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(varName, -1)); } } + varPtr++; + localPtr = localPtr->nextPtr; } if (localVarTablePtr != NULL) { for (entryPtr = Tcl_FirstHashEntry(localVarTablePtr, &search); entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { varPtr = (Var *) Tcl_GetHashValue(entryPtr); - if (!TclIsVarUndefined(varPtr) && !TclIsVarLink(varPtr)) { + if (!TclIsVarUndefined(varPtr) + && (includeLinks || !TclIsVarLink(varPtr))) { varName = Tcl_GetHashKey(localVarTablePtr, entryPtr); if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) { Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(varName, -1)); } } } } - - Tcl_SetObjResult(interp, listPtr); - return TCL_OK; } /* *---------------------------------------------------------------------- * @@ -1285,17 +1355,21 @@ ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { + CONST char *nameOfExecutable; + if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } + + nameOfExecutable = Tcl_GetNameOfExecutable(); - if (tclExecutableName != NULL) { - Tcl_SetStringObj(Tcl_GetObjResult(interp), tclExecutableName, -1); + if (nameOfExecutable != NULL) { + Tcl_SetStringObj(Tcl_GetObjResult(interp), (char *)nameOfExecutable, -1); } return TCL_OK; } /* @@ -1372,17 +1446,17 @@ { char *cmdName, *pattern; Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); register Tcl_HashEntry *entryPtr; Tcl_HashSearch search; - Command *cmdPtr; + Command *cmdPtr, *realCmdPtr; Tcl_Obj *listPtr; if (objc == 2) { pattern = NULL; } else if (objc == 3) { - pattern = Tcl_GetStringFromObj(objv[2], (int *) NULL); + pattern = Tcl_GetString(objv[2]); } else { Tcl_WrongNumArgs(interp, 2, objv, "?pattern?"); return TCL_ERROR; } @@ -1395,11 +1469,21 @@ for (entryPtr = Tcl_FirstHashEntry(&currNsPtr->cmdTable, &search); entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { cmdName = Tcl_GetHashKey(&currNsPtr->cmdTable, entryPtr); cmdPtr = (Command *) Tcl_GetHashValue(entryPtr); - if (TclIsProc(cmdPtr)) { + + /* + * If the command isn't itself a proc, it still might be an + * imported command that points to a "real" proc in a different + * namespace. + */ + + realCmdPtr = (Command *) TclGetOriginalCommand( + (Tcl_Command) cmdPtr); + if (TclIsProc(cmdPtr) + || ((realCmdPtr != NULL) && TclIsProc(realCmdPtr))) { if ((pattern == NULL) || Tcl_StringMatch(cmdName, pattern)) { Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(cmdName, -1)); } } @@ -1563,17 +1647,16 @@ { Interp *iPtr = (Interp *) interp; char *varName, *pattern, *simplePattern; register Tcl_HashEntry *entryPtr; Tcl_HashSearch search; - Var *varPtr, *localVarPtr; + Var *varPtr; 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. */ - int i, result; /* * 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. @@ -1592,17 +1675,15 @@ * return an empty list since no variables there can be found. */ Namespace *dummy1NsPtr, *dummy2NsPtr; - pattern = Tcl_GetStringFromObj(objv[2], (int *) NULL); - result = TclGetNamespaceForQualName(interp, pattern, - (Namespace *) NULL, /*flags*/ TCL_LEAVE_ERR_MSG, - &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern); - if (result != TCL_OK) { - return TCL_ERROR; - } + pattern = Tcl_GetString(objv[2]); + TclGetNamespaceForQualName(interp, pattern, (Namespace *) 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, 2, objv, "?pattern?"); @@ -1677,53 +1758,11 @@ } entryPtr = Tcl_NextHashEntry(&search); } } } else { - /* - * We're in a local call frame and no specific namespace was - * specific. Create a list that starts with the compiled locals - * (i.e. the ones stored in the call frame). - */ - - CallFrame *varFramePtr = iPtr->varFramePtr; - int localVarCt = varFramePtr->numCompiledLocals; - Tcl_HashTable *varTablePtr = varFramePtr->varTablePtr; - - for (i = 0, localVarPtr = iPtr->varFramePtr->compiledLocals; - i < localVarCt; - i++, localVarPtr++) { - if (!TclIsVarUndefined(localVarPtr)) { - varName = localVarPtr->name; - if ((simplePattern == NULL) - || Tcl_StringMatch(varName, simplePattern)) { - Tcl_ListObjAppendElement(interp, listPtr, - Tcl_NewStringObj(varName, -1)); - } - } - } - - /* - * Now add in the variables in the call frame's variable hash - * table (if one exists). - */ - - if (varTablePtr != NULL) { - for (entryPtr = Tcl_FirstHashEntry(varTablePtr, &search); - entryPtr != NULL; - entryPtr = Tcl_NextHashEntry(&search)) { - varPtr = (Var *) Tcl_GetHashValue(entryPtr); - if (!TclIsVarUndefined(varPtr)) { - varName = Tcl_GetHashKey(varTablePtr, entryPtr); - if ((simplePattern == NULL) - || Tcl_StringMatch(varName, simplePattern)) { - Tcl_ListObjAppendElement(interp, listPtr, - Tcl_NewStringObj(varName, -1)); - } - } - } - } + AppendLocals(interp, listPtr, simplePattern, 1); } Tcl_SetObjResult(interp, listPtr); return TCL_OK; } @@ -1904,11 +1943,11 @@ Tcl_Obj *CONST objv[]; /* Argument objects. */ { Tcl_Obj *listPtr, *resultPtr; Tcl_ObjType *typePtr; int index, isDuplicate, len, result; - + if (objc < 4) { Tcl_WrongNumArgs(interp, 1, objv, "list index element ?element ...?"); return TCL_ERROR; } @@ -2238,11 +2277,11 @@ } if ((first >= listLen) && (listLen > 0) && (strncmp(firstArg, "end", (unsigned) firstArgLen) != 0)) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "list doesn't contain element ", - Tcl_GetStringFromObj(objv[2], (int *) NULL), (int *) NULL); + Tcl_GetString(objv[2]), (int *) NULL); result = TCL_ERROR; goto errorReturn; } if (last >= listLen) { last = (listLen - 1); @@ -2294,23 +2333,24 @@ ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument values. */ { -#define EXACT 0 -#define GLOB 1 -#define REGEXP 2 char *bytes, *patternBytes; - int i, match, mode, index, result, listLen, length, elemLen; - Tcl_Obj **elemPtrs; - static char *switches[] = - {"-exact", "-glob", "-regexp", (char *) NULL}; + int i, match, mode, index, result, listc, length, elemLen; + Tcl_Obj *patObj, **listv; + static char *options[] = { + "-exact", "-glob", "-regexp", NULL + }; + enum options { + LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_REGEXP + }; - mode = GLOB; + mode = LSEARCH_GLOB; if (objc == 4) { - if (Tcl_GetIndexFromObj(interp, objv[1], switches, - "search mode", 0, &mode) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[1], options, "search mode", 0, + &mode) != TCL_OK) { return TCL_ERROR; } } else if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "?mode? list pattern"); return TCL_ERROR; @@ -2319,50 +2359,47 @@ /* * Make sure the list argument is a list object and get its length and * a pointer to its array of element pointers. */ - result = Tcl_ListObjGetElements(interp, objv[objc-2], &listLen, &elemPtrs); + result = Tcl_ListObjGetElements(interp, objv[objc - 2], &listc, &listv); if (result != TCL_OK) { return result; } - patternBytes = Tcl_GetStringFromObj(objv[objc-1], &length); - + patObj = objv[objc - 1]; + patternBytes = Tcl_GetStringFromObj(patObj, &length); + index = -1; - for (i = 0; i < listLen; i++) { + for (i = 0; i < listc; i++) { match = 0; - bytes = Tcl_GetStringFromObj(elemPtrs[i], &elemLen); - switch (mode) { - case EXACT: + bytes = Tcl_GetStringFromObj(listv[i], &elemLen); + switch ((enum options) mode) { + case LSEARCH_EXACT: { if (length == elemLen) { match = (memcmp(bytes, patternBytes, (size_t) length) == 0); } break; - case GLOB: - /* - * WARNING: will not work with data containing NULLs. - */ + } + case LSEARCH_GLOB: { match = Tcl_StringMatch(bytes, patternBytes); break; - case REGEXP: - /* - * WARNING: will not work with data containing NULLs. - */ - match = Tcl_RegExpMatch(interp, bytes, patternBytes); + } + case LSEARCH_REGEXP: { + match = TclRegExpMatchObj(interp, bytes, patObj); if (match < 0) { return TCL_ERROR; } break; + } } - if (match) { + if (match != 0) { index = i; break; } } - Tcl_SetIntObj(Tcl_GetObjResult(interp), index); return TCL_OK; } /* @@ -2387,11 +2424,11 @@ ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument values. */ { - int i, index, dummy; + int i, index; Tcl_Obj *resultPtr; int length; Tcl_Obj *cmdPtr, **listObjPtrs; SortElement *elementArray; SortElement *elementPtr; @@ -2468,13 +2505,25 @@ sortInfo.sortMode = SORTMODE_REAL; break; } } if (sortInfo.sortMode == SORTMODE_COMMAND) { - Tcl_DStringInit(&sortInfo.compareCmd); - Tcl_DStringAppend(&sortInfo.compareCmd, - Tcl_GetStringFromObj(cmdPtr, &dummy), -1); + /* + * The existing command is a list. We want to flatten it, append + * two dummy arguments on the end, and replace these arguments + * later. + */ + + Tcl_Obj *newCommandPtr = Tcl_DuplicateObj(cmdPtr); + + if (Tcl_ListObjAppendElement(interp, newCommandPtr, Tcl_NewObj()) + != TCL_OK) { + return TCL_ERROR; + } + Tcl_ListObjAppendElement(interp, newCommandPtr, Tcl_NewObj()); + sortInfo.compareCmdPtr = newCommandPtr; + Tcl_IncrRefCount(newCommandPtr); } sortInfo.resultCode = Tcl_ListObjGetElements(interp, objv[objc-1], &length, &listObjPtrs); if (sortInfo.resultCode != TCL_OK) { @@ -2504,11 +2553,12 @@ } ckfree((char*) elementArray); done: if (sortInfo.sortMode == SORTMODE_COMMAND) { - Tcl_DStringFree(&sortInfo.compareCmd); + Tcl_DecrRefCount(sortInfo.compareCmdPtr); + sortInfo.compareCmdPtr = NULL; } return sortInfo.resultCode; } /* @@ -2657,13 +2707,13 @@ SortCompare(objPtr1, objPtr2, infoPtr) Tcl_Obj *objPtr1, *objPtr2; /* Values to be compared. */ SortInfo *infoPtr; /* Information passed from the * top-level "lsort" command */ { - int order, dummy, listLen, index; + int order, listLen, index; Tcl_Obj *objPtr; - char buffer[30]; + char buffer[TCL_INTEGER_SPACE]; order = 0; if (infoPtr->resultCode != TCL_OK) { /* * Once an error has occurred, skip any future comparisons @@ -2696,15 +2746,14 @@ return order; } if (objPtr == NULL) { objPtr = objPtr1; missingElement: - sprintf(buffer, "%d", infoPtr->index); + TclFormatInt(buffer, infoPtr->index); Tcl_AppendStringsToObj(Tcl_GetObjResult(infoPtr->interp), "element ", buffer, " missing from sublist \"", - Tcl_GetStringFromObj(objPtr, (int *) NULL), - "\"", (char *) NULL); + Tcl_GetString(objPtr), "\"", (char *) NULL); infoPtr->resultCode = TCL_ERROR; return order; } objPtr1 = objPtr; @@ -2728,16 +2777,14 @@ goto missingElement; } objPtr2 = objPtr; } if (infoPtr->sortMode == SORTMODE_ASCII) { - order = strcmp(Tcl_GetStringFromObj(objPtr1, &dummy), - Tcl_GetStringFromObj(objPtr2, &dummy)); + order = strcmp(Tcl_GetString(objPtr1), Tcl_GetString(objPtr2)); } else if (infoPtr->sortMode == SORTMODE_DICTIONARY) { order = DictionaryCompare( - Tcl_GetStringFromObj(objPtr1, &dummy), - Tcl_GetStringFromObj(objPtr2, &dummy)); + Tcl_GetString(objPtr1), Tcl_GetString(objPtr2)); } else if (infoPtr->sortMode == SORTMODE_INTEGER) { int a, b; if ((Tcl_GetIntFromObj(infoPtr->interp, objPtr1, &a) != TCL_OK) || (Tcl_GetIntFromObj(infoPtr->interp, objPtr2, &b) @@ -2763,26 +2810,30 @@ order = 1; } else if (b > a) { order = -1; } } else { - int oldLength; + Tcl_Obj **objv, *paramObjv[2]; + int objc; + + paramObjv[0] = objPtr1; + paramObjv[1] = objPtr2; - /* - * Generate and evaluate a command to determine which string comes - * first. + /* + * We made space in the command list for the two things to + * compare. Replace them and evaluate the result. */ - oldLength = Tcl_DStringLength(&infoPtr->compareCmd); - Tcl_DStringAppendElement(&infoPtr->compareCmd, - Tcl_GetStringFromObj(objPtr1, &dummy)); - Tcl_DStringAppendElement(&infoPtr->compareCmd, - Tcl_GetStringFromObj(objPtr2, &dummy)); - infoPtr->resultCode = Tcl_Eval(infoPtr->interp, - Tcl_DStringValue(&infoPtr->compareCmd)); - Tcl_DStringTrunc(&infoPtr->compareCmd, oldLength); - if (infoPtr->resultCode != TCL_OK) { + Tcl_ListObjLength(infoPtr->interp, infoPtr->compareCmdPtr, &objc); + Tcl_ListObjReplace(infoPtr->interp, infoPtr->compareCmdPtr, objc - 2, + 2, 2, paramObjv); + Tcl_ListObjGetElements(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 order; } @@ -2831,29 +2882,31 @@ static int DictionaryCompare(left, right) char *left, *right; /* The strings to compare */ { + Tcl_UniChar uniLeft, uniRight; int diff, zeros; int secondaryDiff = 0; while (1) { - if (isdigit(UCHAR(*right)) && isdigit(UCHAR(*left))) { + 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') && (*(right + 1) != '\0')) { + while ((*right == '0') && (isdigit(UCHAR(right[1])))) { right++; zeros--; } - while ((*left == '0') && (*(left + 1) != '\0')) { + while ((*left == '0') && (isdigit(UCHAR(left[1])))) { left++; zeros++; } if (secondaryDiff == 0) { secondaryDiff = zeros; @@ -2867,16 +2920,16 @@ */ diff = 0; while (1) { if (diff == 0) { - diff = *left - *right; + diff = UCHAR(*left) - UCHAR(*right); } right++; left++; - if (!isdigit(UCHAR(*right))) { - if (isdigit(UCHAR(*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. @@ -2885,42 +2938,54 @@ if (diff != 0) { return diff; } break; } - } else if (!isdigit(UCHAR(*left))) { + } else if (!isdigit(UCHAR(*left))) { /* INTL: digit */ return -1; } } continue; } - diff = *left - *right; + + /* + * 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); + } else { + diff = UCHAR(*left) - UCHAR(*right); + break; + } + + diff = uniLeft - uniRight; if (diff) { - if (isupper(UCHAR(*left)) && islower(UCHAR(*right))) { - diff = tolower(*left) - *right; - if (diff) { + if (Tcl_UniCharIsUpper(uniLeft) && + Tcl_UniCharIsLower(uniRight)) { + diff = Tcl_UniCharToLower(uniLeft) - uniRight; + if (diff) { return diff; } else if (secondaryDiff == 0) { secondaryDiff = -1; } - } else if (isupper(UCHAR(*right)) && islower(UCHAR(*left))) { - diff = *left - tolower(UCHAR(*right)); + } else if (Tcl_UniCharIsUpper(uniRight) + && Tcl_UniCharIsLower(uniLeft)) { + diff = uniLeft - Tcl_UniCharToLower(uniRight); if (diff) { return diff; } else if (secondaryDiff == 0) { secondaryDiff = 1; } } else { return diff; } } - if (*left == 0) { - break; - } - left++; - right++; } if (diff == 0) { diff = secondaryDiff; } return diff; } Index: generic/tclCmdMZ.c ================================================================== --- generic/tclCmdMZ.c +++ generic/tclCmdMZ.c @@ -6,20 +6,38 @@ * 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-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. * - * SCCS: @(#) tclCmdMZ.c 1.104 97/10/31 13:06:19 + * RCS: @(#) $Id: tclCmdMZ.c,v 1.1.2.12 1999/04/06 04:27:01 rjohnson Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclCompile.h" +#include "tclRegexp.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_SIGNOK 0x10 /* A +/- character is allowed. */ +#define SCAN_NODIGITS 0x20 /* No digits have been scanned. */ +#define SCAN_NOZERO 0x40 /* No zero digits have been scanned. */ +#define SCAN_XOK 0x80 /* An 'x' is allowed. */ +#define SCAN_PTOK 0x100 /* Decimal point is allowed. */ +#define SCAN_EXPOK 0x200 /* An exponent is allowed. */ /* * Structure used to hold information about variable traces: */ @@ -26,11 +44,11 @@ typedef struct { int flags; /* Operations for which Tcl command is * to be invoked. */ char *errMsg; /* Error message returned from Tcl command, * or NULL. Malloc'ed. */ - int length; /* Number of non-NULL chars. in command. */ + size_t length; /* Number of non-NULL chars. in command. */ char command[4]; /* 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 4 bytes. */ @@ -45,11 +63,11 @@ int flags)); /* *---------------------------------------------------------------------- * - * Tcl_PwdCmd -- + * Tcl_PwdObjCmd -- * * This procedure is invoked to process the "pwd" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -61,193 +79,229 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_PwdCmd(dummy, interp, argc, argv) - ClientData dummy; /* Not used. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ -{ - char *dirName; - - if (argc != 1) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], "\"", (char *) NULL); - return TCL_ERROR; - } - - dirName = TclGetCwd(interp); - if (dirName == NULL) { - return TCL_ERROR; - } - Tcl_SetResult(interp, dirName, TCL_VOLATILE); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_RegexpCmd -- - * - * 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. - * - *---------------------------------------------------------------------- - */ - - /* ARGSUSED */ -int -Tcl_RegexpCmd(dummy, interp, argc, argv) - ClientData dummy; /* Not used. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ -{ - int noCase = 0; - int indices = 0; - Tcl_RegExp regExpr; - char **argPtr, *string, *pattern, *start, *end; - int match = 0; /* Initialization needed only to - * prevent compiler warning. */ - int i; - Tcl_DString stringDString, patternDString; - - if (argc < 3) { - wrongNumArgs: - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ?switches? exp string ?matchVar? ?subMatchVar ", - "subMatchVar ...?\"", (char *) NULL); - return TCL_ERROR; - } - argPtr = argv+1; - argc--; - while ((argc > 0) && (argPtr[0][0] == '-')) { - if (strcmp(argPtr[0], "-indices") == 0) { - indices = 1; - } else if (strcmp(argPtr[0], "-nocase") == 0) { - noCase = 1; - } else if (strcmp(argPtr[0], "--") == 0) { - argPtr++; - argc--; - break; - } else { - Tcl_AppendResult(interp, "bad switch \"", argPtr[0], - "\": must be -indices, -nocase, or --", (char *) NULL); - return TCL_ERROR; - } - argPtr++; - argc--; - } - if (argc < 2) { - goto wrongNumArgs; - } - - /* - * Convert the string and pattern to lower case, if desired, and - * perform the matching operation. - */ - - if (noCase) { - register char *p; - - Tcl_DStringInit(&patternDString); - Tcl_DStringAppend(&patternDString, argPtr[0], -1); - pattern = Tcl_DStringValue(&patternDString); - for (p = pattern; *p != 0; p++) { - if (isupper(UCHAR(*p))) { - *p = (char)tolower(UCHAR(*p)); - } - } - Tcl_DStringInit(&stringDString); - Tcl_DStringAppend(&stringDString, argPtr[1], -1); - string = Tcl_DStringValue(&stringDString); - for (p = string; *p != 0; p++) { - if (isupper(UCHAR(*p))) { - *p = (char)tolower(UCHAR(*p)); - } - } - } else { - pattern = argPtr[0]; - string = argPtr[1]; - } - regExpr = Tcl_RegExpCompile(interp, pattern); - if (regExpr != NULL) { - match = Tcl_RegExpExec(interp, regExpr, string, string); - } - if (noCase) { - Tcl_DStringFree(&stringDString); - Tcl_DStringFree(&patternDString); - } +Tcl_PwdObjCmd(dummy, interp, objc, objv) + ClientData dummy; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + Tcl_DString ds; + + if (objc != 1) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return TCL_ERROR; + } + + if (Tcl_GetCwd(interp, &ds) == NULL) { + return TCL_ERROR; + } + Tcl_DStringResult(interp, &ds); + 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. The + * REGEXP_TEST stuff is to minimize code differences between this + * and the "testregexp" command. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +Tcl_RegexpObjCmd(dummy, interp, objc, objv) + ClientData dummy; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + int i, result, indices, stringLength, wLen, match, about; + int cflags, eflags; + Tcl_RegExp regExpr; + char *string; + Tcl_DString stringBuffer, valueBuffer; + Tcl_UniChar *wStart; + static char *options[] = { + "-indices", "-nocase", "-about", "-expanded", + "-line", "-linestop", "-lineanchor", + "--", (char *) NULL + }; + enum options { + REGEXP_INDICES, REGEXP_NOCASE, REGEXP_ABOUT, REGEXP_EXPANDED, + REGEXP_LINE, REGEXP_LINESTOP, REGEXP_LINEANCHOR, + REGEXP_LAST + }; + + indices = 0; + about = 0; + cflags = REG_ADVANCED; + eflags = 0; + + for (i = 1; i < objc; i++) { + 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_LINE: { + cflags |= REG_NEWLINE; + break; + } + case REGEXP_LINESTOP: { + cflags |= REG_NLSTOP; + break; + } + case REGEXP_LINEANCHOR: { + cflags |= REG_NLANCH; + break; + } + case REGEXP_LAST: { + i++; + goto endOfForLoop; + } + } + } + + endOfForLoop: + if (objc - i < 2 - about) { + Tcl_WrongNumArgs(interp, 1, objv, + "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?"); + return TCL_ERROR; + } + objc -= i; + objv += i; + + regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags); if (regExpr == NULL) { return TCL_ERROR; } - if (match < 0) { - return TCL_ERROR; - } - if (!match) { - Tcl_SetResult(interp, "0", TCL_STATIC); + + if (about) { + if (TclRegAbout(interp, regExpr) < 0) { + return TCL_ERROR; + } return TCL_OK; } + + result = TCL_OK; + string = Tcl_GetStringFromObj(objv[1], &stringLength); + + Tcl_DStringInit(&valueBuffer); + + Tcl_DStringInit(&stringBuffer); + wStart = Tcl_UtfToUniCharDString(string, stringLength, &stringBuffer); + wLen = Tcl_DStringLength(&stringBuffer) / sizeof(Tcl_UniChar); + + match = TclRegExpExecUniChar(interp, regExpr, wStart, wLen, objc-2, eflags); + if (match < 0) { + result = TCL_ERROR; + goto done; + } + if (match == 0) { + /* + * Set the interpreter's object result to an integer object w/ value 0. + */ + + Tcl_SetIntObj(Tcl_GetObjResult(interp), 0); + goto done; + } /* * If additional variable names have been specified, return * index information in those variables. */ - argc -= 2; - for (i = 0; i < argc; i++) { - char *result, info[50]; - - Tcl_RegExpRange(regExpr, i, &start, &end); - if (start == NULL) { - if (indices) { - result = Tcl_SetVar(interp, argPtr[i+2], "-1 -1", 0); - } else { - result = Tcl_SetVar(interp, argPtr[i+2], "", 0); - } - } else { - if (indices) { - sprintf(info, "%d %d", (int)(start - string), - (int)(end - string - 1)); - result = Tcl_SetVar(interp, argPtr[i+2], info, 0); - } else { - char savedChar, *first, *last; - - first = argPtr[1] + (start - string); - last = argPtr[1] + (end - string); - if (first == last) { /* don't modify argument */ - result = Tcl_SetVar(interp, argPtr[i+2], "", 0); - } else { - savedChar = *last; - *last = 0; - result = Tcl_SetVar(interp, argPtr[i+2], first, 0); - *last = savedChar; - } - } - } - if (result == NULL) { - Tcl_AppendResult(interp, "couldn't set variable \"", - argPtr[i+2], "\"", (char *) NULL); - return TCL_ERROR; - } - } - Tcl_SetResult(interp, "1", TCL_STATIC); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_RegsubCmd -- + objc -= 2; + objv += 2; + + for (i = 0; i < objc; i++) { + char *varName, *value; + int start, end; + + varName = Tcl_GetString(objv[i]); + + TclRegExpRangeUniChar(regExpr, i, &start, &end); + if (start < 0) { + if (indices) { + value = Tcl_SetVar(interp, varName, "-1 -1", 0); + } else { + value = Tcl_SetVar(interp, varName, "", 0); + } + } else { + if (indices) { + char info[TCL_INTEGER_SPACE * 2]; + + sprintf(info, "%d %d", start, end - 1); + value = Tcl_SetVar(interp, varName, info, 0); + } else { + value = Tcl_UniCharToUtfDString(wStart + start, end - start, + &valueBuffer); + value = Tcl_SetVar(interp, varName, value, 0); + Tcl_DStringSetLength(&valueBuffer, 0); + } + } + if (value == NULL) { + Tcl_AppendResult(interp, "couldn't set variable \"", + varName, "\"", (char *) NULL); + result = TCL_ERROR; + goto done; + } + } + + /* + * Set the interpreter's object result to an integer object w/ value 1. + */ + + Tcl_SetIntObj(Tcl_GetObjResult(interp), 1); + + done: + Tcl_DStringFree(&stringBuffer); + Tcl_DStringFree(&valueBuffer); + return result; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_RegsubObjCmd -- * * This procedure is invoked to process the "regsub" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -259,180 +313,176 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_RegsubCmd(dummy, interp, argc, argv) - ClientData dummy; /* Not used. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ -{ - int noCase = 0, all = 0; - Tcl_RegExp regExpr; - char *string, *pattern, *p, *firstChar, **argPtr; - int match, code, numMatches; - char *start, *end, *subStart, *subEnd; - register char *src, c; - Tcl_DString stringDString, patternDString, resultDString; - - if (argc < 5) { - wrongNumArgs: - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ?switches? exp string subSpec varName\"", (char *) NULL); - return TCL_ERROR; - } - argPtr = argv+1; - argc--; - while (argPtr[0][0] == '-') { - if (strcmp(argPtr[0], "-nocase") == 0) { - noCase = 1; - } else if (strcmp(argPtr[0], "-all") == 0) { - all = 1; - } else if (strcmp(argPtr[0], "--") == 0) { - argPtr++; - argc--; - break; - } else { - Tcl_AppendResult(interp, "bad switch \"", argPtr[0], - "\": must be -all, -nocase, or --", (char *) NULL); - return TCL_ERROR; - } - argPtr++; - argc--; - } - if (argc != 4) { - goto wrongNumArgs; - } - - /* - * Convert the string and pattern to lower case, if desired. - */ - - if (noCase) { - Tcl_DStringInit(&patternDString); - Tcl_DStringAppend(&patternDString, argPtr[0], -1); - pattern = Tcl_DStringValue(&patternDString); - for (p = pattern; *p != 0; p++) { - if (isupper(UCHAR(*p))) { - *p = (char)tolower(UCHAR(*p)); - } - } - Tcl_DStringInit(&stringDString); - Tcl_DStringAppend(&stringDString, argPtr[1], -1); - string = Tcl_DStringValue(&stringDString); - for (p = string; *p != 0; p++) { - if (isupper(UCHAR(*p))) { - *p = (char)tolower(UCHAR(*p)); - } - } - } else { - pattern = argPtr[0]; - string = argPtr[1]; - } - Tcl_DStringInit(&resultDString); - regExpr = Tcl_RegExpCompile(interp, pattern); - if (regExpr == NULL) { - code = TCL_ERROR; - goto done; - } +Tcl_RegsubObjCmd(dummy, interp, objc, objv) + ClientData dummy; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + int i, result, flags, all, stringLength, numMatches; + Tcl_RegExp regExpr; + Tcl_DString resultBuffer, stringBuffer; + CONST Tcl_UniChar *w, *wStart, *wEnd; + char *string, *subspec, *varname; + static char *options[] = { + "-all", "-nocase", "--", NULL + }; + enum options { + REGSUB_ALL, REGSUB_NOCASE, REGSUB_LAST + }; + + flags = 0; + all = 0; + + for (i = 1; i < objc; i++) { + 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 REGSUB_ALL: { + all = 1; + break; + } + case REGSUB_NOCASE: { + flags |= REG_ICASE; + break; + } + case REGSUB_LAST: { + i++; + goto endOfForLoop; + } + } + } + endOfForLoop: + if (objc - i != 4) { + Tcl_WrongNumArgs(interp, 1, objv, + "?switches? exp string subSpec varName"); + return TCL_ERROR; + } + + objv += i; + regExpr = Tcl_GetRegExpFromObj(interp, objv[0], flags | REG_ADVANCED); + if (regExpr == NULL) { + return TCL_ERROR; + } + + result = TCL_OK; + string = Tcl_GetStringFromObj(objv[1], &stringLength); + subspec = Tcl_GetString(objv[2]); + varname = Tcl_GetString(objv[3]); + + Tcl_DStringInit(&resultBuffer); /* * 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. */ + Tcl_DStringInit(&stringBuffer); + wStart = Tcl_UtfToUniCharDString(string, stringLength, &stringBuffer); + wEnd = wStart + Tcl_DStringLength(&stringBuffer) / sizeof(Tcl_UniChar); + numMatches = 0; - for (p = string; *p != 0; ) { - match = Tcl_RegExpExec(interp, regExpr, p, string); + for (w = wStart; w < wEnd; ) { + int start, end, subStart, subEnd, match; + char *src, *firstChar; + char c; + + /* + * The flags argument is set if string is part of a larger string, + * so that "^" won't match. + */ + + match = TclRegExpExecUniChar(interp, regExpr, w, wEnd - w, 10, + ((w > wStart) ? REG_NOTBOL : 0)); if (match < 0) { - code = TCL_ERROR; + result = TCL_ERROR; goto done; } - if (!match) { + if (match == 0) { break; } - numMatches += 1; + numMatches++; /* * Copy the portion of the source string before the match to the * result variable. */ - Tcl_RegExpRange(regExpr, 0, &start, &end); - Tcl_DStringAppend(&resultDString, argPtr[1] + (p - string), start - p); + TclRegExpRangeUniChar(regExpr, 0, &start, &end); + Tcl_UniCharToUtfDString(w, start, &resultBuffer); /* * 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. */ - - for (src = firstChar = argPtr[2], c = *src; c != 0; src++, c = *src) { + + src = subspec; + firstChar = subspec; + for (c = *src; c != '\0'; src++, c = *src) { int index; if (c == '&') { index = 0; } else if (c == '\\') { c = src[1]; if ((c >= '0') && (c <= '9')) { index = c - '0'; } else if ((c == '\\') || (c == '&')) { - *src = c; - src[1] = 0; - Tcl_DStringAppend(&resultDString, firstChar, -1); - *src = '\\'; - src[1] = c; - firstChar = src+2; + Tcl_DStringAppend(&resultBuffer, firstChar, + src - firstChar); + Tcl_DStringAppend(&resultBuffer, &c, 1); + firstChar = src + 2; src++; continue; } else { continue; } } else { continue; } if (firstChar != src) { - c = *src; - *src = 0; - Tcl_DStringAppend(&resultDString, firstChar, -1); - *src = c; - } - Tcl_RegExpRange(regExpr, index, &subStart, &subEnd); - if ((subStart != NULL) && (subEnd != NULL)) { - char *first, *last, saved; - - first = argPtr[1] + (subStart - string); - last = argPtr[1] + (subEnd - string); - saved = *last; - *last = 0; - Tcl_DStringAppend(&resultDString, first, -1); - *last = saved; + Tcl_DStringAppend(&resultBuffer, firstChar, src - firstChar); + } + TclRegExpRangeUniChar(regExpr, index, &subStart, &subEnd); + if ((subStart >= 0) && (subEnd >= 0)) { + Tcl_UniCharToUtfDString(w + subStart, subEnd - subStart, + &resultBuffer); } if (*src == '\\') { src++; } - firstChar = src+1; + firstChar = src + 1; } if (firstChar != src) { - Tcl_DStringAppend(&resultDString, firstChar, -1); + Tcl_DStringAppend(&resultBuffer, firstChar, src - firstChar); } - if (end == p) { - + if (end == 0) { /* * Always consume at least one character of the input string * in order to prevent infinite loops. */ - Tcl_DStringAppend(&resultDString, argPtr[1] + (p - string), 1); - p = end + 1; - } else { - p = end; + Tcl_UniCharToUtfDString(w, 1, &resultBuffer); + w++; } + w += end; if (!all) { break; } } @@ -439,34 +489,31 @@ /* * Copy the portion of the source string after the last match to the * result variable. */ - if ((*p != 0) || (numMatches == 0)) { - Tcl_DStringAppend(&resultDString, argPtr[1] + (p - string), -1); + if ((w < wEnd) || (numMatches == 0)) { + Tcl_UniCharToUtfDString(w, wEnd - w, &resultBuffer); } - if (Tcl_SetVar(interp, argPtr[3], Tcl_DStringValue(&resultDString), 0) - == NULL) { - Tcl_AppendResult(interp, - "couldn't set variable \"", argPtr[3], "\"", + if (Tcl_SetVar(interp, varname, Tcl_DStringValue(&resultBuffer), + 0) == NULL) { + Tcl_AppendResult(interp, "couldn't set variable \"", varname, "\"", (char *) NULL); - code = TCL_ERROR; + result = TCL_ERROR; } else { - char buf[40]; + /* + * Set the interpreter's object result to an integer object holding the + * number of matches. + */ - TclFormatInt(buf, numMatches); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - code = TCL_OK; + Tcl_SetIntObj(Tcl_GetObjResult(interp), numMatches); } done: - if (noCase) { - Tcl_DStringFree(&stringDString); - Tcl_DStringFree(&patternDString); - } - Tcl_DStringFree(&resultDString); - return code; + Tcl_DStringFree(&stringBuffer); + Tcl_DStringFree(&resultBuffer); + return result; } /* *---------------------------------------------------------------------- * @@ -497,12 +544,12 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "oldName newName"); return TCL_ERROR; } - oldName = Tcl_GetStringFromObj(objv[1], (int *) NULL); - newName = Tcl_GetStringFromObj(objv[2], (int *) NULL); + oldName = Tcl_GetString(objv[1]); + newName = Tcl_GetString(objv[2]); return TclRenameCommand(interp, oldName, newName); } /* *---------------------------------------------------------------------- @@ -539,14 +586,10 @@ if (iPtr->errorCode != NULL) { ckfree(iPtr->errorCode); iPtr->errorCode = NULL; } code = TCL_OK; - - /* - * THIS FAILS IF AN OBJECT CONTAINS AN EMBEDDED NULL. - */ for (objv++, objc--; objc > 1; objv += 2, objc -= 2) { char *option = Tcl_GetStringFromObj(objv[0], &optionLen); char *arg = Tcl_GetStringFromObj(objv[1], &argLen); @@ -567,11 +610,11 @@ &code); if (result != TCL_OK) { Tcl_ResetResult(interp); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad completion code \"", - Tcl_GetStringFromObj(objv[1], (int *) NULL), + Tcl_GetString(objv[1]), "\": must be ok, error, return, break, ", "continue, or an integer", (char *) NULL); return result; } } @@ -605,314 +648,10 @@ } /* *---------------------------------------------------------------------- * - * Tcl_ScanCmd -- - * - * This procedure 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_ScanCmd(dummy, interp, argc, argv) - ClientData dummy; /* Not used. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ -{ -# define MAX_FIELDS 20 - typedef struct { - char fmt; /* Format for field. */ - int size; /* How many bytes to allow for - * field. */ - char *location; /* Where field will be stored. */ - } Field; - Field fields[MAX_FIELDS]; /* Info about all the fields in the - * format string. */ - register Field *curField; - int numFields = 0; /* Number of fields actually - * specified. */ - int suppress; /* Current field is assignment- - * suppressed. */ - int totalSize = 0; /* Number of bytes needed to store - * all results combined. */ - char *results; /* Where scanned output goes. - * Malloced; NULL means not allocated - * yet. */ - int numScanned; /* sscanf's result. */ - register char *fmt; - int i, widthSpecified, length, code; - char buf[40]; - - /* - * The variables below are used to hold a copy of the format - * string, so that we can replace format specifiers like "%f" - * and "%F" with specifiers like "%lf" - */ - -# define STATIC_SIZE 5 - char copyBuf[STATIC_SIZE], *fmtCopy; - register char *dst; - - if (argc < 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " string format ?varName varName ...?\"", (char *) NULL); - return TCL_ERROR; - } - - /* - * This procedure operates in four stages: - * 1. Scan the format string, collecting information about each field. - * 2. Allocate an array to hold all of the scanned fields. - * 3. Call sscanf to do all the dirty work, and have it store the - * parsed fields in the array. - * 4. Pick off the fields from the array and assign them to variables. - */ - - code = TCL_OK; - results = NULL; - length = strlen(argv[2]) * 2 + 1; - if (length < STATIC_SIZE) { - fmtCopy = copyBuf; - } else { - fmtCopy = (char *) ckalloc((unsigned) length); - } - dst = fmtCopy; - for (fmt = argv[2]; *fmt != 0; fmt++) { - *dst = *fmt; - dst++; - if (*fmt != '%') { - continue; - } - fmt++; - if (*fmt == '%') { - *dst = *fmt; - dst++; - continue; - } - if (*fmt == '*') { - suppress = 1; - *dst = *fmt; - dst++; - fmt++; - } else { - suppress = 0; - } - widthSpecified = 0; - while (isdigit(UCHAR(*fmt))) { - widthSpecified = 1; - *dst = *fmt; - dst++; - fmt++; - } - if ((*fmt == 'l') || (*fmt == 'h') || (*fmt == 'L')) { - fmt++; - } - *dst = *fmt; - dst++; - if (suppress) { - continue; - } - if (numFields == MAX_FIELDS) { - Tcl_SetResult(interp, "too many fields to scan", TCL_STATIC); - code = TCL_ERROR; - goto done; - } - curField = &fields[numFields]; - numFields++; - switch (*fmt) { - case 'd': - case 'i': - case 'o': - case 'x': - curField->fmt = 'd'; - curField->size = sizeof(int); - break; - - case 'u': - curField->fmt = 'u'; - curField->size = sizeof(int); - break; - - case 's': - curField->fmt = 's'; - curField->size = strlen(argv[1]) + 1; - break; - - case 'c': - if (widthSpecified) { - Tcl_SetResult(interp, - "field width may not be specified in %c conversion", - TCL_STATIC); - code = TCL_ERROR; - goto done; - } - curField->fmt = 'c'; - curField->size = sizeof(int); - break; - - case 'e': - case 'f': - case 'g': - dst[-1] = 'l'; - dst[0] = 'f'; - dst++; - curField->fmt = 'f'; - curField->size = sizeof(double); - break; - - case '[': - curField->fmt = 's'; - curField->size = strlen(argv[1]) + 1; - do { - fmt++; - if (*fmt == 0) { - Tcl_SetResult(interp, - "unmatched [ in format string", TCL_STATIC); - code = TCL_ERROR; - goto done; - } - *dst = *fmt; - dst++; - } while (*fmt != ']'); - break; - - default: - { - char buf[50]; - - sprintf(buf, "bad scan conversion character \"%c\"", *fmt); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - code = TCL_ERROR; - goto done; - } - } - curField->size = TCL_ALIGN(curField->size); - totalSize += curField->size; - } - *dst = 0; - - if (numFields != (argc-3)) { - Tcl_SetResult(interp, - "different numbers of variable names and field specifiers", - TCL_STATIC); - code = TCL_ERROR; - goto done; - } - - /* - * Step 2: - */ - - results = (char *) ckalloc((unsigned) totalSize); - for (i = 0, totalSize = 0, curField = fields; - i < numFields; i++, curField++) { - curField->location = results + totalSize; - totalSize += curField->size; - } - - /* - * Fill in the remaining fields with NULL; the only purpose of - * this is to keep some memory analyzers, like Purify, from - * complaining. - */ - - for ( ; i < MAX_FIELDS; i++, curField++) { - curField->location = NULL; - } - - /* - * Step 3: - */ - - numScanned = sscanf(argv[1], fmtCopy, - fields[0].location, fields[1].location, fields[2].location, - fields[3].location, fields[4].location, fields[5].location, - fields[6].location, fields[7].location, fields[8].location, - fields[9].location, fields[10].location, fields[11].location, - fields[12].location, fields[13].location, fields[14].location, - fields[15].location, fields[16].location, fields[17].location, - fields[18].location, fields[19].location); - - /* - * Step 4: - */ - - if (numScanned < numFields) { - numFields = numScanned; - } - for (i = 0, curField = fields; i < numFields; i++, curField++) { - switch (curField->fmt) { - char string[TCL_DOUBLE_SPACE]; - - case 'd': - TclFormatInt(string, *((int *) curField->location)); - if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) { - storeError: - Tcl_AppendResult(interp, - "couldn't set variable \"", argv[i+3], "\"", - (char *) NULL); - code = TCL_ERROR; - goto done; - } - break; - - case 'u': - sprintf(string, "%u", *((int *) curField->location)); - if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) { - goto storeError; - } - break; - - case 'c': - TclFormatInt(string, *((char *) curField->location) & 0xff); - if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) { - goto storeError; - } - break; - - case 's': - if (Tcl_SetVar(interp, argv[i+3], curField->location, 0) - == NULL) { - goto storeError; - } - break; - - case 'f': - Tcl_PrintDouble((Tcl_Interp *) NULL, - *((double *) curField->location), string); - if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) { - goto storeError; - } - break; - } - } - TclFormatInt(buf, numScanned); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - done: - if (results != NULL) { - ckfree(results); - } - if (fmtCopy != copyBuf) { - ckfree(fmtCopy); - } - return code; -} - -/* - *---------------------------------------------------------------------- - * * Tcl_SourceObjCmd -- * * This procedure is invoked to process the "source" Tcl command. * See the user documentation for details on what it does. * @@ -939,15 +678,11 @@ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "fileName"); return TCL_ERROR; } - /* - * THIS FAILS IF THE OBJECT'S STRING REP CONTAINS A NULL. - */ - - bytes = Tcl_GetStringFromObj(objv[1], (int *) NULL); + bytes = Tcl_GetString(objv[1]); result = Tcl_EvalFile(interp, bytes); return result; } /* @@ -973,14 +708,15 @@ ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - register char *p, *p2; - char *splitChars, *string, *elementStart; - int splitCharLen, stringLen, i, j; - Tcl_Obj *listPtr; + Tcl_UniChar ch; + int len; + char *splitChars, *string, *end; + int splitCharLen, stringLen; + Tcl_Obj *listPtr, *objPtr; if (objc == 2) { splitChars = " \n\t\r"; splitCharLen = 4; } else if (objc == 3) { @@ -989,55 +725,66 @@ Tcl_WrongNumArgs(interp, 1, objv, "string ?splitChars?"); return TCL_ERROR; } string = Tcl_GetStringFromObj(objv[1], &stringLen); - listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - - /* - * Handle the special case of splitting on every character. - */ - - if (splitCharLen == 0) { - for (i = 0, p = string; i < stringLen; i++, p++) { - Tcl_ListObjAppendElement(interp, listPtr, - Tcl_NewStringObj(p, 1)); + end = string + stringLen; + listPtr = Tcl_GetObjResult(interp); + + if (stringLen == 0) { + /* + * Do nothing. + */ + } else if (splitCharLen == 0) { + /* + * Handle the special case of splitting on every character. + */ + + for ( ; string < end; string += len) { + len = Tcl_UtfToUniChar(string, &ch); + objPtr = Tcl_NewStringObj(string, len); + Tcl_ListObjAppendElement(NULL, listPtr, objPtr); } } else { + 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. */ - for (i = 0, p = elementStart = string; i < stringLen; i++, p++) { - for (j = 0, p2 = splitChars; j < splitCharLen; j++, p2++) { - if (*p2 == *p) { - Tcl_ListObjAppendElement(interp, listPtr, - Tcl_NewStringObj(elementStart, (p-elementStart))); - elementStart = p+1; + splitEnd = splitChars + splitCharLen; + + for (element = string; string < end; string += len) { + len = Tcl_UtfToUniChar(string, &ch); + for (p = splitChars; p < splitEnd; p += splitLen) { + splitLen = Tcl_UtfToUniChar(p, &splitChar); + if (ch == splitChar) { + objPtr = Tcl_NewStringObj(element, string - element); + Tcl_ListObjAppendElement(NULL, listPtr, objPtr); + element = string + len; break; } } } - if (p != string) { - int remainingChars = stringLen - (elementStart-string); - Tcl_ListObjAppendElement(interp, listPtr, - Tcl_NewStringObj(elementStart, remainingChars)); - } - } - - Tcl_SetObjResult(interp, listPtr); + objPtr = Tcl_NewStringObj(element, string - element); + Tcl_ListObjAppendElement(NULL, listPtr, objPtr); + } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_StringObjCmd -- * * This procedure is invoked to process the "string" Tcl command. - * See the user documentation for details on what it does. + * 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: @@ -1059,18 +806,18 @@ char *string1, *string2; int length1, length2; static char *options[] = { "compare", "first", "index", "last", "length", "match", "range", "tolower", - "toupper", "trim", "trimleft", "trimright", - "wordend", "wordstart", NULL + "toupper", "totitle", "trim", "trimleft", + "trimright", "wordend", "wordstart", (char *) NULL }; enum options { STR_COMPARE, STR_FIRST, STR_INDEX, STR_LAST, STR_LENGTH, STR_MATCH, STR_RANGE, STR_TOLOWER, - STR_TOUPPER, STR_TRIM, STR_TRIMLEFT, STR_TRIMRIGHT, - STR_WORDEND, STR_WORDSTART + STR_TOUPPER, STR_TOTITLE, STR_TRIM, STR_TRIMLEFT, + STR_TRIMRIGHT, STR_WORDEND, STR_WORDSTART }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; @@ -1110,47 +857,71 @@ badFirstLastArgs: Tcl_WrongNumArgs(interp, 2, objv, "string1 string2"); return TCL_ERROR; } + /* + * This algorithm fails on improperly formed UTF strings. + */ + match = -1; string1 = Tcl_GetStringFromObj(objv[2], &length1); string2 = Tcl_GetStringFromObj(objv[3], &length2); if (length1 > 0) { end = string2 + length2 - length1 + 1; for (p = string2; p < end; p++) { - /* - * Scan forward to find the first character. - */ - - p = memchr(p, *string1, (unsigned) (end - p)); - if (p == NULL) { - break; - } - if (memcmp(string1, p, (unsigned) length1) == 0) { - match = p - string2; - break; - } - } + /* + * Scan forward to find the first character. + */ + + p = memchr(p, *string1, (unsigned) (end - p)); + if (p == NULL) { + break; + } + if (memcmp(string1, p, (unsigned) length1) == 0) { + match = p - string2; + break; + } + } + } + + /* + * Compute the character index of the matching string by counting + * the number of characters before the match. + */ + + if (match != -1) { + match = Tcl_NumUtfChars(string2, match); } Tcl_SetIntObj(resultPtr, match); break; } case STR_INDEX: { int index; + Tcl_UniChar ch; + char buf[TCL_UTF_MAX]; + char *start, *end; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "string charIndex"); return TCL_ERROR; } - string1 = Tcl_GetStringFromObj(objv[2], &length1); if (Tcl_GetIntFromObj(interp, objv[3], &index) != TCL_OK) { return TCL_ERROR; } - if ((index >= 0) && (index < length1)) { - Tcl_SetStringObj(resultPtr, string1 + index, 1); + if (index >= 0) { + start = Tcl_GetStringFromObj(objv[2], &length1); + end = start + length1; + for ( ; start < end; index--) { + start += Tcl_UtfToUniChar(start, &ch); + if (index == 0) { + Tcl_SetStringObj(resultPtr, buf, + Tcl_UniCharToUtf(ch, buf)); + break; + } + } } break; } case STR_LAST: { register char *p; @@ -1158,10 +929,14 @@ if (objc != 4) { goto badFirstLastArgs; } + /* + * This algorithm fails on improperly formed UTF strings. + */ + match = -1; string1 = Tcl_GetStringFromObj(objv[2], &length1); string2 = Tcl_GetStringFromObj(objv[3], &length2); if (length1 > 0) { for (p = string2 + length2 - length1; p >= string2; p--) { @@ -1176,21 +951,30 @@ match = p - string2; break; } } } + + /* + * Compute the character index of the matching string by counting + * the number of characters before the match. + */ + + if (match != -1) { + match = Tcl_NumUtfChars(string2, match); + } Tcl_SetIntObj(resultPtr, match); break; } case STR_LENGTH: { if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "string"); return TCL_ERROR; } - (void) Tcl_GetStringFromObj(objv[2], &length1); - Tcl_SetIntObj(resultPtr, length1); + string1 = Tcl_GetStringFromObj(objv[2], &length1); + Tcl_SetIntObj(resultPtr, Tcl_NumUtfChars(string1, length1)); break; } case STR_MATCH: { if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "pattern string"); @@ -1209,10 +993,11 @@ Tcl_WrongNumArgs(interp, 2, objv, "string first last"); return TCL_ERROR; } string1 = Tcl_GetStringFromObj(objv[2], &length1); + length1 = Tcl_NumUtfChars(string1, length1); if (TclGetIntForIndex(interp, objv[3], length1 - 1, &first) != TCL_OK) { return TCL_ERROR; } if (TclGetIntForIndex(interp, objv[4], length1 - 1, @@ -1224,75 +1009,56 @@ } if (last >= length1 - 1) { last = length1 - 1; } if (last >= first) { - Tcl_SetStringObj(resultPtr, string1 + first, last - first + 1); + char *start, *end; + + start = Tcl_UtfAtIndex(string1, first); + end = Tcl_UtfAtIndex(start, last - first + 1); + Tcl_SetStringObj(resultPtr, start, end - start); } break; } - case STR_TOLOWER: { - register char *p, *end; - + case STR_TOLOWER: + case STR_TOUPPER: + case STR_TOTITLE: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "string"); return TCL_ERROR; } string1 = Tcl_GetStringFromObj(objv[2], &length1); /* - * Since I know resultPtr is not a shared object, I can reach - * in and diddle the bytes in its string rep to convert them in - * place to lower case. - */ - - Tcl_SetStringObj(resultPtr, string1, length1); - string1 = Tcl_GetStringFromObj(resultPtr, &length1); - end = string1 + length1; - for (p = string1; p < end; p++) { - if (isupper(UCHAR(*p))) { - *p = (char) tolower(UCHAR(*p)); - } - } - break; - } - case STR_TOUPPER: { - register char *p, *end; - - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "string"); - return TCL_ERROR; - } - - string1 = Tcl_GetStringFromObj(objv[2], &length1); - - /* - * Since I know resultPtr is not a shared object, I can reach - * in and diddle the bytes in its string rep to convert them in - * place to upper case. - */ - - Tcl_SetStringObj(resultPtr, string1, length1); - string1 = Tcl_GetStringFromObj(resultPtr, &length1); - end = string1 + length1; - for (p = string1; p < end; p++) { - if (islower(UCHAR(*p))) { - *p = (char) toupper(UCHAR(*p)); - } - } - break; - } - case STR_TRIM: { - char ch; - register char *p, *end; - char *check, *checkEnd; + * Since the result object is not a shared object, it is + * safe to copy the string into the result and do the + * conversion in place. The conversion may change the length + * of the string, so reset the length after conversion. + */ + + Tcl_SetStringObj(resultPtr, string1, length1); + if ((enum options) index == STR_TOLOWER) { + length1 = Tcl_UtfToLower(Tcl_GetStringFromObj(resultPtr, NULL)); + } else if ((enum options) index == STR_TOUPPER) { + length1 = Tcl_UtfToUpper(Tcl_GetStringFromObj(resultPtr, NULL)); + } else { + length1 = Tcl_UtfToTitle(Tcl_GetStringFromObj(resultPtr, NULL)); + } + Tcl_SetObjLength(resultPtr, length1); + break; + + case STR_TRIM: { + Tcl_UniChar ch, trim; + register char *p, *end; + char *check, *checkEnd; + int offset; left = 1; right = 1; - trim: + dotrim: if (objc == 4) { string2 = Tcl_GetStringFromObj(objv[3], &length2); } else if (objc == 3) { string2 = " \t\n\r"; length2 = strlen(string2); @@ -1303,37 +1069,56 @@ string1 = Tcl_GetStringFromObj(objv[2], &length1); checkEnd = string2 + length2; if (left) { end = string1 + length1; - for (p = string1; p < end; p++) { - ch = *p; - for (check = string2; ; check++) { + /* + * The outer loop iterates over the string. The inner + * loop iterates over the trim characters. The loops + * terminate as soon as a non-trim character is discovered + * and string1 is left pointing at the first non-trim + * character. + */ + + for (p = string1; p < end; p += offset) { + offset = Tcl_UtfToUniChar(p, &ch); + + for (check = string2; ; ) { if (check >= checkEnd) { p = end; break; } - if (ch == *check) { - length1--; - string1++; + check += Tcl_UtfToUniChar(check, &trim); + if (ch == trim) { + length1 -= offset; + string1 += offset; break; } } } } if (right) { end = string1; + + /* + * The outer loop iterates over the string. The inner + * loop iterates over the trim characters. The loops + * terminate as soon as a non-trim character is discovered + * and length1 marks the last non-trim character. + */ + for (p = string1 + length1; p > end; ) { - p--; - ch = *p; - for (check = string2; ; check++) { + p = Tcl_UtfPrev(p, string1); + offset = Tcl_UtfToUniChar(p, &ch); + for (check = string2; ; ) { if (check >= checkEnd) { p = end; break; } - if (ch == *check) { - length1--; + check += Tcl_UtfToUniChar(check, &trim); + if (ch == trim) { + length1 -= offset; break; } } } } @@ -1341,19 +1126,22 @@ break; } case STR_TRIMLEFT: { left = 1; right = 0; - goto trim; + goto dotrim; } case STR_TRIMRIGHT: { left = 0; right = 1; - goto trim; + goto dotrim; } case STR_WORDEND: { - int cur, c; + int cur; + Tcl_UniChar ch; + char *p, *end; + int numChars; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "string index"); return TCL_ERROR; } @@ -1363,27 +1151,34 @@ return TCL_ERROR; } if (index < 0) { index = 0; } - cur = length1; - if (index < length1) { - for (cur = index; cur < length1; cur++) { - c = UCHAR(string1[cur]); - if (!isalnum(c) && (c != '_')) { + numChars = Tcl_NumUtfChars(string1, length1); + if (index < numChars) { + p = Tcl_UtfAtIndex(string1, index); + end = string1+length1; + for (cur = index; p < end; cur++) { + p += Tcl_UtfToUniChar(p, &ch); + if (!Tcl_UniCharIsWordChar(ch)) { break; } } if (cur == index) { - cur = index + 1; + cur++; } + } else { + cur = numChars; } Tcl_SetIntObj(resultPtr, cur); break; } case STR_WORDSTART: { - int cur, c; + int cur; + Tcl_UniChar ch; + char *p; + int numChars; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "string index"); return TCL_ERROR; } @@ -1390,20 +1185,23 @@ string1 = Tcl_GetStringFromObj(objv[2], &length1); if (Tcl_GetIntFromObj(interp, objv[3], &index) != TCL_OK) { return TCL_ERROR; } - if (index >= length1) { - index = length1 - 1; + numChars = Tcl_NumUtfChars(string1, length1); + if (index >= numChars) { + index = numChars - 1; } cur = 0; if (index > 0) { + p = Tcl_UtfAtIndex(string1, index); for (cur = index; cur >= 0; cur--) { - c = UCHAR(string1[cur]); - if (!isalnum(c) && (c != '_')) { + Tcl_UtfToUniChar(p, &ch); + if (!Tcl_UniCharIsWordChar(ch)) { break; } + p = Tcl_UtfPrev(p, string1); } if (cur != index) { cur += 1; } } @@ -1415,11 +1213,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_SubstCmd -- + * Tcl_SubstObjCmd -- * * This procedure is invoked to process the "subst" Tcl command. * See the user documentation for details on what it does. This * command is an almost direct copy of an implementation by * Andrew Payne. @@ -1433,74 +1231,84 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_SubstCmd(dummy, interp, argc, argv) +Tcl_SubstObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { + static char *substOptions[] = { + "-nobackslashes", "-nocommands", "-novariables", (char *) NULL + }; + enum substOptions { + SUBST_NOBACKSLASHES, SUBST_NOCOMMANDS, SUBST_NOVARS + }; Interp *iPtr = (Interp *) interp; Tcl_DString result; char *p, *old, *value; - int code, count, doVars, doCmds, doBackslashes, i; - size_t length; - char c; + int optionIndex, code, count, doVars, doCmds, doBackslashes, i; /* * Parse command-line options. */ doVars = doCmds = doBackslashes = 1; - for (i = 1; i < (argc-1); i++) { - p = argv[i]; + for (i = 1; i < (objc-1); i++) { + p = Tcl_GetString(objv[i]); if (*p != '-') { break; } - length = strlen(p); - if (length < 4) { - badSwitch: - Tcl_AppendResult(interp, "bad switch \"", p, - "\": must be -nobackslashes, -nocommands, ", - "or -novariables", (char *) NULL); + if (Tcl_GetIndexFromObj(interp, objv[i], substOptions, + "switch", 0, &optionIndex) != TCL_OK) { + return TCL_ERROR; } - if ((p[3] == 'b') && (strncmp(p, "-nobackslashes", length) == 0)) { - doBackslashes = 0; - } else if ((p[3] == 'c') && (strncmp(p, "-nocommands", length) == 0)) { - doCmds = 0; - } else if ((p[3] == 'v') && (strncmp(p, "-novariables", length) == 0)) { - doVars = 0; - } else { - goto badSwitch; + switch (optionIndex) { + case SUBST_NOBACKSLASHES: { + doBackslashes = 0; + break; + } + case SUBST_NOCOMMANDS: { + doCmds = 0; + break; + } + case SUBST_NOVARS: { + doVars = 0; + break; + } + default: { + panic("Tcl_SubstObjCmd: bad option index to SubstOptions"); + } } } - if (i != (argc-1)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ?-nobackslashes? ?-nocommands? ?-novariables? string\"", - (char *) NULL); + if (i != (objc-1)) { + Tcl_WrongNumArgs(interp, 1, objv, + "?-nobackslashes? ?-nocommands? ?-novariables? string"); return TCL_ERROR; } /* * Scan through the string one character at a time, performing * command, variable, and backslash substitutions. */ Tcl_DStringInit(&result); - old = p = argv[i]; + old = p = Tcl_GetString(objv[i]); while (*p != 0) { switch (*p) { case '\\': if (doBackslashes) { + char buf[TCL_UTF_MAX]; + if (p != old) { Tcl_DStringAppend(&result, old, p-old); } - c = Tcl_Backslash(p, &count); - Tcl_DStringAppend(&result, &c, 1); + Tcl_DStringAppend(&result, buf, + Tcl_UtfBackslash(p, &count, buf)); p += count; old = p; } else { p++; } @@ -1577,181 +1385,126 @@ ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { -#define EXACT 0 -#define GLOB 1 -#define REGEXP 2 - int switchObjc, index; - Tcl_Obj *CONST *switchObjv; - Tcl_Obj *patternObj, *bodyObj; - char *string, *pattern, *body; - int splitObjs, length, patternLen, i, code, mode, matched, bodyIdx; - static char *switches[] = - {"-exact", "-glob", "-regexp", "--", (char *) NULL}; - - switchObjc = objc-1; - switchObjv = objv+1; - mode = EXACT; - - while (switchObjc > 0) { - string = Tcl_GetStringFromObj(switchObjv[0], &length); - if (*string != '-') { + int i, j, index, mode, matched, result; + char *string, *pattern; + static char *options[] = { + "-exact", "-glob", "-regexp", "--", + NULL + }; + enum options { + OPT_EXACT, OPT_GLOB, OPT_REGEXP, OPT_LAST + }; + + mode = OPT_EXACT; + for (i = 1; i < objc; i++) { + string = Tcl_GetString(objv[i]); + if (string[0] != '-') { break; } - if (Tcl_GetIndexFromObj(interp, switchObjv[0], switches, - "option", 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, + &index) != TCL_OK) { return TCL_ERROR; } - switch (index) { - case 0: /* -exact */ - mode = EXACT; - break; - case 1: /* -glob */ - mode = GLOB; - break; - case 2: /* -regexp */ - mode = REGEXP; - break; - case 3: /* -- */ - switchObjc--; - switchObjv++; - goto doneWithSwitches; - } - switchObjc--; - switchObjv++; - } - - doneWithSwitches: - if (switchObjc < 2) { + if (index == OPT_LAST) { + i++; + break; + } + mode = index; + } + + if (objc - i < 2) { Tcl_WrongNumArgs(interp, 1, objv, "?switches? string pattern body ... ?default body?"); return TCL_ERROR; } - - string = Tcl_GetStringFromObj(switchObjv[0], &length); - switchObjc--; - switchObjv++; + + string = Tcl_GetString(objv[i]); + objc -= i + 1; + objv += i + 1; /* * If all of the pattern/command pairs are lumped into a single * argument, split them out again. */ - splitObjs = 0; - if (switchObjc == 1) { - code = Tcl_ListObjLength(interp, switchObjv[0], &switchObjc); - if (code != TCL_OK) { - return code; + if (objc == 1) { + Tcl_Obj **listv; + + if (Tcl_ListObjGetElements(interp, objv[0], &objc, &listv) != TCL_OK) { + return TCL_ERROR; } - splitObjs = 1; + objv = listv; } - for (i = 0; i < switchObjc; i += 2) { - if (i == (switchObjc-1)) { + for (i = 0; i < objc; i += 2) { + if (i == objc - 1) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "extra switch pattern with no body", -1); - code = TCL_ERROR; - goto done; + return TCL_ERROR; } /* * See if the pattern matches the string. */ - if (splitObjs) { - code = Tcl_ListObjIndex(interp, switchObjv[0], i, &patternObj); - if (code != TCL_OK) { - return code; - } - pattern = Tcl_GetStringFromObj(patternObj, &patternLen); - } else { - pattern = Tcl_GetStringFromObj(switchObjv[i], &patternLen); - } - - matched = 0; - if ((*pattern == 'd') && (i == switchObjc-2) - && (strcmp(pattern, "default") == 0)) { - matched = 1; - } else { - /* - * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL. - */ - switch (mode) { - case EXACT: - matched = (strcmp(string, pattern) == 0); - break; - case GLOB: - matched = Tcl_StringMatch(string, pattern); - break; - case REGEXP: - matched = Tcl_RegExpMatch(interp, string, pattern); - if (matched < 0) { - code = TCL_ERROR; - goto done; - } - break; - } - } - if (!matched) { + pattern = Tcl_GetString(objv[i]); + matched = 0; + if ((i == objc - 2) + && (*pattern == 'd') + && (strcmp(pattern, "default") == 0)) { + matched = 1; + } else { + switch (mode) { + case OPT_EXACT: + matched = (strcmp(string, pattern) == 0); + break; + case OPT_GLOB: + matched = Tcl_StringMatch(string, pattern); + break; + case OPT_REGEXP: + matched = TclRegExpMatchObj(interp, string, objv[i]); + if (matched < 0) { + return TCL_ERROR; + } + break; + } + } + if (matched == 0) { continue; } /* * We've got a match. Find a body to execute, skipping bodies * that are "-". */ - for (bodyIdx = i+1; ; bodyIdx += 2) { - if (bodyIdx >= switchObjc) { + for (j = i + 1; ; j += 2) { + if (j >= objc) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no body specified for pattern \"", pattern, "\"", (char *) NULL); - code = TCL_ERROR; - goto done; - } - - if (splitObjs) { - code = Tcl_ListObjIndex(interp, switchObjv[0], bodyIdx, - &bodyObj); - if (code != TCL_OK) { - return code; - } - } else { - bodyObj = switchObjv[bodyIdx]; - } - /* - * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL. - */ - body = Tcl_GetStringFromObj(bodyObj, &length); - if ((length != 1) || (body[0] != '-')) { + return TCL_ERROR; + } + if (strcmp(Tcl_GetString(objv[j]), "-") != 0) { break; } } - code = Tcl_EvalObj(interp, bodyObj); - if (code == TCL_ERROR) { - char msg[100]; + result = Tcl_EvalObjEx(interp, objv[j], 0); + if (result == TCL_ERROR) { + char msg[100 + TCL_INTEGER_SPACE]; + sprintf(msg, "\n (\"%.50s\" arm line %d)", pattern, interp->errorLine); Tcl_AddObjErrorInfo(interp, msg, -1); } - goto done; - } - - /* - * Nothing matched: return nothing. - */ - - code = TCL_OK; - - done: - return code; -#undef EXACT -#undef GLOB -#undef REGEXP + return result; + } + return TCL_OK; } /* *---------------------------------------------------------------------- * @@ -1798,11 +1551,11 @@ objPtr = objv[1]; i = count; TclpGetTime(&start); while (i-- > 0) { - result = Tcl_EvalObj(interp, objPtr); + result = Tcl_EvalObjEx(interp, objPtr, 0); if (result != TCL_OK) { return result; } } TclpGetTime(&stop); @@ -1817,11 +1570,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_TraceCmd -- + * Tcl_TraceObjCmd -- * * This procedure is invoked to process the "trace" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -1833,164 +1586,190 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_TraceCmd(dummy, interp, argc, argv) +Tcl_TraceObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ -{ - int c; - size_t length; - - if (argc < 2) { - Tcl_AppendResult(interp, "too few args: should be \"", - argv[0], " option [arg arg ...]\"", (char *) NULL); - return TCL_ERROR; - } - c = argv[1][1]; - length = strlen(argv[1]); - if ((c == 'a') && (strncmp(argv[1], "variable", length) == 0) - && (length >= 2)) { - char *p; - int flags, length; - TraceVarInfo *tvarPtr; - - if (argc != 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " variable name ops command\"", (char *) NULL); - return TCL_ERROR; - } - - flags = 0; - for (p = argv[3] ; *p != 0; p++) { - if (*p == 'r') { - flags |= TCL_TRACE_READS; - } else if (*p == 'w') { - flags |= TCL_TRACE_WRITES; - } else if (*p == 'u') { - flags |= TCL_TRACE_UNSETS; - } else { - goto badOps; - } - } - if (flags == 0) { - goto badOps; - } - - length = strlen(argv[4]); - tvarPtr = (TraceVarInfo *) ckalloc((unsigned) - (sizeof(TraceVarInfo) - sizeof(tvarPtr->command) + length + 1)); - tvarPtr->flags = flags; - tvarPtr->errMsg = NULL; - tvarPtr->length = length; - flags |= TCL_TRACE_UNSETS; - strcpy(tvarPtr->command, argv[4]); - if (Tcl_TraceVar(interp, argv[2], flags, TraceVarProc, - (ClientData) tvarPtr) != TCL_OK) { - ckfree((char *) tvarPtr); - return TCL_ERROR; - } - } else if ((c == 'd') && (strncmp(argv[1], "vdelete", length) - && (length >= 2)) == 0) { - char *p; - int flags, length; - TraceVarInfo *tvarPtr; - ClientData clientData; - - if (argc != 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " vdelete name ops command\"", (char *) NULL); - return TCL_ERROR; - } - - flags = 0; - for (p = argv[3] ; *p != 0; p++) { - if (*p == 'r') { - flags |= TCL_TRACE_READS; - } else if (*p == 'w') { - flags |= TCL_TRACE_WRITES; - } else if (*p == 'u') { - flags |= TCL_TRACE_UNSETS; - } else { - goto badOps; - } - } - if (flags == 0) { - goto badOps; - } - - /* - * 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. - */ - - length = strlen(argv[4]); - clientData = 0; - while ((clientData = Tcl_VarTraceInfo(interp, argv[2], 0, - TraceVarProc, clientData)) != 0) { - tvarPtr = (TraceVarInfo *) clientData; - if ((tvarPtr->length == length) && (tvarPtr->flags == flags) - && (strncmp(argv[4], tvarPtr->command, - (size_t) length) == 0)) { - Tcl_UntraceVar(interp, argv[2], flags | TCL_TRACE_UNSETS, - TraceVarProc, clientData); - if (tvarPtr->errMsg != NULL) { - ckfree(tvarPtr->errMsg); - } - ckfree((char *) tvarPtr); - break; - } - } - } else if ((c == 'i') && (strncmp(argv[1], "vinfo", length) == 0) - && (length >= 2)) { - ClientData clientData; - char ops[4], *p; - char *prefix = "{"; - - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " vinfo name\"", (char *) NULL); - return TCL_ERROR; - } - clientData = 0; - while ((clientData = Tcl_VarTraceInfo(interp, argv[2], 0, - TraceVarProc, clientData)) != 0) { - TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData; - p = ops; - if (tvarPtr->flags & TCL_TRACE_READS) { - *p = 'r'; - p++; - } - if (tvarPtr->flags & TCL_TRACE_WRITES) { - *p = 'w'; - p++; - } - if (tvarPtr->flags & TCL_TRACE_UNSETS) { - *p = 'u'; - p++; - } - *p = '\0'; - Tcl_AppendResult(interp, prefix, (char *) NULL); - Tcl_AppendElement(interp, ops); - Tcl_AppendElement(interp, tvarPtr->command); - Tcl_AppendResult(interp, "}", (char *) NULL); - prefix = " {"; - } - } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": should be variable, vdelete, or vinfo", - (char *) NULL); - return TCL_ERROR; + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + int optionIndex, commandLength; + char *name, *rwuOps, *command, *p; + size_t length; + static char *traceOptions[] = { + "variable", "vdelete", "vinfo", (char *) NULL + }; + enum traceOptions { + TRACE_VARIABLE, TRACE_VDELETE, TRACE_VINFO + }; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option [arg 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_VARIABLE: { + int flags; + TraceVarInfo *tvarPtr; + if (objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "name ops command"); + return TCL_ERROR; + } + + flags = 0; + rwuOps = Tcl_GetString(objv[3]); + for (p = rwuOps; *p != 0; p++) { + if (*p == 'r') { + flags |= TCL_TRACE_READS; + } else if (*p == 'w') { + flags |= TCL_TRACE_WRITES; + } else if (*p == 'u') { + flags |= TCL_TRACE_UNSETS; + } else { + goto badOps; + } + } + if (flags == 0) { + goto badOps; + } + + command = Tcl_GetStringFromObj(objv[4], &commandLength); + length = (size_t) commandLength; + tvarPtr = (TraceVarInfo *) ckalloc((unsigned) + (sizeof(TraceVarInfo) - sizeof(tvarPtr->command) + + length + 1)); + tvarPtr->flags = flags; + tvarPtr->errMsg = NULL; + tvarPtr->length = length; + flags |= TCL_TRACE_UNSETS; + strcpy(tvarPtr->command, command); + name = Tcl_GetString(objv[2]); + if (Tcl_TraceVar(interp, name, flags, TraceVarProc, + (ClientData) tvarPtr) != TCL_OK) { + ckfree((char *) tvarPtr); + return TCL_ERROR; + } + break; + } + case TRACE_VDELETE: { + int flags; + TraceVarInfo *tvarPtr; + ClientData clientData; + + if (objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "name ops command"); + return TCL_ERROR; + } + + flags = 0; + rwuOps = Tcl_GetString(objv[3]); + for (p = rwuOps; *p != 0; p++) { + if (*p == 'r') { + flags |= TCL_TRACE_READS; + } else if (*p == 'w') { + flags |= TCL_TRACE_WRITES; + } else if (*p == 'u') { + flags |= TCL_TRACE_UNSETS; + } else { + goto badOps; + } + } + if (flags == 0) { + goto badOps; + } + + /* + * 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. + */ + + command = Tcl_GetStringFromObj(objv[4], &commandLength); + length = (size_t) commandLength; + clientData = 0; + name = Tcl_GetString(objv[2]); + while ((clientData = Tcl_VarTraceInfo(interp, name, 0, + TraceVarProc, clientData)) != 0) { + tvarPtr = (TraceVarInfo *) clientData; + if ((tvarPtr->length == length) && (tvarPtr->flags == flags) + && (strncmp(command, tvarPtr->command, + (size_t) length) == 0)) { + Tcl_UntraceVar(interp, name, flags | TCL_TRACE_UNSETS, + TraceVarProc, clientData); + if (tvarPtr->errMsg != NULL) { + ckfree(tvarPtr->errMsg); + } + ckfree((char *) tvarPtr); + break; + } + } + break; + } + case TRACE_VINFO: { + ClientData clientData; + char ops[4]; + Tcl_Obj *resultListPtr, *pairObjPtr, *elemObjPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "name"); + return TCL_ERROR; + } + resultListPtr = Tcl_GetObjResult(interp); + clientData = 0; + name = Tcl_GetString(objv[2]); + while ((clientData = Tcl_VarTraceInfo(interp, name, 0, + TraceVarProc, clientData)) != 0) { + + TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData; + + pairObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); + p = ops; + if (tvarPtr->flags & TCL_TRACE_READS) { + *p = 'r'; + p++; + } + if (tvarPtr->flags & TCL_TRACE_WRITES) { + *p = 'w'; + p++; + } + if (tvarPtr->flags & TCL_TRACE_UNSETS) { + *p = 'u'; + p++; + } + *p = '\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; + } + default: { + panic("Tcl_TraceObjCmd: bad option index to TraceOptions"); + } } return TCL_OK; badOps: - Tcl_AppendResult(interp, "bad operations \"", argv[3], + Tcl_AppendResult(interp, "bad operations \"", rwuOps, "\": should be one or more of rwu", (char *) NULL); return TCL_ERROR; } /* @@ -2020,17 +1799,15 @@ char *name2; /* Name of element within array; NULL means * scalar variable is being referenced. */ int flags; /* OR-ed bits giving operation and other * information. */ { - Interp *iPtr = (Interp *) interp; + Tcl_SavedResult state; TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData; char *result; int code; - Interp dummy; Tcl_DString cmd; - Tcl_Obj *saveObjPtr, *oldObjResultPtr; result = NULL; if (tvarPtr->errMsg != NULL) { ckfree(tvarPtr->errMsg); tvarPtr->errMsg = NULL; @@ -2046,11 +1823,11 @@ if (name2 == NULL) { name2 = ""; } Tcl_DStringInit(&cmd); - Tcl_DStringAppend(&cmd, tvarPtr->command, tvarPtr->length); + Tcl_DStringAppend(&cmd, tvarPtr->command, (int) tvarPtr->length); Tcl_DStringAppendElement(&cmd, name1); Tcl_DStringAppendElement(&cmd, name2); if (flags & TCL_TRACE_READS) { Tcl_DStringAppend(&cmd, " r", 2); } else if (flags & TCL_TRACE_WRITES) { @@ -2058,57 +1835,29 @@ } else if (flags & TCL_TRACE_UNSETS) { Tcl_DStringAppend(&cmd, " u", 2); } /* - * Execute the command. Be careful to save and restore both the - * string and object results from the interpreter used for + * Execute the command. Save the interp's result used for * the command. We discard any object result the command returns. */ - dummy.objResultPtr = Tcl_NewObj(); - Tcl_IncrRefCount(dummy.objResultPtr); - if (interp->freeProc == 0) { - dummy.freeProc = (Tcl_FreeProc *) 0; - dummy.result = ""; - Tcl_SetResult((Tcl_Interp *) &dummy, interp->result, - TCL_VOLATILE); - } else { - dummy.freeProc = interp->freeProc; - dummy.result = interp->result; - interp->freeProc = (Tcl_FreeProc *) 0; - } - - saveObjPtr = Tcl_GetObjResult(interp); - Tcl_IncrRefCount(saveObjPtr); - - code = Tcl_Eval(interp, Tcl_DStringValue(&cmd)); - if (code != TCL_OK) { /* copy error msg to result */ - tvarPtr->errMsg = (char *) - ckalloc((unsigned) (strlen(interp->result) + 1)); - strcpy(tvarPtr->errMsg, interp->result); - result = tvarPtr->errMsg; - Tcl_ResetResult(interp); /* must clear error state. */ - } - - /* - * Restore the interpreter's string result. - */ - - Tcl_SetResult(interp, dummy.result, - (dummy.freeProc == 0) ? TCL_VOLATILE : dummy.freeProc); - - /* - * Restore the interpreter's object result from saveObjPtr. - */ - - oldObjResultPtr = iPtr->objResultPtr; - iPtr->objResultPtr = saveObjPtr; /* was incremented above */ - Tcl_DecrRefCount(oldObjResultPtr); - - Tcl_DecrRefCount(dummy.objResultPtr); - dummy.objResultPtr = NULL; + Tcl_SaveResult(interp, &state); + + code = Tcl_Eval(interp, Tcl_DStringValue(&cmd)); + if (code != TCL_OK) { /* copy error msg to result */ + char *string; + int length; + + string = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length); + tvarPtr->errMsg = (char *) ckalloc((unsigned) (length + 1)); + memcpy(tvarPtr->errMsg, string, (size_t) (length + 1)); + result = tvarPtr->errMsg; + } + + Tcl_RestoreResult(interp, &state); + Tcl_DStringFree(&cmd); } if (flags & TCL_TRACE_DESTROYED) { result = NULL; if (tvarPtr->errMsg != NULL) { @@ -2120,11 +1869,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_WhileCmd -- + * 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 @@ -2140,36 +1889,36 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_WhileCmd(dummy, interp, argc, argv) +Tcl_WhileObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { int result, value; - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " test command\"", (char *) NULL); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "test command"); return TCL_ERROR; } while (1) { - result = Tcl_ExprBoolean(interp, argv[1], &value); + result = Tcl_ExprBooleanObj(interp, objv[1], &value); if (result != TCL_OK) { return result; } if (!value) { break; } - result = Tcl_Eval(interp, argv[2]); + result = Tcl_EvalObjEx(interp, objv[2], 0); if ((result != TCL_OK) && (result != TCL_CONTINUE)) { if (result == TCL_ERROR) { - char msg[60]; + char msg[32 + TCL_INTEGER_SPACE]; + sprintf(msg, "\n (\"while\" body line %d)", interp->errorLine); Tcl_AddErrorInfo(interp, msg); } break; ADDED generic/tclCompCmds.c Index: generic/tclCompCmds.c ================================================================== --- /dev/null +++ generic/tclCompCmds.c @@ -0,0 +1,1980 @@ +/* + * 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. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclCompCmds.c,v 1.1.2.8 1999/02/10 23:31:14 stanton Exp $ + */ + +#include "tclInt.h" +#include "tclCompile.h" + +/* + * Prototypes for procedures defined later in this file: + */ + +static ClientData DupForeachInfo _ANSI_ARGS_((ClientData clientData)); +static void FreeForeachInfo _ANSI_ARGS_(( + ClientData clientData)); + +/* + * The structures below define the AuxData types defined in this file. + */ + +AuxDataType tclForeachInfoType = { + "ForeachInfo", /* name */ + DupForeachInfo, /* dupProc */ + FreeForeachInfo /* freeProc */ +}; + +/* + *---------------------------------------------------------------------- + * + * TclCompileBreakCmd -- + * + * Procedure called to compile the "break" command. + * + * Results: + * The return value is a standard Tcl result, which is TCL_OK unless + * there was an error during compilation. If an error occurs then + * the interpreter's result contains a standard error message. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the command. + * + * Side effects: + * Instructions are added to envPtr to execute the "break" command + * at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileBreakCmd(interp, parsePtr, envPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Parse *parsePtr; /* Points to a parse structure for the + * command created by Tcl_ParseCommand. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ +{ + if (parsePtr->numWords != 1) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: should be \"break\"", -1); + envPtr->maxStackDepth = 0; + return TCL_ERROR; + } + + /* + * Emit a break instruction. + */ + + TclEmitOpcode(INST_BREAK, envPtr); + envPtr->maxStackDepth = 0; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TclCompileCatchCmd -- + * + * Procedure called to compile the "catch" command. + * + * Results: + * The return value is a standard Tcl result, which is TCL_OK if + * compilation was successful. If an error occurs then the + * interpreter's result contains a standard error message and TCL_ERROR + * is returned. If the command is too complex for TclCompileCatchCmd, + * TCL_OUT_LINE_COMPILE is returned indicating that the catch command + * should be compiled "out of line" by emitting code to invoke its + * command procedure at runtime. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the command. + * + * Side effects: + * Instructions are added to envPtr to execute the "catch" command + * at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileCatchCmd(interp, parsePtr, envPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Parse *parsePtr; /* Points to a parse structure for the + * command created by Tcl_ParseCommand. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ +{ + JumpFixup jumpFixup; + Tcl_Token *cmdTokenPtr, *nameTokenPtr; + char *name; + int localIndex, nameChars, range, maxDepth, startOffset, jumpDist; + int code; + char buffer[32 + TCL_INTEGER_SPACE]; + + envPtr->maxStackDepth = 0; + if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: should be \"catch command ?varName?\"", -1); + return TCL_ERROR; + } + + /* + * If a variable was 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) && (envPtr->procPtr == NULL)) { + return TCL_OUT_LINE_COMPILE; + } + + /* + * Make sure the variable name, if any, has no substitutions and just + * refers to a local scaler. + */ + + localIndex = -1; + cmdTokenPtr = parsePtr->tokenPtr + + (parsePtr->tokenPtr->numComponents + 1); + if (parsePtr->numWords == 3) { + nameTokenPtr = cmdTokenPtr + (cmdTokenPtr->numComponents + 1); + if (nameTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { + name = nameTokenPtr[1].start; + nameChars = nameTokenPtr[1].size; + if (!TclIsLocalScalar(name, nameChars)) { + return TCL_OUT_LINE_COMPILE; + } + localIndex = TclFindCompiledLocal(nameTokenPtr[1].start, + nameTokenPtr[1].size, /*create*/ 1, + /*flags*/ VAR_SCALAR, envPtr->procPtr); + } else { + return TCL_OUT_LINE_COMPILE; + } + } + + /* + * We will compile the catch command. Emit a beginCatch instruction at + * the start of the catch body: the subcommand it controls. + */ + + maxDepth = 0; + + envPtr->exceptDepth++; + envPtr->maxExceptDepth = + TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth); + range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); + TclEmitInstInt4(INST_BEGIN_CATCH4, range, envPtr); + + startOffset = (envPtr->codeNext - envPtr->codeStart); + envPtr->exceptArrayPtr[range].codeOffset = startOffset; + code = TclCompileCmdWord(interp, cmdTokenPtr+1, + cmdTokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + sprintf(buffer, "\n (\"catch\" body line %d)", + interp->errorLine); + Tcl_AddObjErrorInfo(interp, buffer, -1); + } + goto done; + } + maxDepth = envPtr->maxStackDepth; + envPtr->exceptArrayPtr[range].numCodeBytes = + (envPtr->codeNext - envPtr->codeStart) - startOffset; + + /* + * The "no errors" epilogue code: store the body's result into the + * variable (if any), push "0" (TCL_OK) as the catch's "no error" + * result, and jump around the "error case" code. + */ + + if (localIndex != -1) { + if (localIndex <= 255) { + TclEmitInstInt1(INST_STORE_SCALAR1, localIndex, envPtr); + } else { + TclEmitInstInt4(INST_STORE_SCALAR4, localIndex, envPtr); + } + } + TclEmitOpcode(INST_POP, envPtr); + TclEmitPush(TclRegisterLiteral(envPtr, "0", 1, /*onHeap*/ 0), + envPtr); + if (maxDepth == 0) { + maxDepth = 1; + } + TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); + + /* + * The "error case" code: store the body's result into the variable (if + * any), then push the error result code. The initial PC offset here is + * the catch's error target. + */ + + envPtr->exceptArrayPtr[range].catchOffset = + (envPtr->codeNext - envPtr->codeStart); + if (localIndex != -1) { + TclEmitOpcode(INST_PUSH_RESULT, envPtr); + if (localIndex <= 255) { + TclEmitInstInt1(INST_STORE_SCALAR1, localIndex, envPtr); + } else { + TclEmitInstInt4(INST_STORE_SCALAR4, localIndex, envPtr); + } + TclEmitOpcode(INST_POP, envPtr); + } + TclEmitOpcode(INST_PUSH_RETURN_CODE, envPtr); + + /* + * Update the target of the jump after the "no errors" code, then emit + * an endCatch instruction at the end of the catch command. + */ + + jumpDist = (envPtr->codeNext - envPtr->codeStart) + - jumpFixup.codeOffset; + if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) { + panic("TclCompileCatchCmd: bad jump distance %d\n", jumpDist); + } + TclEmitOpcode(INST_END_CATCH, envPtr); + + done: + envPtr->exceptDepth--; + envPtr->maxStackDepth = maxDepth; + return code; +} + +/* + *---------------------------------------------------------------------- + * + * TclCompileContinueCmd -- + * + * Procedure called to compile the "continue" command. + * + * Results: + * The return value is a standard Tcl result, which is TCL_OK unless + * there was an error while parsing string. If an error occurs then + * the interpreter's result contains a standard error message. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the command. + * + * Side effects: + * Instructions are added to envPtr to execute the "continue" command + * at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileContinueCmd(interp, parsePtr, envPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Parse *parsePtr; /* Points to a parse structure for the + * command created by Tcl_ParseCommand. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ +{ + /* + * There should be no argument after the "continue". + */ + + if (parsePtr->numWords != 1) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: should be \"continue\"", -1); + envPtr->maxStackDepth = 0; + return TCL_ERROR; + } + + /* + * Emit a continue instruction. + */ + + TclEmitOpcode(INST_CONTINUE, envPtr); + envPtr->maxStackDepth = 0; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TclCompileExprCmd -- + * + * Procedure called to compile the "expr" command. + * + * Results: + * The return value is a standard Tcl result, which is TCL_OK + * unless there was an error while parsing string. If an error occurs + * then the interpreter's result contains a standard error message. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the "expr" command. + * + * Side effects: + * Instructions are added to envPtr to execute the "expr" command + * at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileExprCmd(interp, parsePtr, envPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Parse *parsePtr; /* Points to a parse structure for the + * command created by Tcl_ParseCommand. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ +{ + Tcl_Token *firstWordPtr; + + envPtr->maxStackDepth = 0; + if (parsePtr->numWords == 1) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: should be \"expr arg ?arg ...?\"", -1); + return TCL_ERROR; + } + + firstWordPtr = parsePtr->tokenPtr + + (parsePtr->tokenPtr->numComponents + 1); + return TclCompileExprWords(interp, firstWordPtr, (parsePtr->numWords-1), + envPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TclCompileForCmd -- + * + * Procedure called to compile the "for" command. + * + * Results: + * The return value is a standard Tcl result, which is TCL_OK unless + * there was an error while parsing string. If an error occurs then + * the interpreter's result contains a standard error message. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the command. + * + * Side effects: + * Instructions are added to envPtr to execute the "for" command + * at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileForCmd(interp, parsePtr, envPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Parse *parsePtr; /* Points to a parse structure for the + * command created by Tcl_ParseCommand. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ +{ + Tcl_Token *startTokenPtr, *testTokenPtr, *nextTokenPtr, *bodyTokenPtr; + JumpFixup jumpFalseFixup; + int maxDepth, jumpBackDist, jumpBackOffset, testCodeOffset, jumpDist; + int bodyRange, nextRange, code; + unsigned char *jumpPc; + char buffer[32 + TCL_INTEGER_SPACE]; + + envPtr->maxStackDepth = 0; + if (parsePtr->numWords != 5) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: should be \"for start test next command\"", -1); + 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 = parsePtr->tokenPtr + + (parsePtr->tokenPtr->numComponents + 1); + testTokenPtr = startTokenPtr + (startTokenPtr->numComponents + 1); + if (testTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { + return TCL_OUT_LINE_COMPILE; + } + + /* + * Create ExceptionRange records for the body and the "next" command. + * The "next" command's ExceptionRange supports break but not continue + * (and has a -1 continueOffset). + */ + + envPtr->exceptDepth++; + envPtr->maxExceptDepth = + TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth); + bodyRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); + nextRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); + + /* + * Inline compile the initial command. + */ + + maxDepth = 0; + code = TclCompileCmdWord(interp, startTokenPtr+1, + startTokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + Tcl_AddObjErrorInfo(interp, + "\n (\"for\" initial command)", -1); + } + goto done; + } + maxDepth = envPtr->maxStackDepth; + TclEmitOpcode(INST_POP, envPtr); + + /* + * Compile the test then emit the conditional jump that exits the for. + */ + + testCodeOffset = (envPtr->codeNext - envPtr->codeStart); + code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + Tcl_AddObjErrorInfo(interp, + "\n (\"for\" test expression)", -1); + } + goto done; + } + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup); + + /* + * Compile the loop body. + */ + + nextTokenPtr = testTokenPtr + (testTokenPtr->numComponents + 1); + bodyTokenPtr = nextTokenPtr + (nextTokenPtr->numComponents + 1); + envPtr->exceptArrayPtr[bodyRange].codeOffset = + (envPtr->codeNext - envPtr->codeStart); + code = TclCompileCmdWord(interp, bodyTokenPtr+1, + bodyTokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + sprintf(buffer, "\n (\"for\" body line %d)", + interp->errorLine); + Tcl_AddObjErrorInfo(interp, buffer, -1); + } + goto done; + } + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + envPtr->exceptArrayPtr[bodyRange].numCodeBytes = + (envPtr->codeNext - envPtr->codeStart) + - envPtr->exceptArrayPtr[bodyRange].codeOffset; + TclEmitOpcode(INST_POP, envPtr); + + /* + * Compile the "next" subcommand. + */ + + envPtr->exceptArrayPtr[bodyRange].continueOffset = + (envPtr->codeNext - envPtr->codeStart); + envPtr->exceptArrayPtr[nextRange].codeOffset = + (envPtr->codeNext - envPtr->codeStart); + code = TclCompileCmdWord(interp, nextTokenPtr+1, + nextTokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + Tcl_AddObjErrorInfo(interp, + "\n (\"for\" loop-end command)", -1); + } + goto done; + } + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + envPtr->exceptArrayPtr[nextRange].numCodeBytes = + (envPtr->codeNext - envPtr->codeStart) + - envPtr->exceptArrayPtr[nextRange].codeOffset; + TclEmitOpcode(INST_POP, envPtr); + + /* + * Jump back to the test at the top of the loop. Generate a 4 byte jump + * if the distance to the test is > 120 bytes. This is conservative and + * ensures that we won't have to replace this jump if we later need to + * replace the ifFalse jump with a 4 byte jump. + */ + + jumpBackOffset = (envPtr->codeNext - envPtr->codeStart); + jumpBackDist = (jumpBackOffset - testCodeOffset); + if (jumpBackDist > 120) { + TclEmitInstInt4(INST_JUMP4, -jumpBackDist, envPtr); + } else { + TclEmitInstInt1(INST_JUMP1, -jumpBackDist, envPtr); + } + + /* + * Fix the target of the jumpFalse after the test. + */ + + jumpDist = (envPtr->codeNext - envPtr->codeStart) + - jumpFalseFixup.codeOffset; + if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) { + /* + * Update the loop body and "next" command ExceptionRanges since + * they moved down. + */ + + envPtr->exceptArrayPtr[bodyRange].codeOffset += 3; + envPtr->exceptArrayPtr[bodyRange].continueOffset += 3; + envPtr->exceptArrayPtr[nextRange].codeOffset += 3; + + /* + * Update the jump back to the test at the top of the loop since it + * also moved down 3 bytes. + */ + + jumpBackOffset += 3; + jumpPc = (envPtr->codeStart + jumpBackOffset); + jumpBackDist += 3; + if (jumpBackDist > 120) { + TclUpdateInstInt4AtPc(INST_JUMP4, -jumpBackDist, jumpPc); + } else { + TclUpdateInstInt1AtPc(INST_JUMP1, -jumpBackDist, jumpPc); + } + } + + /* + * Set the loop's break target. + */ + + envPtr->exceptArrayPtr[bodyRange].breakOffset = + envPtr->exceptArrayPtr[nextRange].breakOffset = + (envPtr->codeNext - envPtr->codeStart); + + /* + * The for command's result is an empty string. + */ + + TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr); + if (maxDepth == 0) { + maxDepth = 1; + } + code = TCL_OK; + + done: + envPtr->maxStackDepth = maxDepth; + envPtr->exceptDepth--; + return code; +} + +/* + *---------------------------------------------------------------------- + * + * TclCompileForeachCmd -- + * + * Procedure called to compile the "foreach" command. + * + * Results: + * The return value is a standard Tcl result, which is TCL_OK if + * compilation was successful. If an error occurs then the + * interpreter's result contains a standard error message and TCL_ERROR + * is returned. If the command is too complex for TclCompileForeachCmd, + * TCL_OUT_LINE_COMPILE is returned indicating that the foreach command + * should be compiled "out of line" by emitting code to invoke its + * command procedure at runtime. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the "while" command. + * + * Side effects: + * Instructions are added to envPtr to execute the "foreach" command + * at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileForeachCmd(interp, parsePtr, envPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Parse *parsePtr; /* Points to a parse structure for the + * command created by Tcl_ParseCommand. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ +{ + Proc *procPtr = envPtr->procPtr; + ForeachInfo *infoPtr; /* Points to the structure describing this + * foreach command. Stored in a AuxData + * record in the ByteCode. */ + int firstValueTemp; /* Index of the first temp var in the frame + * used to point to a value list. */ + int loopCtTemp; /* Index of temp var holding the loop's + * iteration count. */ + Tcl_Token *tokenPtr, *bodyTokenPtr; + char *varList; + unsigned char *jumpPc; + JumpFixup jumpFalseFixup; + int jumpDist, jumpBackDist, jumpBackOffset, maxDepth, infoIndex, range; + int numWords, numLists, numVars, loopIndex, tempVar, i, j, code; + char savedChar; + char buffer[32 + TCL_INTEGER_SPACE]; + + /* + * We parse the variable list argument words and create two arrays: + * varcList[i] is number of variables in i-th var list + * varvList[i] points to array of var names in i-th var list + */ + +#define STATIC_VAR_LIST_SIZE 5 + int varcListStaticSpace[STATIC_VAR_LIST_SIZE]; + char **varvListStaticSpace[STATIC_VAR_LIST_SIZE]; + int *varcList = varcListStaticSpace; + char ***varvList = varvListStaticSpace; + + /* + * If the foreach command isn't in a procedure, don't compile it inline: + * the payoff is too small. + */ + + envPtr->maxStackDepth = 0; + if (procPtr == NULL) { + return TCL_OUT_LINE_COMPILE; + } + + maxDepth = 0; + + numWords = parsePtr->numWords; + if ((numWords < 4) || (numWords%2 != 0)) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: should be \"foreach varList list ?varList list ...? command\"", -1); + return TCL_ERROR; + } + + /* + * Allocate storage for the varcList and varvList arrays if necessary. + */ + + numLists = (numWords - 2)/2; + if (numLists > STATIC_VAR_LIST_SIZE) { + varcList = (int *) ckalloc(numLists * sizeof(int)); + varvList = (char ***) ckalloc(numLists * sizeof(char **)); + } + for (loopIndex = 0; loopIndex < numLists; loopIndex++) { + varcList[loopIndex] = 0; + varvList[loopIndex] = (char **) NULL; + } + + /* + * Set the exception stack depth. + */ + + envPtr->exceptDepth++; + envPtr->maxExceptDepth = + TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth); + + /* + * Break up each var list and set the varcList and varvList arrays. + * Don't compile the foreach inline if any var name needs substitutions + * or isn't a scalar, or if any var list needs substitutions. + */ + + loopIndex = 0; + for (i = 0, tokenPtr = parsePtr->tokenPtr; + i < numWords-1; + i++, tokenPtr += (tokenPtr->numComponents + 1)) { + if (i%2 == 1) { + if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { + code = TCL_OUT_LINE_COMPILE; + goto done; + } + varList = tokenPtr[1].start; + savedChar = varList[tokenPtr[1].size]; + + /* + * Note there is a danger that modifying the string could have + * undesirable side effects. In this case, Tcl_SplitList does + * not have any dependencies on shared strings so we should be + * safe. + */ + + varList[tokenPtr[1].size] = '\0'; + code = Tcl_SplitList(interp, varList, + &varcList[loopIndex], &varvList[loopIndex]); + varList[tokenPtr[1].size] = savedChar; + if (code != TCL_OK) { + goto done; + } + + numVars = varcList[loopIndex]; + for (j = 0; j < numVars; j++) { + char *varName = varvList[loopIndex][j]; + if (!TclIsLocalScalar(varName, (int) strlen(varName))) { + code = TCL_OUT_LINE_COMPILE; + goto done; + } + } + loopIndex++; + } + } + + /* + * We will compile the foreach command. + * Reserve (numLists + 1) temporary variables: + * - numLists temps to hold each value list + * - 1 temp for the loop counter (index of next element in each list) + * At this time we don't try to reuse temporaries; if there are two + * nonoverlapping foreach loops, they don't share any temps. + */ + + firstValueTemp = -1; + for (loopIndex = 0; loopIndex < numLists; loopIndex++) { + tempVar = TclFindCompiledLocal(NULL, /*nameChars*/ 0, + /*create*/ 1, /*flags*/ VAR_SCALAR, procPtr); + if (loopIndex == 0) { + firstValueTemp = tempVar; + } + } + loopCtTemp = TclFindCompiledLocal(NULL, /*nameChars*/ 0, + /*create*/ 1, /*flags*/ VAR_SCALAR, procPtr); + + /* + * Create and initialize the ForeachInfo and ForeachVarList data + * structures describing this command. Then create a AuxData record + * pointing to the ForeachInfo structure. + */ + + infoPtr = (ForeachInfo *) ckalloc((unsigned) + (sizeof(ForeachInfo) + (numLists * sizeof(ForeachVarList *)))); + infoPtr->numLists = numLists; + infoPtr->firstValueTemp = firstValueTemp; + infoPtr->loopCtTemp = loopCtTemp; + for (loopIndex = 0; loopIndex < numLists; loopIndex++) { + ForeachVarList *varListPtr; + numVars = varcList[loopIndex]; + varListPtr = (ForeachVarList *) ckalloc((unsigned) + sizeof(ForeachVarList) + (numVars * sizeof(int))); + varListPtr->numVars = numVars; + for (j = 0; j < numVars; j++) { + char *varName = varvList[loopIndex][j]; + int nameChars = strlen(varName); + varListPtr->varIndexes[j] = TclFindCompiledLocal(varName, + nameChars, /*create*/ 1, /*flags*/ VAR_SCALAR, procPtr); + } + infoPtr->varLists[loopIndex] = varListPtr; + } + infoIndex = TclCreateAuxData((ClientData) infoPtr, &tclForeachInfoType, envPtr); + + /* + * Evaluate then store each value list in the associated temporary. + */ + + range = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); + + loopIndex = 0; + for (i = 0, tokenPtr = parsePtr->tokenPtr; + i < numWords-1; + i++, tokenPtr += (tokenPtr->numComponents + 1)) { + if ((i%2 == 0) && (i > 0)) { + code = TclCompileTokens(interp, tokenPtr+1, + tokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + + tempVar = (firstValueTemp + loopIndex); + if (tempVar <= 255) { + TclEmitInstInt1(INST_STORE_SCALAR1, tempVar, envPtr); + } else { + TclEmitInstInt4(INST_STORE_SCALAR4, tempVar, envPtr); + } + TclEmitOpcode(INST_POP, envPtr); + loopIndex++; + } + } + bodyTokenPtr = tokenPtr; + + /* + * Initialize the temporary var that holds the count of loop iterations. + */ + + TclEmitInstInt4(INST_FOREACH_START4, infoIndex, envPtr); + + /* + * Top of loop code: assign each loop variable and check whether + * to terminate the loop. + */ + + envPtr->exceptArrayPtr[range].continueOffset = + (envPtr->codeNext - envPtr->codeStart); + TclEmitInstInt4(INST_FOREACH_STEP4, infoIndex, envPtr); + TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup); + + /* + * Inline compile the loop body. + */ + + envPtr->exceptArrayPtr[range].codeOffset = + (envPtr->codeNext - envPtr->codeStart); + code = TclCompileCmdWord(interp, bodyTokenPtr+1, + bodyTokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + sprintf(buffer, "\n (\"foreach\" body line %d)", + interp->errorLine); + Tcl_AddObjErrorInfo(interp, buffer, -1); + } + goto done; + } + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + envPtr->exceptArrayPtr[range].numCodeBytes = + (envPtr->codeNext - envPtr->codeStart) + - envPtr->exceptArrayPtr[range].codeOffset; + TclEmitOpcode(INST_POP, envPtr); + + /* + * Jump back to the test at the top of the loop. Generate a 4 byte jump + * if the distance to the test is > 120 bytes. This is conservative and + * ensures that we won't have to replace this jump if we later need to + * replace the ifFalse jump with a 4 byte jump. + */ + + jumpBackOffset = (envPtr->codeNext - envPtr->codeStart); + jumpBackDist = + (jumpBackOffset - envPtr->exceptArrayPtr[range].continueOffset); + if (jumpBackDist > 120) { + TclEmitInstInt4(INST_JUMP4, -jumpBackDist, envPtr); + } else { + TclEmitInstInt1(INST_JUMP1, -jumpBackDist, envPtr); + } + + /* + * Fix the target of the jump after the foreach_step test. + */ + + jumpDist = (envPtr->codeNext - envPtr->codeStart) + - jumpFalseFixup.codeOffset; + if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) { + /* + * Update the loop body's starting PC offset since it moved down. + */ + + envPtr->exceptArrayPtr[range].codeOffset += 3; + + /* + * Update the jump back to the test at the top of the loop since it + * also moved down 3 bytes. + */ + + jumpBackOffset += 3; + jumpPc = (envPtr->codeStart + jumpBackOffset); + jumpBackDist += 3; + if (jumpBackDist > 120) { + TclUpdateInstInt4AtPc(INST_JUMP4, -jumpBackDist, jumpPc); + } else { + TclUpdateInstInt1AtPc(INST_JUMP1, -jumpBackDist, jumpPc); + } + } + + /* + * Set the loop's break target. + */ + + envPtr->exceptArrayPtr[range].breakOffset = + (envPtr->codeNext - envPtr->codeStart); + + /* + * The foreach command's result is an empty string. + */ + + TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr); + if (maxDepth == 0) { + maxDepth = 1; + } + + done: + for (loopIndex = 0; loopIndex < numLists; loopIndex++) { + if (varvList[loopIndex] != (char **) NULL) { + ckfree((char *) varvList[loopIndex]); + } + } + if (varcList != varcListStaticSpace) { + ckfree((char *) varcList); + ckfree((char *) varvList); + } + envPtr->maxStackDepth = maxDepth; + envPtr->exceptDepth--; + 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 clientData; /* The foreach command's compilation + * auxiliary data to duplicate. */ +{ + register ForeachInfo *srcPtr = (ForeachInfo *) clientData; + ForeachInfo *dupPtr; + register ForeachVarList *srcListPtr, *dupListPtr; + int numLists = srcPtr->numLists; + int numVars, i, j; + + dupPtr = (ForeachInfo *) ckalloc((unsigned) + (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 = (ForeachVarList *) ckalloc((unsigned) + 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 (ClientData) 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 clientData; /* The foreach command's compilation + * auxiliary data to free. */ +{ + register ForeachInfo *infoPtr = (ForeachInfo *) clientData; + register ForeachVarList *listPtr; + int numLists = infoPtr->numLists; + register int i; + + for (i = 0; i < numLists; i++) { + listPtr = infoPtr->varLists[i]; + ckfree((char *) listPtr); + } + ckfree((char *) infoPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TclCompileIfCmd -- + * + * Procedure called to compile the "if" command. + * + * Results: + * The return value is a standard Tcl result, which is TCL_OK if + * compilation was successful. If an error occurs then the + * interpreter's result contains a standard error message and TCL_ERROR + * is returned. If the command is too complex for TclCompileIfCmd, + * TCL_OUT_LINE_COMPILE is returned indicating that the if command + * should be compiled "out of line" by emitting code to invoke its + * command procedure at runtime. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the command. + * + * Side effects: + * Instructions are added to envPtr to execute the "if" command + * at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileIfCmd(interp, parsePtr, envPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Parse *parsePtr; /* Points to a parse structure for the + * command created by Tcl_ParseCommand. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ +{ + JumpFixupArray jumpFalseFixupArray; + /* Used to fix the ifFalse jump after each + * test when its target PC is determined. */ + JumpFixupArray jumpEndFixupArray; + /* Used to fix the jump after each "then" + * body to the end of the "if" when that PC + * is determined. */ + Tcl_Token *tokenPtr, *testTokenPtr; + int jumpDist, jumpFalseDist, jumpIndex; + int numWords, wordIdx, numBytes, maxDepth, j, code; + char *word; + char buffer[100]; + + TclInitJumpFixupArray(&jumpFalseFixupArray); + TclInitJumpFixupArray(&jumpEndFixupArray); + maxDepth = 0; + 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; + numWords = parsePtr->numWords; + while (wordIdx < numWords) { + /* + * Stop looping if the token isn't "if" or "elseif". + */ + + if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { + break; + } + word = tokenPtr[1].start; + numBytes = tokenPtr[1].size; + if ((tokenPtr == parsePtr->tokenPtr) + || ((numBytes == 6) && (strncmp(word, "elseif", 6) == 0))) { + tokenPtr += (tokenPtr->numComponents + 1); + wordIdx++; + } else { + break; + } + if (wordIdx >= numWords) { + sprintf(buffer, + "wrong # args: no expression after \"%.30s\" argument", + word); + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), buffer, -1); + code = TCL_ERROR; + goto done; + } + + /* + * Compile the test expression then emit the conditional jump + * around the "then" part. If the expression word isn't simple, + * we back off and compile the if command out-of-line. + */ + + testTokenPtr = tokenPtr; + code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + Tcl_AddObjErrorInfo(interp, + "\n (\"if\" test expression)", -1); + } + goto done; + } + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) { + TclExpandJumpFixupArray(&jumpFalseFixupArray); + } + jumpIndex = jumpFalseFixupArray.next; + jumpFalseFixupArray.next++; + TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, + &(jumpFalseFixupArray.fixup[jumpIndex])); + + /* + * Skip over the optional "then" before the then clause. + */ + + tokenPtr = testTokenPtr + (testTokenPtr->numComponents + 1); + wordIdx++; + if (wordIdx >= numWords) { + sprintf(buffer, "wrong # args: no script following \"%.20s\" argument", testTokenPtr->start); + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), buffer, -1); + 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 += (tokenPtr->numComponents + 1); + wordIdx++; + if (wordIdx >= numWords) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: no script following \"then\" argument", -1); + code = TCL_ERROR; + goto done; + } + } + } + + /* + * Compile the "then" command body. + */ + + code = TclCompileCmdWord(interp, tokenPtr+1, + tokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + sprintf(buffer, "\n (\"if\" then script line %d)", + interp->errorLine); + Tcl_AddObjErrorInfo(interp, buffer, -1); + } + goto done; + } + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + + /* + * 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. + */ + + jumpDist = (envPtr->codeNext - envPtr->codeStart) + - jumpFalseFixupArray.fixup[jumpIndex].codeOffset; + if (TclFixupForwardJump(envPtr, + &(jumpFalseFixupArray.fixup[jumpIndex]), jumpDist, 120)) { + /* + * Adjust the code offset for the proceeding jump to the end + * of the "if" command. + */ + + jumpEndFixupArray.fixup[jumpIndex].codeOffset += 3; + } + + tokenPtr += (tokenPtr->numComponents + 1); + wordIdx++; + } + + /* + * Check for the optional else clause. + */ + + 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 += (tokenPtr->numComponents + 1); + wordIdx++; + if (wordIdx >= numWords) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: no script following \"else\" argument", -1); + code = TCL_ERROR; + goto done; + } + } + + /* + * Compile the else command body. + */ + + code = TclCompileCmdWord(interp, tokenPtr+1, + tokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + sprintf(buffer, "\n (\"if\" else script line %d)", + interp->errorLine); + Tcl_AddObjErrorInfo(interp, buffer, -1); + } + goto done; + } + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + + /* + * Make sure there are no words after the else clause. + */ + + wordIdx++; + if (wordIdx < numWords) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: extra words after \"else\" clause in \"if\" command", -1); + code = TCL_ERROR; + goto done; + } + } else { + /* + * No else clause: the "if" command's result is an empty string. + */ + + TclEmitPush(TclRegisterLiteral(envPtr, "", 0,/*onHeap*/ 0), envPtr); + maxDepth = TclMax(1, maxDepth); + } + + /* + * 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 */ + jumpDist = (envPtr->codeNext - envPtr->codeStart) + - jumpEndFixupArray.fixup[jumpIndex].codeOffset; + if (TclFixupForwardJump(envPtr, + &(jumpEndFixupArray.fixup[jumpIndex]), jumpDist, 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 { + panic("TclCompileIfCmd: unexpected opcode updating ifFalse jump"); + } + } + } + + /* + * Free the jumpFixupArray array if malloc'ed storage was used. + */ + + done: + TclFreeJumpFixupArray(&jumpFalseFixupArray); + TclFreeJumpFixupArray(&jumpEndFixupArray); + envPtr->maxStackDepth = maxDepth; + return code; +} + +/* + *---------------------------------------------------------------------- + * + * TclCompileIncrCmd -- + * + * Procedure called to compile the "incr" command. + * + * Results: + * The return value is a standard Tcl result, which is TCL_OK if + * compilation was successful. If an error occurs then the + * interpreter's result contains a standard error message and TCL_ERROR + * is returned. If the command is too complex for TclCompileIncrCmd, + * TCL_OUT_LINE_COMPILE is returned indicating that the incr command + * should be compiled "out of line" by emitting code to invoke its + * command procedure at runtime. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the "incr" command. + * + * Side effects: + * Instructions are added to envPtr to execute the "incr" command + * at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileIncrCmd(interp, parsePtr, envPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Parse *parsePtr; /* Points to a parse structure for the + * command created by Tcl_ParseCommand. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ +{ + Tcl_Token *varTokenPtr, *incrTokenPtr; + Tcl_Parse elemParse; + int gotElemParse = 0; + char *name, *elName, *p; + int nameChars, elNameChars, haveImmValue, immValue, localIndex, i, code; + int maxDepth = 0; + char buffer[160]; + + envPtr->maxStackDepth = 0; + if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: should be \"incr varName ?increment?\"", -1); + return TCL_ERROR; + } + + name = NULL; + elName = NULL; + elNameChars = 0; + localIndex = -1; + code = TCL_OK; + + varTokenPtr = parsePtr->tokenPtr + + (parsePtr->tokenPtr->numComponents + 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. + */ + + name = varTokenPtr[1].start; + nameChars = varTokenPtr[1].size; + for (i = 0, p = name; i < nameChars; i++, p++) { + if (*p == '(') { + char *openParen = p; + p = (name + nameChars-1); + if (*p == ')') { /* last char is ')' => array reference */ + nameChars = (openParen - name); + elName = openParen+1; + elNameChars = (p - elName); + } + break; + } + } + if (envPtr->procPtr != NULL) { + localIndex = TclFindCompiledLocal(name, nameChars, + /*create*/ 0, /*flags*/ 0, envPtr->procPtr); + if (localIndex > 255) { /* we'll push the name */ + localIndex = -1; + } + } + if (localIndex < 0) { + TclEmitPush(TclRegisterLiteral(envPtr, name, nameChars, + /*onHeap*/ 0), envPtr); + maxDepth = 1; + } + + /* + * Compile the element script, if any. + */ + + if (elName != NULL) { + /* + * Temporarily replace the '(' and ')' by '"'s. + */ + + *(elName-1) = '"'; + *(elName+elNameChars) = '"'; + code = Tcl_ParseCommand(interp, elName-1, elNameChars+2, + /*nested*/ 0, &elemParse); + *(elName-1) = '('; + *(elName+elNameChars) = ')'; + gotElemParse = 1; + if ((code != TCL_OK) || (elemParse.numWords > 1)) { + sprintf(buffer, "\n (parsing index for array \"%.*s\")", + TclMin(nameChars, 100), name); + Tcl_AddObjErrorInfo(interp, buffer, -1); + code = TCL_ERROR; + goto done; + } else if (elemParse.numWords == 1) { + code = TclCompileTokens(interp, elemParse.tokenPtr+1, + elemParse.tokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth += envPtr->maxStackDepth; + } else { + TclEmitPush(TclRegisterLiteral(envPtr, "", 0, + /*alreadyAlloced*/ 0), envPtr); + maxDepth += 1; + } + } + } else { + /* + * Not a simple variable name. Look it up at runtime. + */ + + code = TclCompileTokens(interp, varTokenPtr+1, + varTokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + } + + /* + * If an increment is given, push it, but see first if it's a small + * integer. + */ + + haveImmValue = 0; + immValue = 0; + if (parsePtr->numWords == 3) { + incrTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1); + if (incrTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { + char *word = incrTokenPtr[1].start; + int numBytes = incrTokenPtr[1].size; + char savedChar = word[numBytes]; + long n; + + /* + * Note there is a danger that modifying the string could have + * undesirable side effects. In this case, TclLooksLikeInt and + * TclGetLong do not have any dependencies on shared strings so we + * should be safe. + */ + + word[numBytes] = '\0'; + if (TclLooksLikeInt(word, numBytes) + && (TclGetLong((Tcl_Interp *) NULL, word, &n) == TCL_OK)) { + if ((-127 <= n) && (n <= 127)) { + haveImmValue = 1; + immValue = n; + } + } + word[numBytes] = savedChar; + if (!haveImmValue) { + TclEmitPush(TclRegisterLiteral(envPtr, word, numBytes, + /*onHeap*/ 0), envPtr); + maxDepth += 1; + } + } else { + code = TclCompileTokens(interp, incrTokenPtr+1, + incrTokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + Tcl_AddObjErrorInfo(interp, + "\n (increment expression)", -1); + } + goto done; + } + maxDepth += envPtr->maxStackDepth; + } + } else { /* no incr amount given so use 1 */ + haveImmValue = 1; + immValue = 1; + } + + /* + * Emit the instruction to increment the variable. + */ + + if (name != NULL) { + if (elName == NULL) { + 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_SCALAR_STK_IMM, immValue, + envPtr); + } else { + TclEmitOpcode(INST_INCR_SCALAR_STK, envPtr); + } + } + } else { + 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); + } + } + } + } else { /* non-simple variable name */ + if (haveImmValue) { + TclEmitInstInt1(INST_INCR_STK_IMM, immValue, envPtr); + } else { + TclEmitOpcode(INST_INCR_STK, envPtr); + } + } + + done: + if (gotElemParse) { + Tcl_FreeParse(&elemParse); + } + envPtr->maxStackDepth = maxDepth; + return code; +} + +/* + *---------------------------------------------------------------------- + * + * TclCompileSetCmd -- + * + * Procedure called to compile the "set" command. + * + * Results: + * The return value is a standard Tcl result, which is normally TCL_OK + * unless there was an error while parsing string. If an error occurs + * then the interpreter's result contains a standard error message. If + * complation fails because the set command requires a second level of + * substitutions, TCL_OUT_LINE_COMPILE is returned indicating that the + * set command should be compiled "out of line" by emitting code to + * invoke its command procedure (Tcl_SetCmd) at runtime. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the incr command. + * + * Side effects: + * Instructions are added to envPtr to execute the "set" command + * at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileSetCmd(interp, parsePtr, envPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Parse *parsePtr; /* Points to a parse structure for the + * command created by Tcl_ParseCommand. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ +{ + Tcl_Token *varTokenPtr, *valueTokenPtr; + Tcl_Parse elemParse; + int gotElemParse = 0; + register char *p; + char *name, *elName; + int nameChars, elNameChars; + register int i; + int isAssignment, simpleVarName, localIndex, numWords; + int maxDepth = 0; + int code = TCL_OK; + + envPtr->maxStackDepth = 0; + numWords = parsePtr->numWords; + if ((numWords != 2) && (numWords != 3)) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: should be \"set varName ?newValue?\"", -1); + 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. + */ + + simpleVarName = 0; + name = elName = NULL; + nameChars = elNameChars = 0; + localIndex = -1; + + varTokenPtr = parsePtr->tokenPtr + + (parsePtr->tokenPtr->numComponents + 1); + if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { + simpleVarName = 1; + name = varTokenPtr[1].start; + nameChars = varTokenPtr[1].size; + /* last char is ')' => potential array reference */ + if ( *(name + nameChars - 1) == ')') { + for (i = 0, p = name; i < nameChars; i++, p++) { + if (*p == '(') { + elName = p + 1; + elNameChars = nameChars - i - 2; + nameChars = i ; + break; + } + } + } + + /* + * If elName contains any double quotes ("), we can't inline + * compile the element script using the replace '()' by '"' + * technique below. + */ + + for (i = 0, p = elName; i < elNameChars; i++, p++) { + if (*p == '"') { + simpleVarName = 0; + break; + } + } + } else if ((varTokenPtr->numComponents == 4) + && (varTokenPtr[1].type == TCL_TOKEN_TEXT) + && (varTokenPtr[1].start[varTokenPtr[1].size-1] == '(') + && (varTokenPtr[4].type == TCL_TOKEN_TEXT) + && (varTokenPtr[4].size == 1) + && (varTokenPtr[4].start[0] == ')')) { + simpleVarName = 1; + name = varTokenPtr[1].start; + nameChars = varTokenPtr[1].size - 1; + elName = varTokenPtr[2].start; + elNameChars = varTokenPtr[2].size; + } + + 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 ((envPtr->procPtr != NULL) && !hasNsQualifiers) { + localIndex = TclFindCompiledLocal(name, nameChars, + /*create*/ isAssignment, + /*flags*/ ((elName==NULL)? VAR_SCALAR : VAR_ARRAY), + envPtr->procPtr); + } + if (localIndex >= 0) { + maxDepth = 0; + } else { + TclEmitPush(TclRegisterLiteral(envPtr, name, nameChars, + /*onHeap*/ 0), envPtr); + maxDepth = 1; + } + + /* + * Compile the element script, if any. + */ + + if (elName != NULL) { + /* + * Temporarily replace the '(' and ')' by '"'s. + */ + + *(elName-1) = '"'; + *(elName+elNameChars) = '"'; + code = Tcl_ParseCommand(interp, elName-1, elNameChars+2, + /*nested*/ 0, &elemParse); + *(elName-1) = '('; + *(elName+elNameChars) = ')'; + gotElemParse = 1; + if ((code != TCL_OK) || (elemParse.numWords > 1)) { + char buffer[160]; + sprintf(buffer, "\n (parsing index for array \"%.*s\")", + TclMin(nameChars, 100), name); + Tcl_AddObjErrorInfo(interp, buffer, -1); + code = TCL_ERROR; + goto done; + } else if (elemParse.numWords == 1) { + code = TclCompileTokens(interp, elemParse.tokenPtr+1, + elemParse.tokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth += envPtr->maxStackDepth; + } else { + TclEmitPush(TclRegisterLiteral(envPtr, "", 0, + /*alreadyAlloced*/ 0), envPtr); + maxDepth += 1; + } + } + } else { + /* + * The var name isn't simple: compile and push it. + */ + + code = TclCompileTokens(interp, varTokenPtr+1, + varTokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth += envPtr->maxStackDepth; + } + + /* + * If we are doing an assignment, push the new value. + */ + + if (isAssignment) { + valueTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1); + if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { + TclEmitPush(TclRegisterLiteral(envPtr, valueTokenPtr[1].start, + valueTokenPtr[1].size, /*onHeap*/ 0), envPtr); + maxDepth += 1; + } else { + code = TclCompileTokens(interp, valueTokenPtr+1, + valueTokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth += envPtr->maxStackDepth; + } + } + + /* + * Emit instructions to set/get the variable. + */ + + if (simpleVarName) { + if (elName == NULL) { + if (localIndex >= 0) { + 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 { + TclEmitOpcode((isAssignment? + INST_STORE_SCALAR_STK : INST_LOAD_SCALAR_STK), + envPtr); + } + } else { + if (localIndex >= 0) { + if (localIndex <= 255) { + TclEmitInstInt1((isAssignment? + INST_STORE_ARRAY1 : INST_LOAD_ARRAY1), + localIndex, envPtr); + } else { + TclEmitInstInt4((isAssignment? + INST_STORE_ARRAY4 : INST_LOAD_ARRAY4), + localIndex, envPtr); + } + } else { + TclEmitOpcode((isAssignment? + INST_STORE_ARRAY_STK : INST_LOAD_ARRAY_STK), + envPtr); + } + } + } else { + TclEmitOpcode((isAssignment? INST_STORE_STK : INST_LOAD_STK), + envPtr); + } + + done: + if (gotElemParse) { + Tcl_FreeParse(&elemParse); + } + envPtr->maxStackDepth = maxDepth; + return code; +} + +/* + *---------------------------------------------------------------------- + * + * TclCompileWhileCmd -- + * + * Procedure called to compile the "while" command. + * + * Results: + * The return value is a standard Tcl result, which is TCL_OK if + * compilation was successful. If an error occurs then the + * interpreter's result contains a standard error message and TCL_ERROR + * is returned. If compilation failed because the command is too + * complex for TclCompileWhileCmd, TCL_OUT_LINE_COMPILE is returned + * indicating that the while command should be compiled "out of line" + * by emitting code to invoke its command procedure at runtime. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the "while" command. + * + * Side effects: + * Instructions are added to envPtr to execute the "while" command + * at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileWhileCmd(interp, parsePtr, envPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Parse *parsePtr; /* Points to a parse structure for the + * command created by Tcl_ParseCommand. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ +{ + Tcl_Token *testTokenPtr, *bodyTokenPtr; + JumpFixup jumpFalseFixup; + unsigned char *jumpPc; + int testCodeOffset, jumpDist, jumpBackDist, jumpBackOffset; + int range, maxDepth, code; + char buffer[32 + TCL_INTEGER_SPACE]; + + envPtr->maxStackDepth = 0; + maxDepth = 0; + if (parsePtr->numWords != 3) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "wrong # args: should be \"while test command\"", -1); + 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" {}". + */ + + testTokenPtr = parsePtr->tokenPtr + + (parsePtr->tokenPtr->numComponents + 1); + if (testTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { + return TCL_OUT_LINE_COMPILE; + } + + /* + * Create a ExceptionRange record for the loop body. This is used to + * implement break and continue. + */ + + envPtr->exceptDepth++; + envPtr->maxExceptDepth = + TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth); + range = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); + envPtr->exceptArrayPtr[range].continueOffset = + (envPtr->codeNext - envPtr->codeStart); + + /* + * Compile the test expression then emit the conditional jump that + * terminates the while. We already know it's a simple word. + */ + + testCodeOffset = (envPtr->codeNext - envPtr->codeStart); + envPtr->exceptArrayPtr[range].continueOffset = testCodeOffset; + code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + Tcl_AddObjErrorInfo(interp, + "\n (\"while\" test expression)", -1); + } + goto error; + } + maxDepth = envPtr->maxStackDepth; + TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup); + + /* + * Compile the loop body. + */ + + bodyTokenPtr = testTokenPtr + (testTokenPtr->numComponents + 1); + envPtr->exceptArrayPtr[range].codeOffset = + (envPtr->codeNext - envPtr->codeStart); + code = TclCompileCmdWord(interp, bodyTokenPtr+1, + bodyTokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + if (code == TCL_ERROR) { + sprintf(buffer, "\n (\"while\" body line %d)", + interp->errorLine); + Tcl_AddObjErrorInfo(interp, buffer, -1); + } + goto error; + } + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + envPtr->exceptArrayPtr[range].numCodeBytes = + (envPtr->codeNext - envPtr->codeStart) + - envPtr->exceptArrayPtr[range].codeOffset; + TclEmitOpcode(INST_POP, envPtr); + + /* + * Jump back to the test at the top of the loop. Generate a 4 byte jump + * if the distance to the test is > 120 bytes. This is conservative and + * ensures that we won't have to replace this jump if we later need to + * replace the ifFalse jump with a 4 byte jump. + */ + + jumpBackOffset = (envPtr->codeNext - envPtr->codeStart); + jumpBackDist = (jumpBackOffset - testCodeOffset); + if (jumpBackDist > 120) { + TclEmitInstInt4(INST_JUMP4, -jumpBackDist, envPtr); + } else { + TclEmitInstInt1(INST_JUMP1, -jumpBackDist, envPtr); + } + + /* + * Fix the target of the jumpFalse after the test. + */ + + jumpDist = (envPtr->codeNext - envPtr->codeStart) + - jumpFalseFixup.codeOffset; + if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) { + /* + * Update the loop body's starting PC offset since it moved down. + */ + + envPtr->exceptArrayPtr[range].codeOffset += 3; + + /* + * Update the jump back to the test at the top of the loop since it + * also moved down 3 bytes. + */ + + jumpBackOffset += 3; + jumpPc = (envPtr->codeStart + jumpBackOffset); + jumpBackDist += 3; + if (jumpBackDist > 120) { + TclUpdateInstInt4AtPc(INST_JUMP4, -jumpBackDist, jumpPc); + } else { + TclUpdateInstInt1AtPc(INST_JUMP1, -jumpBackDist, jumpPc); + } + } + + /* + * Set the loop's break target. + */ + + envPtr->exceptArrayPtr[range].breakOffset = + (envPtr->codeNext - envPtr->codeStart); + + /* + * The while command's result is an empty string. + */ + + TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr); + if (maxDepth == 0) { + maxDepth = 1; + } + envPtr->maxStackDepth = maxDepth; + envPtr->exceptDepth--; + return TCL_OK; + + error: + envPtr->maxStackDepth = maxDepth; + envPtr->exceptDepth--; + return code; +} + + + Index: generic/tclCompExpr.c ================================================================== --- generic/tclCompExpr.c +++ generic/tclCompExpr.c @@ -1,16 +1,16 @@ /* * tclCompExpr.c -- * * This file contains the code to compile Tcl expressions. * - * Copyright (c) 1996-1997 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclCompExpr.c 1.34 97/11/03 14:29:18 + * RCS: @(#) $Id: tclCompExpr.c,v 1.1.2.7 1998/12/12 01:36:54 lfb Exp $ */ #include "tclInt.h" #include "tclCompile.h" @@ -35,35 +35,26 @@ * Boolean variable that controls whether expression compilation tracing * is enabled. */ #ifdef TCL_COMPILE_DEBUG -static int traceCompileExpr = 0; +static int traceExprComp = 0; #endif /* TCL_COMPILE_DEBUG */ /* * The ExprInfo structure describes the state of compiling an expression. * A pointer to an ExprInfo record is passed among the routines in * this module. */ typedef struct ExprInfo { - int token; /* Type of the last token parsed in expr. - * See below for definitions. Corresponds - * to the characters just before next. */ - int objIndex; /* If token is a literal value, the index of - * an object holding the value in the code's - * object table; otherwise is NULL. */ - char *funcName; /* If the token is FUNC_NAME, points to the - * first character of the math function's - * name; otherwise is NULL. */ - char *next; /* Position of the next character to be - * scanned in the expression string. */ - char *originalExpr; /* The entire expression that was originally - * passed to Tcl_ExprString et al. */ - char *lastChar; /* Pointer to terminating null in - * originalExpr. */ + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Parse *parsePtr; /* Structure filled with information about + * the parsed expression. */ + char *expr; /* The expression that was originally passed + * to TclCompileExpr. */ + char *lastChar; /* Points just after last byte of expr. */ int hasOperators; /* Set 1 if the expr has operators; 0 if * expr is only a primary. If 1 after * compiling an expr, a tryCvtToNumeric * instruction is emitted to convert the * primary to a number if possible. */ @@ -80,139 +71,120 @@ * to implement expr's 2 level substitution * semantics properly. */ } ExprInfo; /* - * Definitions of the different tokens that appear in expressions. The order - * of these must match the corresponding entries in the operatorStrings - * array below. - */ - -#define LITERAL 0 -#define FUNC_NAME (LITERAL + 1) -#define OPEN_BRACKET (LITERAL + 2) -#define CLOSE_BRACKET (LITERAL + 3) -#define OPEN_PAREN (LITERAL + 4) -#define CLOSE_PAREN (LITERAL + 5) -#define DOLLAR (LITERAL + 6) -#define QUOTE (LITERAL + 7) -#define COMMA (LITERAL + 8) -#define END (LITERAL + 9) -#define UNKNOWN (LITERAL + 10) - -/* - * Binary operators: - */ - -#define MULT (UNKNOWN + 1) -#define DIVIDE (MULT + 1) -#define MOD (MULT + 2) -#define PLUS (MULT + 3) -#define MINUS (MULT + 4) -#define LEFT_SHIFT (MULT + 5) -#define RIGHT_SHIFT (MULT + 6) -#define LESS (MULT + 7) -#define GREATER (MULT + 8) -#define LEQ (MULT + 9) -#define GEQ (MULT + 10) -#define EQUAL (MULT + 11) -#define NEQ (MULT + 12) -#define BIT_AND (MULT + 13) -#define BIT_XOR (MULT + 14) -#define BIT_OR (MULT + 15) -#define AND (MULT + 16) -#define OR (MULT + 17) -#define QUESTY (MULT + 18) -#define COLON (MULT + 19) - -/* - * Unary operators. Unary minus and plus are represented by the (binary) - * tokens MINUS and PLUS. - */ - -#define NOT (COLON + 1) -#define BIT_NOT (NOT + 1) - -/* - * Mapping from tokens to strings; used for debugging messages. These - * entries must match the order and number of the token definitions above. - */ - -#ifdef TCL_COMPILE_DEBUG -static char *tokenStrings[] = { - "LITERAL", "FUNCNAME", - "[", "]", "(", ")", "$", "\"", ",", "END", "UNKNOWN", - "*", "/", "%", "+", "-", - "<<", ">>", "<", ">", "<=", ">=", "==", "!=", - "&", "^", "|", "&&", "||", "?", ":", - "!", "~" + * Definitions of numeric codes representing each expression operator. + * The order of these must match the entries in the operatorTable below. + * Also the codes for the relational operators (OP_LESS, OP_GREATER, + * OP_LE, OP_GE, OP_EQ, and OP_NE) must be consecutive and in that order. + * Note that OP_PLUS and OP_MINUS represent both unary and binary operators. + */ + +#define OP_MULT 0 +#define OP_DIVIDE 1 +#define OP_MOD 2 +#define OP_PLUS 3 +#define OP_MINUS 4 +#define OP_LSHIFT 5 +#define OP_RSHIFT 6 +#define OP_LESS 7 +#define OP_GREATER 8 +#define OP_LE 9 +#define OP_GE 10 +#define OP_EQ 11 +#define OP_NEQ 12 +#define OP_BITAND 13 +#define OP_BITXOR 14 +#define OP_BITOR 15 +#define OP_LAND 16 +#define OP_LOR 17 +#define OP_QUESTY 18 +#define OP_LNOT 19 +#define OP_BITNOT 20 + +/* + * Table describing the expression operators. Entries in this table must + * correspond to the definitions of numeric codes for operators just above. + */ + +static int opTableInitialized = 0; /* 0 means not yet initialized. */ + +TCL_DECLARE_MUTEX(opMutex) + +typedef struct OperatorDesc { + char *name; /* Name of the operator. */ + int numOperands; /* Number of operands. 0 if the operator + * requires special handling. */ + int instruction; /* Instruction opcode for the operator. + * Ignored if numOperands is 0. */ +} OperatorDesc; + +OperatorDesc operatorTable[] = { + {"*", 2, INST_MULT}, + {"/", 2, INST_DIV}, + {"%", 2, INST_MOD}, + {"+", 0}, + {"-", 0}, + {"<<", 2, INST_LSHIFT}, + {">>", 2, INST_RSHIFT}, + {"<", 2, INST_LT}, + {">", 2, INST_GT}, + {"<=", 2, INST_LE}, + {">=", 2, INST_GE}, + {"==", 2, INST_EQ}, + {"!=", 2, INST_NEQ}, + {"&", 2, INST_BITAND}, + {"^", 2, INST_BITXOR}, + {"|", 2, INST_BITOR}, + {"&&", 0}, + {"||", 0}, + {"?", 0}, + {"!", 1, INST_LNOT}, + {"~", 1, INST_BITNOT}, + {NULL} }; -#endif /* TCL_COMPILE_DEBUG */ + +/* + * Hashtable used to map the names of expression operators to the index + * of their OperatorDesc description. + */ + +static Tcl_HashTable opHashTable; /* * Declarations for local procedures to this file: */ -static int CompileAddExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompileBitAndExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompileBitOrExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompileBitXorExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompileCondExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompileEqualityExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompileLandExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompileLorExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompileMathFuncCall _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompileMultiplyExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompilePrimaryExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompileRelationalExpr _ANSI_ARGS_(( - Tcl_Interp *interp, ExprInfo *infoPtr, - int flags, CompileEnv *envPtr)); -static int CompileShiftExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int CompileUnaryExpr _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, int flags, - CompileEnv *envPtr)); -static int GetToken _ANSI_ARGS_((Tcl_Interp *interp, - ExprInfo *infoPtr, CompileEnv *envPtr)); - -/* - * Macro used to debug the execution of the recursive descent parser used - * to compile expressions. +static int CompileCondExpr _ANSI_ARGS_(( + Tcl_Token *exprTokenPtr, ExprInfo *infoPtr, + CompileEnv *envPtr, Tcl_Token **endPtrPtr)); +static int CompileLandOrLorExpr _ANSI_ARGS_(( + Tcl_Token *exprTokenPtr, int opIndex, + ExprInfo *infoPtr, CompileEnv *envPtr, + Tcl_Token **endPtrPtr)); +static int CompileMathFuncCall _ANSI_ARGS_(( + Tcl_Token *exprTokenPtr, char *funcName, + ExprInfo *infoPtr, CompileEnv *envPtr, + Tcl_Token **endPtrPtr)); +static int CompileSubExpr _ANSI_ARGS_(( + Tcl_Token *exprTokenPtr, ExprInfo *infoPtr, + CompileEnv *envPtr)); +static void LogSyntaxError _ANSI_ARGS_((ExprInfo *infoPtr)); + +/* + * Macro used to debug the execution of the expression compiler. */ #ifdef TCL_COMPILE_DEBUG -#define HERE(production, level) \ - if (traceCompileExpr) { \ - fprintf(stderr, "%*s%s: token=%s, next=\"%.20s\"\n", \ - (level), " ", (production), tokenStrings[infoPtr->token], \ - infoPtr->next); \ +#define TRACE(exprBytes, exprLength, tokenBytes, tokenLength) \ + if (traceExprComp) { \ + fprintf(stderr, "CompileSubExpr: \"%.*s\", token \"%.*s\"\n", \ + (exprLength), (exprBytes), (tokenLength), (tokenBytes)); \ } #else -#define HERE(production, level) +#define TRACE(exprBytes, exprLength, tokenBytes, tokenLength) #endif /* TCL_COMPILE_DEBUG */ /* *---------------------------------------------------------------------- * @@ -222,27 +194,15 @@ * Tcl bytecodes. This procedure is the top-level interface to the * the expression compilation module, and is used by such public * procedures as Tcl_ExprString, Tcl_ExprStringObj, Tcl_ExprLong, * Tcl_ExprDouble, Tcl_ExprBoolean, and Tcl_ExprBooleanObj. * - * Note that the topmost recursive-descent parsing routine used by - * TclCompileExpr to compile expressions is called "CompileCondExpr" - * and not, e.g., "CompileExpr". This is done to avoid an extra - * procedure call since such a procedure would only return the result - * of calling CompileCondExpr. Other recursive-descent procedures - * that need to parse expressions also call CompileCondExpr. - * * 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. * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed; this might - * be the offset of the ']' (if flags & TCL_BRACKET_TERM), or the - * offset of the '\0' at the end of the string. - * * envPtr->maxStackDepth is updated with the maximum number of stack * elements needed to execute the expression. * * envPtr->exprIsJustVarRef is set 1 if the expression consisted of * a single variable reference as in the expression of "if $b then...". @@ -259,89 +219,77 @@ * *---------------------------------------------------------------------- */ int -TclCompileExpr(interp, string, lastChar, flags, envPtr) +TclCompileExpr(interp, script, numBytes, envPtr) Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ + char *script; /* The source script to compile. */ + int numBytes; /* Number of bytes in script. If < 0, the + * string consists of all bytes up to the + * first null character. */ CompileEnv *envPtr; /* Holds resulting instructions. */ { - Interp *iPtr = (Interp *) interp; ExprInfo info; - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int result; - -#ifdef TCL_COMPILE_DEBUG - if (traceCompileExpr) { - fprintf(stderr, "expr: string=\"%.30s\"\n", string); - } -#endif /* TCL_COMPILE_DEBUG */ - - /* - * Register the builtin math functions the first time an expression is - * compiled. - */ - - if (!(iPtr->flags & EXPR_INITIALIZED)) { - BuiltinFunc *funcPtr; - Tcl_HashEntry *hPtr; - MathFunc *mathFuncPtr; - int i; - - iPtr->flags |= EXPR_INITIALIZED; - i = 0; - for (funcPtr = builtinFuncTable; funcPtr->name != NULL; funcPtr++) { - Tcl_CreateMathFunc(interp, funcPtr->name, - funcPtr->numArgs, funcPtr->argTypes, - (Tcl_MathProc *) NULL, (ClientData) 0); - - hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcPtr->name); - if (hPtr == NULL) { - panic("TclCompileExpr: Tcl_CreateMathFunc incorrectly registered '%s'", funcPtr->name); - return TCL_ERROR; - } - mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr); - mathFuncPtr->builtinFuncIndex = i; - i++; - } - } - - info.token = UNKNOWN; - info.objIndex = -1; - info.funcName = NULL; - info.next = string; - info.originalExpr = string; - info.lastChar = lastChar; + Tcl_Parse parse; + Tcl_HashEntry *hPtr; + int maxDepth, new, i, code; + + /* + * If this is the first time we've been called, initialize the table + * of expression operators. + */ + + if (numBytes < 0) { + numBytes = (script? strlen(script) : 0); + } + if (!opTableInitialized) { + Tcl_MutexLock(&opMutex); + if (!opTableInitialized) { + Tcl_InitHashTable(&opHashTable, TCL_STRING_KEYS); + for (i = 0; operatorTable[i].name != NULL; i++) { + hPtr = Tcl_CreateHashEntry(&opHashTable, + operatorTable[i].name, &new); + if (new) { + Tcl_SetHashValue(hPtr, (ClientData) i); + } + } + opTableInitialized = 1; + } + Tcl_MutexUnlock(&opMutex); + } + + /* + * Initialize the structure containing information abvout this + * expression compilation. + */ + + info.interp = interp; + info.parsePtr = &parse; + info.expr = script; + info.lastChar = (script + numBytes); info.hasOperators = 0; info.exprIsJustVarRef = 1; /* will be set 0 if anything else is seen */ - info.exprIsComparison = 0; /* set 1 if topmost operator is <,==,etc. */ - - /* - * Get the first token then compile an expression. - */ - - result = GetToken(interp, &info, envPtr); - if (result != TCL_OK) { - goto done; - } - - result = CompileCondExpr(interp, &info, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - if (info.token != END) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "syntax error in expression \"", string, "\"", (char *) NULL); - result = TCL_ERROR; - goto done; - } + info.exprIsComparison = 0; + + /* + * Parse the expression then compile it. + */ + + maxDepth = 0; + code = Tcl_ParseExpr(interp, script, numBytes, &parse); + if (code != TCL_OK) { + goto done; + } + + code = CompileSubExpr(parse.tokenPtr, &info, envPtr); + if (code != TCL_OK) { + Tcl_FreeParse(&parse); + goto done; + } + maxDepth = envPtr->maxStackDepth; + if (!info.hasOperators) { /* * Attempt to convert the primary's object to an int or double. * This is done in order to support Tcl's policy of interpreting * operands if at all possible as first integers, else @@ -348,361 +296,361 @@ * floating-point numbers. */ TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr); } - maxDepth = envPtr->maxStackDepth; - - done: - envPtr->termOffset = (info.next - string); - envPtr->maxStackDepth = maxDepth; - envPtr->exprIsJustVarRef = info.exprIsJustVarRef; - envPtr->exprIsComparison = info.exprIsComparison; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileCondExpr -- - * - * This procedure compiles a Tcl conditional expression: - * condExpr ::= lorExpr ['?' condExpr ':' condExpr] - * - * Note that this is the topmost recursive-descent parsing routine used - * by TclCompileExpr to compile expressions. It does not call an - * separate, higher-level "CompileExpr" procedure. This avoids an extra - * procedure call since such a procedure would only return the result - * of calling CompileCondExpr. Other recursive-descent procedures that - * need to parse expressions also call CompileCondExpr. - * - * 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. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the expression. - * - * Side effects: - * Adds instructions to envPtr to evaluate the expression at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileCondExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - JumpFixup jumpAroundThenFixup, jumpAroundElseFixup; - /* Used to update or replace one-byte jumps - * around the then and else expressions when - * their target PCs are determined. */ - int elseCodeOffset, currCodeOffset, jumpDist, result; - - HERE("condExpr", 1); - result = CompileLorExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - - if (infoPtr->token == QUESTY) { - result = GetToken(interp, infoPtr, envPtr); /* skip over the '?' */ - if (result != TCL_OK) { - goto done; - } - - /* - * Emit the jump around the "then" clause to the "else" condExpr if - * the test was false. We emit a one byte (relative) jump here, and - * replace it later with a four byte jump if the jump target is more - * than 127 bytes away. - */ - - TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpAroundThenFixup); - - /* - * Compile the "then" expression. Note that if a subexpression - * is only a primary, we need to try to convert it to numeric. - * This is done in order to support Tcl's policy of interpreting - * operands if at all possible as first integers, else - * floating-point numbers. - */ - - infoPtr->hasOperators = 0; - infoPtr->exprIsJustVarRef = 0; - infoPtr->exprIsComparison = 0; - result = CompileCondExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - if (infoPtr->token != COLON) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "syntax error in expression \"", infoPtr->originalExpr, - "\"", (char *) NULL); - result = TCL_ERROR; - goto done; - } - if (!infoPtr->hasOperators) { - TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr); - } - result = GetToken(interp, infoPtr, envPtr); /* skip over the ':' */ - if (result != TCL_OK) { - goto done; - } - - /* - * Emit an unconditional jump around the "else" condExpr. - */ - - TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, - &jumpAroundElseFixup); - - /* - * Compile the "else" expression. - */ - - infoPtr->hasOperators = 0; - elseCodeOffset = TclCurrCodeOffset(); - result = CompileCondExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - if (!infoPtr->hasOperators) { - TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr); - } - - /* - * Fix up the second jump: the unconditional jump around the "else" - * expression. If the distance is too great (> 127 bytes), replace - * it with a four byte instruction and move the instructions after - * the jump down. - */ - - currCodeOffset = TclCurrCodeOffset(); - jumpDist = (currCodeOffset - jumpAroundElseFixup.codeOffset); - if (TclFixupForwardJump(envPtr, &jumpAroundElseFixup, jumpDist, 127)) { - /* - * Update the else expression's starting code offset since it - * moved down 3 bytes too. - */ - - elseCodeOffset += 3; - } - - /* - * Now fix up the first branch: the jumpFalse after the test. If the - * distance is too great, replace it with a four byte instruction - * and update the code offsets for the commands in both the "then" - * and "else" expressions. - */ - - jumpDist = (elseCodeOffset - jumpAroundThenFixup.codeOffset); - TclFixupForwardJump(envPtr, &jumpAroundThenFixup, jumpDist, 127); - - infoPtr->hasOperators = 1; - - /* - * A comparison is not the top-level operator in this expression. - */ - - infoPtr->exprIsComparison = 0; - } - - done: - envPtr->maxStackDepth = maxDepth; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileLorExpr -- - * - * This procedure compiles a Tcl logical or expression: - * lorExpr ::= landExpr {'||' landExpr} + Tcl_FreeParse(&parse); + + done: + envPtr->maxStackDepth = maxDepth; + envPtr->exprIsJustVarRef = info.exprIsJustVarRef; + envPtr->exprIsComparison = info.exprIsComparison; + return code; +} + +/* + *---------------------------------------------------------------------- + * + * TclFinalizeCompilation -- + * + * Clean up the compilation environment so it can later be + * properly reinitialized. This procedure is called by + * TclFinalizeCompExecEnv() in tclObj.c, which in turn is called + * by Tcl_Finalize(). + * + * Results: + * None. + * + * Side effects: + * Cleans up the compilation environment. At the moment, just the + * table of expression operators is freed. + * + *---------------------------------------------------------------------- + */ + +void +TclFinalizeCompilation() +{ + Tcl_MutexLock(&opMutex); + if (opTableInitialized) { + Tcl_DeleteHashTable(&opHashTable); + opTableInitialized = 0; + } + Tcl_MutexUnlock(&opMutex); +} + +/* + *---------------------------------------------------------------------- + * + * CompileSubExpr -- + * + * Given a pointer to a TCL_TOKEN_SUB_EXPR token describing a + * subexpression, this procedure emits instructions to evaluate the + * subexpression at runtime. * * 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. * * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the expression. + * elements needed to execute the subexpression. + * + * envPtr->exprIsJustVarRef is set 1 if the subexpression consisted of + * a single variable reference as in the expression of "if $b then...". + * Otherwise it is set 0. This is used to implement Tcl's two level + * expression substitution semantics properly. + * + * envPtr->exprIsComparison is set 1 if the top-level operator in the + * subexpression is a comparison. Otherwise it is set 0. If 1, because + * the operands might be strings, the expr is compiled out-of-line in + * order to implement expr's 2 level substitution semantics properly. * * Side effects: - * Adds instructions to envPtr to evaluate the expression at runtime. + * Adds instructions to envPtr to evaluate the subexpression. * *---------------------------------------------------------------------- */ static int -CompileLorExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ +CompileSubExpr(exprTokenPtr, infoPtr, envPtr) + Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token + * to compile. */ ExprInfo *infoPtr; /* Describes the compilation state for the * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ CompileEnv *envPtr; /* Holds resulting instructions. */ { - int maxDepth; /* Maximum number of stack elements needed - * to execute the expression. */ - JumpFixupArray jumpFixupArray; - /* Used to fix up the forward "short - * circuit" jump after each or-ed - * subexpression to just after the last - * subexpression. */ - JumpFixup jumpTrueFixup, jumpFixup; - /* Used to emit the jumps in the code to - * convert the first operand to a 0 or 1. */ - int fixupIndex, jumpDist, currCodeOffset, objIndex, j, result; - Tcl_Obj *objPtr; - - HERE("lorExpr", 2); - result = CompileLandExpr(interp, infoPtr, flags, envPtr); - if ((result != TCL_OK) || (infoPtr->token != OR)) { - return result; /* envPtr->maxStackDepth is already set */ - } - - infoPtr->hasOperators = 1; - infoPtr->exprIsJustVarRef = 0; - maxDepth = envPtr->maxStackDepth; - TclInitJumpFixupArray(&jumpFixupArray); - while (infoPtr->token == OR) { - result = GetToken(interp, infoPtr, envPtr); /* skip over the '||' */ - if (result != TCL_OK) { - goto done; - } - - if (jumpFixupArray.next == 0) { - /* - * Just the first "lor" operand is on the stack. The following - * is slightly ugly: we need to convert that first "lor" operand - * to a "0" or "1" to get the correct result if it is nonzero. - * Eventually we'll use a new instruction for this. - */ - - TclEmitForwardJump(envPtr, TCL_TRUE_JUMP, &jumpTrueFixup); - - objIndex = TclObjIndexForString("0", 1, /*allocStrRep*/ 0, - /*inHeap*/ 0, envPtr); - objPtr = envPtr->objArrayPtr[objIndex]; - - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.longValue = 0; - objPtr->typePtr = &tclIntType; - - TclEmitPush(objIndex, envPtr); - TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); - - jumpDist = (TclCurrCodeOffset() - jumpTrueFixup.codeOffset); - if (TclFixupForwardJump(envPtr, &jumpTrueFixup, jumpDist, 127)) { - panic("CompileLorExpr: bad jump distance %d\n", jumpDist); - } - objIndex = TclObjIndexForString("1", 1, /*allocStrRep*/ 0, - /*inHeap*/ 0, envPtr); - objPtr = envPtr->objArrayPtr[objIndex]; - - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.longValue = 1; - objPtr->typePtr = &tclIntType; - - TclEmitPush(objIndex, envPtr); - - jumpDist = (TclCurrCodeOffset() - jumpFixup.codeOffset); - if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) { - panic("CompileLorExpr: bad jump distance %d\n", jumpDist); - } - } - - /* - * Duplicate the value on top of the stack to prevent the jump from - * consuming it. - */ - - TclEmitOpcode(INST_DUP, envPtr); - - /* - * Emit the "short circuit" jump around the rest of the lorExp if - * the previous expression was true. We emit a one byte (relative) - * jump here, and replace it later with a four byte jump if the jump - * target is more than 127 bytes away. - */ - - if (jumpFixupArray.next == jumpFixupArray.end) { - TclExpandJumpFixupArray(&jumpFixupArray); - } - fixupIndex = jumpFixupArray.next; - jumpFixupArray.next++; - TclEmitForwardJump(envPtr, TCL_TRUE_JUMP, - &(jumpFixupArray.fixup[fixupIndex])); - - /* - * Compile the subexpression. - */ - - result = CompileLandExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); - - /* - * Emit a "logical or" instruction. This does not try to "short- - * circuit" the evaluation of both operands of a Tcl "||" operator, - * but instead ensures that we either have a "1" or a "0" result. - */ - - TclEmitOpcode(INST_LOR, envPtr); - } - - /* - * Now that we know the target of the forward jumps, update the jumps - * with the correct distance. Also, if the distance is too great (> 127 - * bytes), replace the jump with a four byte instruction and move the - * instructions after the jump down. - */ - - for (j = jumpFixupArray.next; j > 0; j--) { - fixupIndex = (j - 1); /* process closest jump first */ - currCodeOffset = TclCurrCodeOffset(); - jumpDist = (currCodeOffset - jumpFixupArray.fixup[fixupIndex].codeOffset); - TclFixupForwardJump(envPtr, &(jumpFixupArray.fixup[fixupIndex]), jumpDist, 127); - } - - /* - * We get here only if one or more ||'s appear as top-level operators. - */ - - done: - infoPtr->exprIsComparison = 0; - TclFreeJumpFixupArray(&jumpFixupArray); - envPtr->maxStackDepth = maxDepth; - return result; + Tcl_Interp *interp = infoPtr->interp; + Tcl_Token *tokenPtr, *endPtr, *afterSubexprPtr; + OperatorDesc *opDescPtr; + Tcl_HashEntry *hPtr; + char *operator; + char savedChar; + int maxDepth, objIndex, opIndex, length, code; + char buffer[TCL_UTF_MAX]; + + if (exprTokenPtr->type != TCL_TOKEN_SUB_EXPR) { + panic("CompileSubExpr: token type %d not TCL_TOKEN_SUB_EXPR\n", + exprTokenPtr->type); + } + maxDepth = 0; + code = TCL_OK; + + /* + * Switch on the type of the first token after the subexpression token. + * After processing it, advance tokenPtr to point just after the + * subexpression's last token. + */ + + tokenPtr = exprTokenPtr+1; + TRACE(exprTokenPtr->start, exprTokenPtr->size, + tokenPtr->start, tokenPtr->size); + switch (tokenPtr->type) { + case TCL_TOKEN_WORD: + code = TclCompileTokens(interp, tokenPtr+1, + tokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + tokenPtr += (tokenPtr->numComponents + 1); + infoPtr->exprIsJustVarRef = 0; + break; + + case TCL_TOKEN_TEXT: + if (tokenPtr->size > 0) { + objIndex = TclRegisterLiteral(envPtr, tokenPtr->start, + tokenPtr->size, /*onHeap*/ 0); + } else { + objIndex = TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0); + } + TclEmitPush(objIndex, envPtr); + maxDepth = 1; + tokenPtr += 1; + infoPtr->exprIsJustVarRef = 0; + break; + + case TCL_TOKEN_BS: + length = Tcl_UtfBackslash(tokenPtr->start, (int *) NULL, + buffer); + if (length > 0) { + objIndex = TclRegisterLiteral(envPtr, buffer, length, + /*onHeap*/ 0); + } else { + objIndex = TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0); + } + TclEmitPush(objIndex, envPtr); + maxDepth = 1; + tokenPtr += 1; + infoPtr->exprIsJustVarRef = 0; + break; + + case TCL_TOKEN_COMMAND: + code = TclCompileScript(interp, tokenPtr->start+1, + tokenPtr->size-2, /*nested*/ 1, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + tokenPtr += 1; + infoPtr->exprIsJustVarRef = 0; + break; + + case TCL_TOKEN_VARIABLE: + code = TclCompileTokens(interp, tokenPtr, 1, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + tokenPtr += (tokenPtr->numComponents + 1); + break; + + case TCL_TOKEN_SUB_EXPR: + infoPtr->exprIsComparison = 0; + code = CompileSubExpr(tokenPtr, infoPtr, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + tokenPtr += (tokenPtr->numComponents + 1); + break; + + case TCL_TOKEN_OPERATOR: + /* + * Look up the operator. Temporarily overwrite the character + * just after the end of the operator with a 0 byte. If the + * operator isn't found, treat it as a math function. + */ + + /* + * TODO: Note that the string is modified in place. This is unsafe + * and will break if any of the routines called while the string is + * modified have side effects that depend on the original string + * being unmodified (e.g. adding an entry to the literal table). + */ + + operator = tokenPtr->start; + savedChar = operator[tokenPtr->size]; + operator[tokenPtr->size] = 0; + hPtr = Tcl_FindHashEntry(&opHashTable, operator); + if (hPtr == NULL) { + code = CompileMathFuncCall(exprTokenPtr, operator, infoPtr, + envPtr, &endPtr); + operator[tokenPtr->size] = (char) savedChar; + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + tokenPtr = endPtr; + infoPtr->exprIsJustVarRef = 0; + infoPtr->exprIsComparison = 0; + break; + } + operator[tokenPtr->size] = (char) savedChar; + opIndex = (int) Tcl_GetHashValue(hPtr); + opDescPtr = &(operatorTable[opIndex]); + + /* + * If the operator is "normal", compile it using information + * from the operator table. + */ + + if (opDescPtr->numOperands > 0) { + tokenPtr++; + code = CompileSubExpr(tokenPtr, infoPtr, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + tokenPtr += (tokenPtr->numComponents + 1); + + if (opDescPtr->numOperands == 2) { + code = CompileSubExpr(tokenPtr, infoPtr, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = TclMax((envPtr->maxStackDepth + 1), + maxDepth); + tokenPtr += (tokenPtr->numComponents + 1); + } + TclEmitOpcode(opDescPtr->instruction, envPtr); + infoPtr->hasOperators = 1; + infoPtr->exprIsJustVarRef = 0; + infoPtr->exprIsComparison = + ((opIndex >= OP_LESS) && (opIndex <= OP_NEQ)); + break; + } + + /* + * The operator requires special treatment, and is either + * "+" or "-", or one of "&&", "||" or "?". + */ + + switch (opIndex) { + case OP_PLUS: + case OP_MINUS: + tokenPtr++; + code = CompileSubExpr(tokenPtr, infoPtr, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + tokenPtr += (tokenPtr->numComponents + 1); + + /* + * Check whether the "+" or "-" is unary. + */ + + afterSubexprPtr = exprTokenPtr + + exprTokenPtr->numComponents+1; + if (tokenPtr == afterSubexprPtr) { + TclEmitOpcode(((opIndex==OP_PLUS)? + INST_UPLUS : INST_UMINUS), + envPtr); + break; + } + + /* + * The "+" or "-" is binary. + */ + + code = CompileSubExpr(tokenPtr, infoPtr, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = TclMax((envPtr->maxStackDepth + 1), + maxDepth); + tokenPtr += (tokenPtr->numComponents + 1); + TclEmitOpcode(((opIndex==OP_PLUS)? INST_ADD : INST_SUB), + envPtr); + break; + + case OP_LAND: + case OP_LOR: + code = CompileLandOrLorExpr(exprTokenPtr, opIndex, + infoPtr, envPtr, &endPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + tokenPtr = endPtr; + break; + + case OP_QUESTY: + code = CompileCondExpr(exprTokenPtr, infoPtr, + envPtr, &endPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + tokenPtr = endPtr; + break; + + default: + panic("CompileSubExpr: unexpected operator %d requiring special treatment\n", + opIndex); + } /* end switch on operator requiring special treatment */ + infoPtr->hasOperators = 1; + infoPtr->exprIsJustVarRef = 0; + infoPtr->exprIsComparison = 0; + break; + + default: + panic("CompileSubExpr: unexpected token type %d\n", + tokenPtr->type); + } + + /* + * Verify that the subexpression token had the required number of + * subtokens: that we've advanced tokenPtr just beyond the + * subexpression's last token. For example, a "*" subexpression must + * contain the tokens for exactly two operands. + */ + + if (tokenPtr != (exprTokenPtr + exprTokenPtr->numComponents+1)) { + LogSyntaxError(infoPtr); + code = TCL_ERROR; + } + + done: + envPtr->maxStackDepth = maxDepth; + return code; } /* *---------------------------------------------------------------------- * - * CompileLandExpr -- + * CompileLandOrLorExpr -- * - * This procedure compiles a Tcl logical and expression: - * landExpr ::= bitOrExpr {'&&' bitOrExpr} + * This procedure compiles a Tcl logical and ("&&") or logical or + * ("||") subexpression. * * 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 + * on failure. If TCL_OK is returned, a pointer to the token just after + * the last one in the subexpression is stored at the address in + * endPtrPtr. If TCL_ERROR is returned, then the interpreter's result * contains an error message. * * envPtr->maxStackDepth is updated with the maximum number of stack * elements needed to execute the expression. * @@ -711,166 +659,120 @@ * *---------------------------------------------------------------------- */ static int -CompileLandExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth; /* Maximum number of stack elements needed - * to execute the expression. */ - JumpFixupArray jumpFixupArray; - /* Used to fix up the forward "short - * circuit" jump after each and-ed - * subexpression to just after the last - * subexpression. */ - JumpFixup jumpTrueFixup, jumpFixup; - /* Used to emit the jumps in the code to - * convert the first operand to a 0 or 1. */ - int fixupIndex, jumpDist, currCodeOffset, objIndex, j, result; - Tcl_Obj *objPtr; - - HERE("landExpr", 3); - result = CompileBitOrExpr(interp, infoPtr, flags, envPtr); - if ((result != TCL_OK) || (infoPtr->token != AND)) { - return result; /* envPtr->maxStackDepth is already set */ - } - - infoPtr->hasOperators = 1; - infoPtr->exprIsJustVarRef = 0; - maxDepth = envPtr->maxStackDepth; - TclInitJumpFixupArray(&jumpFixupArray); - while (infoPtr->token == AND) { - result = GetToken(interp, infoPtr, envPtr); /* skip over the '&&' */ - if (result != TCL_OK) { - goto done; - } - - if (jumpFixupArray.next == 0) { - /* - * Just the first "land" operand is on the stack. The following - * is slightly ugly: we need to convert the first "land" operand - * to a "0" or "1" to get the correct result if it is - * nonzero. Eventually we'll use a new instruction. - */ - - TclEmitForwardJump(envPtr, TCL_TRUE_JUMP, &jumpTrueFixup); - - objIndex = TclObjIndexForString("0", 1, /*allocStrRep*/ 0, - /*inHeap*/ 0, envPtr); - objPtr = envPtr->objArrayPtr[objIndex]; - - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.longValue = 0; - objPtr->typePtr = &tclIntType; - - TclEmitPush(objIndex, envPtr); - TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); - - jumpDist = (TclCurrCodeOffset() - jumpTrueFixup.codeOffset); - if (TclFixupForwardJump(envPtr, &jumpTrueFixup, jumpDist, 127)) { - panic("CompileLandExpr: bad jump distance %d\n", jumpDist); - } - objIndex = TclObjIndexForString("1", 1, /*allocStrRep*/ 0, - /*inHeap*/ 0, envPtr); - objPtr = envPtr->objArrayPtr[objIndex]; - - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.longValue = 1; - objPtr->typePtr = &tclIntType; - - TclEmitPush(objIndex, envPtr); - - jumpDist = (TclCurrCodeOffset() - jumpFixup.codeOffset); - if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) { - panic("CompileLandExpr: bad jump distance %d\n", jumpDist); - } - } - - /* - * Duplicate the value on top of the stack to prevent the jump from - * consuming it. - */ - - TclEmitOpcode(INST_DUP, envPtr); - - /* - * Emit the "short circuit" jump around the rest of the landExp if - * the previous expression was false. We emit a one byte (relative) - * jump here, and replace it later with a four byte jump if the jump - * target is more than 127 bytes away. - */ - - if (jumpFixupArray.next == jumpFixupArray.end) { - TclExpandJumpFixupArray(&jumpFixupArray); - } - fixupIndex = jumpFixupArray.next; - jumpFixupArray.next++; - TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, - &(jumpFixupArray.fixup[fixupIndex])); - - /* - * Compile the subexpression. - */ - - result = CompileBitOrExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); - - /* - * Emit a "logical and" instruction. This does not try to "short- - * circuit" the evaluation of both operands of a Tcl "&&" operator, - * but instead ensures that we either have a "1" or a "0" result. - */ - - TclEmitOpcode(INST_LAND, envPtr); - } - - /* - * Now that we know the target of the forward jumps, update the jumps - * with the correct distance. Also, if the distance is too great (> 127 - * bytes), replace the jump with a four byte instruction and move the - * instructions after the jump down. - */ - - for (j = jumpFixupArray.next; j > 0; j--) { - fixupIndex = (j - 1); /* process closest jump first */ - currCodeOffset = TclCurrCodeOffset(); - jumpDist = (currCodeOffset - jumpFixupArray.fixup[fixupIndex].codeOffset); - TclFixupForwardJump(envPtr, &(jumpFixupArray.fixup[fixupIndex]), - jumpDist, 127); - } - - /* - * We get here only if one or more &&'s appear as top-level operators. - */ +CompileLandOrLorExpr(exprTokenPtr, opIndex, infoPtr, envPtr, endPtrPtr) + Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token + * containing the "&&" or "||" operator. */ + int opIndex; /* A code describing the expression + * operator: either OP_LAND or OP_LOR. */ + ExprInfo *infoPtr; /* Describes the compilation state for the + * expression being compiled. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ + Tcl_Token **endPtrPtr; /* If successful, a pointer to the token + * just after the last token in the + * subexpression is stored here. */ +{ + JumpFixup shortCircuitFixup; /* Used to fix up the short circuit jump + * after the first subexpression. */ + JumpFixup lhsTrueFixup, lhsEndFixup; + /* Used to fix up jumps used to convert the + * first operand to 0 or 1. */ + Tcl_Token *tokenPtr; + int dist, maxDepth, code; + + /* + * Emit code for the first operand. + */ + + maxDepth = 0; + tokenPtr = exprTokenPtr+2; + code = CompileSubExpr(tokenPtr, infoPtr, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + tokenPtr += (tokenPtr->numComponents + 1); + + /* + * Convert the first operand to the result that Tcl requires: + * "0" or "1". Eventually we'll use a new instruction for this. + */ + + TclEmitForwardJump(envPtr, TCL_TRUE_JUMP, &lhsTrueFixup); + TclEmitPush(TclRegisterLiteral(envPtr, "0", 1, /*onHeap*/ 0), envPtr); + TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &lhsEndFixup); + dist = (envPtr->codeNext - envPtr->codeStart) - lhsTrueFixup.codeOffset; + if (TclFixupForwardJump(envPtr, &lhsTrueFixup, dist, 127)) { + badDist: + panic("CompileLandOrLorExpr: bad jump distance %d\n", dist); + } + TclEmitPush(TclRegisterLiteral(envPtr, "1", 1, /*onHeap*/ 0), envPtr); + dist = (envPtr->codeNext - envPtr->codeStart) - lhsEndFixup.codeOffset; + if (TclFixupForwardJump(envPtr, &lhsEndFixup, dist, 127)) { + goto badDist; + } + + /* + * Emit the "short circuit" jump around the rest of the expression. + * Duplicate the "0" or "1" on top of the stack first to keep the + * jump from consuming it. + */ + + TclEmitOpcode(INST_DUP, envPtr); + TclEmitForwardJump(envPtr, + ((opIndex==OP_LAND)? TCL_FALSE_JUMP : TCL_TRUE_JUMP), + &shortCircuitFixup); + + /* + * Emit code for the second operand. + */ + + code = CompileSubExpr(tokenPtr, infoPtr, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); + tokenPtr += (tokenPtr->numComponents + 1); + + /* + * Emit a "logical and" or "logical or" instruction. This does not try + * to "short- circuit" the evaluation of both operands, but instead + * ensures that we either have a "1" or a "0" result. + */ + + TclEmitOpcode(((opIndex==OP_LAND)? INST_LAND : INST_LOR), envPtr); + + /* + * Now that we know the target of the forward jump, update it with the + * correct distance. + */ + + dist = (envPtr->codeNext - envPtr->codeStart) + - shortCircuitFixup.codeOffset; + TclFixupForwardJump(envPtr, &shortCircuitFixup, dist, 127); + *endPtrPtr = tokenPtr; done: - infoPtr->exprIsComparison = 0; - TclFreeJumpFixupArray(&jumpFixupArray); envPtr->maxStackDepth = maxDepth; - return result; + return code; } /* *---------------------------------------------------------------------- * - * CompileBitOrExpr -- + * CompileCondExpr -- * - * This procedure compiles a Tcl bitwise or expression: - * bitOrExpr ::= bitXorExpr {'|' bitXorExpr} + * This procedure compiles a Tcl conditional expression: + * condExpr ::= lorExpr ['?' condExpr ':' condExpr] * * 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 + * on failure. If TCL_OK is returned, a pointer to the token just after + * the last one in the subexpression is stored at the address in + * endPtrPtr. If TCL_ERROR is returned, then the interpreter's result * contains an error message. * * envPtr->maxStackDepth is updated with the maximum number of stack * elements needed to execute the expression. * @@ -879,833 +781,113 @@ * *---------------------------------------------------------------------- */ static int -CompileBitOrExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int result; - - HERE("bitOrExpr", 4); - result = CompileBitXorExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - - while (infoPtr->token == BIT_OR) { - infoPtr->hasOperators = 1; - infoPtr->exprIsJustVarRef = 0; - result = GetToken(interp, infoPtr, envPtr); /* skip over the '|' */ - if (result != TCL_OK) { - goto done; - } - - result = CompileBitXorExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); - - TclEmitOpcode(INST_BITOR, envPtr); - - /* - * A comparison is not the top-level operator in this expression. - */ - - infoPtr->exprIsComparison = 0; - } - - done: - envPtr->maxStackDepth = maxDepth; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileBitXorExpr -- - * - * This procedure compiles a Tcl bitwise exclusive or expression: - * bitXorExpr ::= bitAndExpr {'^' bitAndExpr} - * - * 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. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the expression. - * - * Side effects: - * Adds instructions to envPtr to evaluate the expression at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileBitXorExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int result; - - HERE("bitXorExpr", 5); - result = CompileBitAndExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - - while (infoPtr->token == BIT_XOR) { - infoPtr->hasOperators = 1; - infoPtr->exprIsJustVarRef = 0; - result = GetToken(interp, infoPtr, envPtr); /* skip over the '^' */ - if (result != TCL_OK) { - goto done; - } - - result = CompileBitAndExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); - - TclEmitOpcode(INST_BITXOR, envPtr); - - /* - * A comparison is not the top-level operator in this expression. - */ - - infoPtr->exprIsComparison = 0; - } - - done: - envPtr->maxStackDepth = maxDepth; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileBitAndExpr -- - * - * This procedure compiles a Tcl bitwise and expression: - * bitAndExpr ::= equalityExpr {'&' equalityExpr} - * - * 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. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the expression. - * - * Side effects: - * Adds instructions to envPtr to evaluate the expression at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileBitAndExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int result; - - HERE("bitAndExpr", 6); - result = CompileEqualityExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - - while (infoPtr->token == BIT_AND) { - infoPtr->hasOperators = 1; - infoPtr->exprIsJustVarRef = 0; - result = GetToken(interp, infoPtr, envPtr); /* skip over the '&' */ - if (result != TCL_OK) { - goto done; - } - - result = CompileEqualityExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); - - TclEmitOpcode(INST_BITAND, envPtr); - - /* - * A comparison is not the top-level operator in this expression. - */ - - infoPtr->exprIsComparison = 0; - } - - done: - envPtr->maxStackDepth = maxDepth; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileEqualityExpr -- - * - * This procedure compiles a Tcl equality (inequality) expression: - * equalityExpr ::= relationalExpr {('==' | '!=') relationalExpr} - * - * 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. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the expression. - * - * Side effects: - * Adds instructions to envPtr to evaluate the expression at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileEqualityExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int op, result; - - HERE("equalityExpr", 7); - result = CompileRelationalExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - - op = infoPtr->token; - while ((op == EQUAL) || (op == NEQ)) { - infoPtr->hasOperators = 1; - infoPtr->exprIsJustVarRef = 0; - result = GetToken(interp, infoPtr, envPtr); /* skip over == or != */ - if (result != TCL_OK) { - goto done; - } - - result = CompileRelationalExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); - - if (op == EQUAL) { - TclEmitOpcode(INST_EQ, envPtr); - } else { - TclEmitOpcode(INST_NEQ, envPtr); - } - - op = infoPtr->token; - - /* - * A comparison _is_ the top-level operator in this expression. - */ - - infoPtr->exprIsComparison = 1; - } - - done: - envPtr->maxStackDepth = maxDepth; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileRelationalExpr -- - * - * This procedure compiles a Tcl relational expression: - * relationalExpr ::= shiftExpr {('<' | '>' | '<=' | '>=') shiftExpr} - * - * 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. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the expression. - * - * Side effects: - * Adds instructions to envPtr to evaluate the expression at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileRelationalExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int op, result; - - HERE("relationalExpr", 8); - result = CompileShiftExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - - op = infoPtr->token; - while ((op == LESS) || (op == GREATER) || (op == LEQ) || (op == GEQ)) { - infoPtr->hasOperators = 1; - infoPtr->exprIsJustVarRef = 0; - result = GetToken(interp, infoPtr, envPtr); /* skip over the op */ - if (result != TCL_OK) { - goto done; - } - - result = CompileShiftExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); - - switch (op) { - case LESS: - TclEmitOpcode(INST_LT, envPtr); - break; - case GREATER: - TclEmitOpcode(INST_GT, envPtr); - break; - case LEQ: - TclEmitOpcode(INST_LE, envPtr); - break; - case GEQ: - TclEmitOpcode(INST_GE, envPtr); - break; - } - - op = infoPtr->token; - - /* - * A comparison _is_ the top-level operator in this expression. - */ - - infoPtr->exprIsComparison = 1; - } - - done: - envPtr->maxStackDepth = maxDepth; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileShiftExpr -- - * - * This procedure compiles a Tcl shift expression: - * shiftExpr ::= addExpr {('<<' | '>>') addExpr} - * - * 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. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the expression. - * - * Side effects: - * Adds instructions to envPtr to evaluate the expression at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileShiftExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int op, result; - - HERE("shiftExpr", 9); - result = CompileAddExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - - op = infoPtr->token; - while ((op == LEFT_SHIFT) || (op == RIGHT_SHIFT)) { - infoPtr->hasOperators = 1; - infoPtr->exprIsJustVarRef = 0; - result = GetToken(interp, infoPtr, envPtr); /* skip over << or >> */ - if (result != TCL_OK) { - goto done; - } - - result = CompileAddExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); - - if (op == LEFT_SHIFT) { - TclEmitOpcode(INST_LSHIFT, envPtr); - } else { - TclEmitOpcode(INST_RSHIFT, envPtr); - } - - op = infoPtr->token; - - /* - * A comparison is not the top-level operator in this expression. - */ - - infoPtr->exprIsComparison = 0; - } - - done: - envPtr->maxStackDepth = maxDepth; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileAddExpr -- - * - * This procedure compiles a Tcl addition expression: - * addExpr ::= multiplyExpr {('+' | '-') multiplyExpr} - * - * 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. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the expression. - * - * Side effects: - * Adds instructions to envPtr to evaluate the expression at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileAddExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int op, result; - - HERE("addExpr", 10); - result = CompileMultiplyExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - - op = infoPtr->token; - while ((op == PLUS) || (op == MINUS)) { - infoPtr->hasOperators = 1; - infoPtr->exprIsJustVarRef = 0; - result = GetToken(interp, infoPtr, envPtr); /* skip over + or - */ - if (result != TCL_OK) { - goto done; - } - - result = CompileMultiplyExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); - - if (op == PLUS) { - TclEmitOpcode(INST_ADD, envPtr); - } else { - TclEmitOpcode(INST_SUB, envPtr); - } - - op = infoPtr->token; - - /* - * A comparison is not the top-level operator in this expression. - */ - - infoPtr->exprIsComparison = 0; - } - - done: - envPtr->maxStackDepth = maxDepth; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileMultiplyExpr -- - * - * This procedure compiles a Tcl multiply expression: - * multiplyExpr ::= unaryExpr {('*' | '/' | '%') unaryExpr} - * - * 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. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the expression. - * - * Side effects: - * Adds instructions to envPtr to evaluate the expression at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileMultiplyExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int op, result; - - HERE("multiplyExpr", 11); - result = CompileUnaryExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - - op = infoPtr->token; - while ((op == MULT) || (op == DIVIDE) || (op == MOD)) { - infoPtr->hasOperators = 1; - infoPtr->exprIsJustVarRef = 0; - result = GetToken(interp, infoPtr, envPtr); /* skip over * or / */ - if (result != TCL_OK) { - goto done; - } - - result = CompileUnaryExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); - - if (op == MULT) { - TclEmitOpcode(INST_MULT, envPtr); - } else if (op == DIVIDE) { - TclEmitOpcode(INST_DIV, envPtr); - } else { - TclEmitOpcode(INST_MOD, envPtr); - } - - op = infoPtr->token; - - /* - * A comparison is not the top-level operator in this expression. - */ - - infoPtr->exprIsComparison = 0; - } - - done: - envPtr->maxStackDepth = maxDepth; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileUnaryExpr -- - * - * This procedure compiles a Tcl unary expression: - * unaryExpr ::= ('+' | '-' | '~' | '!') unaryExpr | primaryExpr - * - * 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. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the expression. - * - * Side effects: - * Adds instructions to envPtr to evaluate the expression at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileUnaryExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int op, result; - - HERE("unaryExpr", 12); - op = infoPtr->token; - if ((op == PLUS) || (op == MINUS) || (op == BIT_NOT) || (op == NOT)) { - infoPtr->hasOperators = 1; - infoPtr->exprIsJustVarRef = 0; - result = GetToken(interp, infoPtr, envPtr); /* skip over the op */ - if (result != TCL_OK) { - goto done; - } - - result = CompileUnaryExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - - switch (op) { - case PLUS: - TclEmitOpcode(INST_UPLUS, envPtr); - break; - case MINUS: - TclEmitOpcode(INST_UMINUS, envPtr); - break; - case BIT_NOT: - TclEmitOpcode(INST_BITNOT, envPtr); - break; - case NOT: - TclEmitOpcode(INST_LNOT, envPtr); - break; - } - - /* - * A comparison is not the top-level operator in this expression. - */ - - infoPtr->exprIsComparison = 0; - } else { /* must be a primaryExpr */ - result = CompilePrimaryExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - } - - done: - envPtr->maxStackDepth = maxDepth; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompilePrimaryExpr -- - * - * This procedure compiles a Tcl primary expression: - * primaryExpr ::= literal | varReference | quotedString | - * '[' command ']' | mathFuncCall | '(' condExpr ')' - * - * 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. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the expression. - * - * Side effects: - * Adds instructions to envPtr to evaluate the expression at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompilePrimaryExpr(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - ExprInfo *infoPtr; /* Describes the compilation state for the - * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int theToken; - char *dollarPtr, *quotePtr, *cmdPtr, *termPtr; - int result = TCL_OK; - - /* - * We emit tryCvtToNumeric instructions after most of these primary - * expressions in order to support Tcl's policy of interpreting operands - * as first integers if possible, otherwise floating-point numbers if - * possible. - */ - - HERE("primaryExpr", 13); - theToken = infoPtr->token; - - if ((theToken != DOLLAR) && (theToken != OPEN_PAREN)) { - infoPtr->exprIsJustVarRef = 0; - } - switch (theToken) { - case LITERAL: /* int, double, or string in braces */ - TclEmitPush(infoPtr->objIndex, envPtr); - maxDepth = 1; - break; - - case DOLLAR: /* $var variable reference */ - dollarPtr = (infoPtr->next - 1); - envPtr->pushSimpleWords = 1; - result = TclCompileDollarVar(interp, dollarPtr, - infoPtr->lastChar, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - infoPtr->next = (dollarPtr + envPtr->termOffset); - break; - - case QUOTE: /* quotedString */ - quotePtr = infoPtr->next; - envPtr->pushSimpleWords = 1; - result = TclCompileQuotes(interp, quotePtr, - infoPtr->lastChar, '"', flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - infoPtr->next = (quotePtr + envPtr->termOffset); - break; - - case OPEN_BRACKET: /* '[' command ']' */ - cmdPtr = infoPtr->next; - envPtr->pushSimpleWords = 1; - result = TclCompileString(interp, cmdPtr, - infoPtr->lastChar, (flags | TCL_BRACKET_TERM), envPtr); - if (result != TCL_OK) { - goto done; - } - termPtr = (cmdPtr + envPtr->termOffset); - if (*termPtr == ']') { - infoPtr->next = (termPtr + 1); /* advance over the ']'. */ - } else if (termPtr == infoPtr->lastChar) { - /* - * Missing ] at end of nested command. - */ - - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "missing close-bracket", -1); - result = TCL_ERROR; - goto done; - } else { - panic("CompilePrimaryExpr: unexpected termination char '%c' for nested command\n", *termPtr); - } - maxDepth = envPtr->maxStackDepth; - break; - - case FUNC_NAME: - result = CompileMathFuncCall(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - break; - - case OPEN_PAREN: - result = GetToken(interp, infoPtr, envPtr); /* skip over the '(' */ - if (result != TCL_OK) { - goto done; - } - infoPtr->exprIsComparison = 0; - result = CompileCondExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = envPtr->maxStackDepth; - if (infoPtr->token != CLOSE_PAREN) { - goto syntaxError; - } - break; - - default: - goto syntaxError; - } - - if (theToken != FUNC_NAME) { - /* - * Advance to the next token before returning. - */ - - result = GetToken(interp, infoPtr, envPtr); - if (result != TCL_OK) { - goto done; - } - } - - done: - envPtr->maxStackDepth = maxDepth; - return result; - - syntaxError: - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "syntax error in expression \"", infoPtr->originalExpr, - "\"", (char *) NULL); - return TCL_ERROR; +CompileCondExpr(exprTokenPtr, infoPtr, envPtr, endPtrPtr) + Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token + * containing the "?" operator. */ + ExprInfo *infoPtr; /* Describes the compilation state for the + * expression being compiled. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ + Tcl_Token **endPtrPtr; /* If successful, a pointer to the token + * just after the last token in the + * subexpression is stored here. */ +{ + JumpFixup jumpAroundThenFixup, jumpAroundElseFixup; + /* Used to update or replace one-byte jumps + * around the then and else expressions when + * their target PCs are determined. */ + Tcl_Token *tokenPtr; + int elseCodeOffset, dist, maxDepth, code; + + /* + * Emit code for the test. + */ + + maxDepth = 0; + tokenPtr = exprTokenPtr+2; + code = CompileSubExpr(tokenPtr, infoPtr, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = envPtr->maxStackDepth; + tokenPtr += (tokenPtr->numComponents + 1); + + /* + * Emit the jump to the "else" expression if the test was false. + */ + + TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpAroundThenFixup); + + /* + * Compile the "then" expression. Note that if a subexpression is only + * a primary, we need to try to convert it to numeric. We do this to + * support Tcl's policy of interpreting operands if at all possible as + * first integers, else floating-point numbers. + */ + + infoPtr->hasOperators = 0; + code = CompileSubExpr(tokenPtr, infoPtr, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + tokenPtr += (tokenPtr->numComponents + 1); + if (!infoPtr->hasOperators) { + TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr); + } + + /* + * Emit an unconditional jump around the "else" condExpr. + */ + + TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, + &jumpAroundElseFixup); + + /* + * Compile the "else" expression. + */ + + elseCodeOffset = (envPtr->codeNext - envPtr->codeStart); + infoPtr->hasOperators = 0; + code = CompileSubExpr(tokenPtr, infoPtr, envPtr); + if (code != TCL_OK) { + goto done; + } + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + tokenPtr += (tokenPtr->numComponents + 1); + if (!infoPtr->hasOperators) { + TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr); + } + + /* + * Fix up the second jump around the "else" expression. + */ + + dist = (envPtr->codeNext - envPtr->codeStart) + - jumpAroundElseFixup.codeOffset; + if (TclFixupForwardJump(envPtr, &jumpAroundElseFixup, dist, 127)) { + /* + * Update the else expression's starting code offset since it + * moved down 3 bytes too. + */ + + elseCodeOffset += 3; + } + + /* + * Fix up the first jump to the "else" expression if the test was false. + */ + + dist = (elseCodeOffset - jumpAroundThenFixup.codeOffset); + TclFixupForwardJump(envPtr, &jumpAroundThenFixup, dist, 127); + *endPtrPtr = tokenPtr; + + done: + envPtr->maxStackDepth = maxDepth; + return code; } /* *---------------------------------------------------------------------- * @@ -1714,11 +896,13 @@ * This procedure compiles a call on a math function in an expression: * mathFuncCall ::= funcName '(' [condExpr {',' condExpr}] ')' * * 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 + * on failure. If TCL_OK is returned, a pointer to the token just after + * the last one in the subexpression is stored at the address in + * endPtrPtr. If TCL_ERROR is returned, then the interpreter's result * contains an error message. * * envPtr->maxStackDepth is updated with the maximum number of stack * elements needed to execute the function. * @@ -1728,659 +912,137 @@ * *---------------------------------------------------------------------- */ static int -CompileMathFuncCall(interp, infoPtr, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ +CompileMathFuncCall(exprTokenPtr, funcName, infoPtr, envPtr, endPtrPtr) + Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token + * containing the math function call. */ + char *funcName; /* Name of the math function. */ ExprInfo *infoPtr; /* Describes the compilation state for the * expression being compiled. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - Interp *iPtr = (Interp *) interp; - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - MathFunc *mathFuncPtr; /* Info about math function. */ - int objIndex; /* The object array index for an object - * holding the function name if it is not - * builtin. */ - Tcl_HashEntry *hPtr; - char *p, *funcName; - char savedChar; - int result, i; + CompileEnv *envPtr; /* Holds resulting instructions. */ + Tcl_Token **endPtrPtr; /* If successful, a pointer to the token + * just after the last token in the + * subexpression is stored here. */ +{ + Tcl_Interp *interp = infoPtr->interp; + Interp *iPtr = (Interp *) interp; + MathFunc *mathFuncPtr; + Tcl_HashEntry *hPtr; + Tcl_Token *tokenPtr, *afterSubexprPtr; + int maxDepth, code, i; /* - * infoPtr->funcName points to the first character of the math - * function's name. Look for the end of its name and look up the - * MathFunc record for the function. + * Look up the MathFunc record for the function. */ - funcName = p = infoPtr->funcName; - while (isalnum(UCHAR(*p)) || (*p == '_')) { - p++; - } - infoPtr->next = p; - - result = GetToken(interp, infoPtr, envPtr); /* skip over func name */ - if (result != TCL_OK) { - goto done; - } - if (infoPtr->token != OPEN_PAREN) { - goto syntaxError; - } - result = GetToken(interp, infoPtr, envPtr); /* skip over '(' */ - if (result != TCL_OK) { - goto done; - } - - savedChar = *p; - *p = 0; + code = TCL_OK; + maxDepth = 0; hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName); if (hPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "unknown math function \"", funcName, "\"", (char *) NULL); - result = TCL_ERROR; - *p = savedChar; + code = TCL_ERROR; goto done; } mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr); /* * If not a builtin function, push an object with the function's name. */ - if (mathFuncPtr->builtinFuncIndex < 0) { /* not builtin */ - objIndex = TclObjIndexForString(funcName, -1, /*allocStrRep*/ 1, - /*inHeap*/ 0, envPtr); - TclEmitPush(objIndex, envPtr); + if (mathFuncPtr->builtinFuncIndex < 0) { + TclEmitPush(TclRegisterLiteral(envPtr, funcName, -1, /*onHeap*/ 0), + envPtr); maxDepth = 1; } /* - * Restore the saved character after the function name. - */ - - *p = savedChar; - - /* - * Compile the arguments for the function, if there are any. - */ - - if (mathFuncPtr->numArgs > 0) { - for (i = 0; ; i++) { - infoPtr->exprIsComparison = 0; - result = CompileCondExpr(interp, infoPtr, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - - /* - * Check for a ',' between arguments or a ')' ending the - * argument list. - */ - - if (i == (mathFuncPtr->numArgs-1)) { - if (infoPtr->token == CLOSE_PAREN) { - break; /* exit the argument parsing loop */ - } else if (infoPtr->token == COMMA) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "too many arguments for math function", -1); - result = TCL_ERROR; - goto done; - } else { - goto syntaxError; - } - } - if (infoPtr->token != COMMA) { - if (infoPtr->token == CLOSE_PAREN) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "too few arguments for math function", -1); - result = TCL_ERROR; - goto done; - } else { - goto syntaxError; - } - } - result = GetToken(interp, infoPtr, envPtr); /* skip over , */ - if (result != TCL_OK) { - goto done; - } - maxDepth++; - } - } - - if (infoPtr->token != CLOSE_PAREN) { - goto syntaxError; - } - result = GetToken(interp, infoPtr, envPtr); /* skip over ')' */ - if (result != TCL_OK) { + * Compile any arguments for the function. + */ + + tokenPtr = exprTokenPtr+2; + afterSubexprPtr = exprTokenPtr + (exprTokenPtr->numComponents + 1); + if (mathFuncPtr->numArgs > 0) { + for (i = 0; i < mathFuncPtr->numArgs; i++) { + if (tokenPtr == afterSubexprPtr) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "too few arguments for math function", -1); + code = TCL_ERROR; + goto done; + } + infoPtr->exprIsComparison = 0; + code = CompileSubExpr(tokenPtr, infoPtr, envPtr); + if (code != TCL_OK) { + goto done; + } + tokenPtr += (tokenPtr->numComponents + 1); + maxDepth++; + } + if (tokenPtr != afterSubexprPtr) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "too many arguments for math function", -1); + code = TCL_ERROR; + goto done; + } + } else if (tokenPtr != afterSubexprPtr) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "too many arguments for math function", -1); + code = TCL_ERROR; goto done; } /* * Compile the call on the math function. Note that the "objc" argument * count for non-builtin functions is incremented by 1 to include the - * the function name itself. - */ - - if (mathFuncPtr->builtinFuncIndex >= 0) { /* a builtin function */ - TclEmitInstUInt1(INST_CALL_BUILTIN_FUNC1, - mathFuncPtr->builtinFuncIndex, envPtr); - } else { - TclEmitInstUInt1(INST_CALL_FUNC1, (mathFuncPtr->numArgs+1), envPtr); - } - - /* - * A comparison is not the top-level operator in this expression. - */ - - done: - infoPtr->exprIsComparison = 0; - envPtr->maxStackDepth = maxDepth; - return result; - - syntaxError: - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "syntax error in expression \"", infoPtr->originalExpr, - "\"", (char *) NULL); - return TCL_ERROR; -} - -/* - *---------------------------------------------------------------------- - * - * GetToken -- - * - * Lexical scanner used to compile expressions: parses a single - * operator or other syntactic element from an expression string. - * - * Results: - * TCL_OK is returned unless an error occurred. In that case a standard - * Tcl error is returned, using the interpreter's result to hold an - * error message. TCL_ERROR is returned if an integer overflow, or a - * floating-point overflow or underflow occurred while reading in a - * number. If the lexical analysis is successful, infoPtr->token refers - * to the next symbol in the expression string, and infoPtr->next is - * advanced past the token. Also, if the token is a integer, double, or - * string literal, then infoPtr->objIndex the index of an object - * holding the value in the code's object table; otherwise is NULL. - * - * Side effects: - * Object are added to envPtr to hold the values of scanned literal - * integers, doubles, or strings. - * - *---------------------------------------------------------------------- - */ - -static int -GetToken(interp, infoPtr, envPtr) - Tcl_Interp *interp; /* Interpreter to use for error - * reporting. */ - register ExprInfo *infoPtr; /* Describes the state of the - * compiling the expression, - * including the resulting token. */ - CompileEnv *envPtr; /* Holds objects that store literal - * values that are scanned. */ -{ - register char *src; /* Points to current source char. */ - register char c; /* The current char. */ - register int type; /* Current char's CHAR_TYPE type. */ - char *termPtr; /* Points to char terminating a literal. */ - char savedChar; /* Holds the character termporarily replaced - * by a null character during processing of - * literal tokens. */ - int objIndex; /* The object array index for an object - * holding a scanned literal. */ - long longValue; /* Value of a scanned integer literal. */ - double doubleValue; /* Value of a scanned double literal. */ - Tcl_Obj *objPtr; - - /* - * First initialize the scanner's "result" fields to default values. - */ - - infoPtr->token = UNKNOWN; - infoPtr->objIndex = -1; - infoPtr->funcName = NULL; - - /* - * Scan over leading white space at the start of a token. Note that a - * backslash-newline is treated as a space. - */ - - src = infoPtr->next; - c = *src; - type = CHAR_TYPE(src, infoPtr->lastChar); - while ((type & (TCL_SPACE | TCL_BACKSLASH)) || (c == '\n')) { - if (type == TCL_BACKSLASH) { - if (src[1] == '\n') { - src += 2; - } else { - break; /* no longer white space */ - } - } else { - src++; - } - c = *src; - type = CHAR_TYPE(src, infoPtr->lastChar); - } - if (src == infoPtr->lastChar) { - infoPtr->token = END; - infoPtr->next = src; - return TCL_OK; - } - - /* - * Try to parse the token first as an integer or floating-point - * number. Don't check for a number if the first character is "+" or - * "-". If we did, we might treat a binary operator as unary by mistake, - * which would eventually cause a syntax error. - */ - - if ((*src != '+') && (*src != '-')) { - int startsWithDigit = isdigit(UCHAR(*src)); - - if (startsWithDigit && TclLooksLikeInt(src)) { - errno = 0; - longValue = strtoul(src, &termPtr, 0); - if (errno == ERANGE) { - char *s = "integer value too large to represent"; - - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1); - Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, - (char *) NULL); - return TCL_ERROR; - } - if (termPtr != src) { - /* - * src was the start of a valid integer. Find/create an - * object in envPtr's object array to contain the integer. - */ - - savedChar = *termPtr; - *termPtr = '\0'; - objIndex = TclObjIndexForString(src, termPtr - src, - /*allocStrRep*/ 0, /*inHeap*/ 0, envPtr); - *termPtr = savedChar; /* restore the saved char */ - - objPtr = envPtr->objArrayPtr[objIndex]; - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.longValue = longValue; - objPtr->typePtr = &tclIntType; - - infoPtr->token = LITERAL; - infoPtr->objIndex = objIndex; - infoPtr->next = termPtr; - return TCL_OK; - } - } else if (startsWithDigit || (*src == '.') - || (*src == 'n') || (*src == 'N')) { - errno = 0; - doubleValue = strtod(src, &termPtr); - if (termPtr != src) { - if (errno != 0) { - TclExprFloatError(interp, doubleValue); - return TCL_ERROR; - } - - /* - * Find/create an object in the object array containing the - * double. - */ - - savedChar = *termPtr; - *termPtr = '\0'; - objIndex = TclObjIndexForString(src, termPtr - src, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - *termPtr = savedChar; /* restore the saved char */ - - objPtr = envPtr->objArrayPtr[objIndex]; - objPtr->internalRep.doubleValue = doubleValue; - objPtr->typePtr = &tclDoubleType; - - infoPtr->token = LITERAL; - infoPtr->objIndex = objIndex; - infoPtr->next = termPtr; - return TCL_OK; - } - } - } - - /* - * Not an integer or double literal. Check next for a string literal - * in braces. - */ - - if (*src == '{') { - int level = 0; /* The {} nesting level. */ - int hasBackslashNL = 0; /* Nonzero if '\newline' was found. */ - char *string = src; /* Set below to point just after the - * starting '{'. */ - char *last; /* Points just before terminating '}'. */ - int numChars; /* Number of chars in braced string. */ - char savedChar; /* Holds the character from string - * termporarily replaced by a null char - * during braced string processing. */ - int numRead; - - /* - * Check first for any backslash-newlines, since we must treat - * backslash-newlines specially (they must be replaced by spaces). - */ - - while (1) { - if (src == infoPtr->lastChar) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "missing close-brace", -1); - return TCL_ERROR; - } else if (CHAR_TYPE(src, infoPtr->lastChar) == TCL_NORMAL) { - src++; - continue; - } - c = *src++; - if (c == '{') { - level++; - } else if (c == '}') { - --level; - if (level == 0) { - last = (src - 2); /* i.e. just before terminating } */ - break; - } - } else if (c == '\\') { - if (*src == '\n') { - hasBackslashNL = 1; - } - (void) Tcl_Backslash(src-1, &numRead); - src += numRead - 1; - } - } - - /* - * Create a string object for the braced string. This will start at - * "string" and ends just after "last" (which points to the final - * character before the terminating '}'). If backslash-newlines were - * found, we copy characters one at a time into a heap-allocated - * buffer and do backslash-newline substitutions. - */ - - string++; - numChars = (last - string + 1); - savedChar = string[numChars]; - string[numChars] = '\0'; - if (hasBackslashNL && (numChars > 0)) { - char *buffer = ckalloc((unsigned) numChars + 1); - register char *dst = buffer; - register char *p = string; - while (p <= last) { - c = *dst++ = *p++; - if (c == '\\') { - if (*p == '\n') { - dst[-1] = Tcl_Backslash(p-1, &numRead); - p += numRead - 1; - } else { - (void) Tcl_Backslash(p-1, &numRead); - while (numRead > 1) { - *dst++ = *p++; - numRead--; - } - } - } - } - *dst = '\0'; - objIndex = TclObjIndexForString(buffer, dst - buffer, - /*allocStrRep*/ 1, /*inHeap*/ 1, envPtr); - } else { - objIndex = TclObjIndexForString(string, numChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - } - string[numChars] = savedChar; /* restore the saved char */ - - infoPtr->token = LITERAL; - infoPtr->objIndex = objIndex; - infoPtr->next = src; - return TCL_OK; - } - - /* - * Not an literal value. - */ - - infoPtr->next = src+1; /* assume a 1 char token and advance over it */ - switch (*src) { - case '[': - infoPtr->token = OPEN_BRACKET; - return TCL_OK; - - case ']': - infoPtr->token = CLOSE_BRACKET; - return TCL_OK; - - case '(': - infoPtr->token = OPEN_PAREN; - return TCL_OK; - - case ')': - infoPtr->token = CLOSE_PAREN; - return TCL_OK; - - case '$': - infoPtr->token = DOLLAR; - return TCL_OK; - - case '"': - infoPtr->token = QUOTE; - return TCL_OK; - - case ',': - infoPtr->token = COMMA; - return TCL_OK; - - case '*': - infoPtr->token = MULT; - return TCL_OK; - - case '/': - infoPtr->token = DIVIDE; - return TCL_OK; - - case '%': - infoPtr->token = MOD; - return TCL_OK; - - case '+': - infoPtr->token = PLUS; - return TCL_OK; - - case '-': - infoPtr->token = MINUS; - return TCL_OK; - - case '?': - infoPtr->token = QUESTY; - return TCL_OK; - - case ':': - infoPtr->token = COLON; - return TCL_OK; - - case '<': - switch (src[1]) { - case '<': - infoPtr->next = src+2; - infoPtr->token = LEFT_SHIFT; - break; - case '=': - infoPtr->next = src+2; - infoPtr->token = LEQ; - break; - default: - infoPtr->token = LESS; - break; - } - return TCL_OK; - - case '>': - switch (src[1]) { - case '>': - infoPtr->next = src+2; - infoPtr->token = RIGHT_SHIFT; - break; - case '=': - infoPtr->next = src+2; - infoPtr->token = GEQ; - break; - default: - infoPtr->token = GREATER; - break; - } - return TCL_OK; - - case '=': - if (src[1] == '=') { - infoPtr->next = src+2; - infoPtr->token = EQUAL; - } else { - infoPtr->token = UNKNOWN; - } - return TCL_OK; - - case '!': - if (src[1] == '=') { - infoPtr->next = src+2; - infoPtr->token = NEQ; - } else { - infoPtr->token = NOT; - } - return TCL_OK; - - case '&': - if (src[1] == '&') { - infoPtr->next = src+2; - infoPtr->token = AND; - } else { - infoPtr->token = BIT_AND; - } - return TCL_OK; - - case '^': - infoPtr->token = BIT_XOR; - return TCL_OK; - - case '|': - if (src[1] == '|') { - infoPtr->next = src+2; - infoPtr->token = OR; - } else { - infoPtr->token = BIT_OR; - } - return TCL_OK; - - case '~': - infoPtr->token = BIT_NOT; - return TCL_OK; - - default: - if (isalpha(UCHAR(*src))) { - infoPtr->token = FUNC_NAME; - infoPtr->funcName = src; - while (isalnum(UCHAR(*src)) || (*src == '_')) { - src++; - } - infoPtr->next = src; - return TCL_OK; - } - infoPtr->next = src+1; - infoPtr->token = UNKNOWN; - return TCL_OK; - } -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_CreateMathFunc -- - * - * Creates a new math function for expressions in a given - * interpreter. - * - * Results: - * None. - * - * Side effects: - * The 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(interp, name, numArgs, argTypes, proc, clientData) - Tcl_Interp *interp; /* Interpreter in which function is - * to be available. */ - 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; /* Procedure that implements the - * math function. */ - ClientData clientData; /* Additional value to pass to the - * function. */ -{ - Interp *iPtr = (Interp *) interp; - Tcl_HashEntry *hPtr; - MathFunc *mathFuncPtr; - int new, i; - - hPtr = Tcl_CreateHashEntry(&iPtr->mathFuncTable, name, &new); - if (new) { - Tcl_SetHashValue(hPtr, ckalloc(sizeof(MathFunc))); - } - mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr); - - if (!new) { - if (mathFuncPtr->builtinFuncIndex >= 0) { - /* - * We are redefining a builtin math function. Invalidate the - * interpreter's existing code by incrementing its - * compileEpoch member. This field is checked in Tcl_EvalObj - * and ObjInterpProc, and code whose compilation epoch doesn't - * match is recompiled. Newly compiled code will no longer - * treat the function as builtin. - */ - - iPtr->compileEpoch++; - } else { - /* - * A non-builtin function is being redefined. We must invalidate - * existing code if the number of arguments has changed. This - * is because existing code was compiled assuming that number. - */ - - if (numArgs != mathFuncPtr->numArgs) { - iPtr->compileEpoch++; - } - } - } - - mathFuncPtr->builtinFuncIndex = -1; /* can't be a builtin function */ - if (numArgs > MAX_MATH_ARGS) { - numArgs = MAX_MATH_ARGS; - } - mathFuncPtr->numArgs = numArgs; - for (i = 0; i < numArgs; i++) { - mathFuncPtr->argTypes[i] = argTypes[i]; - } - mathFuncPtr->proc = proc; - mathFuncPtr->clientData = clientData; + * function name itself. + */ + + if (mathFuncPtr->builtinFuncIndex >= 0) { /* a builtin function */ + TclEmitInstInt1(INST_CALL_BUILTIN_FUNC1, + mathFuncPtr->builtinFuncIndex, envPtr); + } else { + TclEmitInstInt1(INST_CALL_FUNC1, (mathFuncPtr->numArgs+1), envPtr); + } + *endPtrPtr = afterSubexprPtr; + + done: + envPtr->maxStackDepth = maxDepth; + return code; +} + +/* + *---------------------------------------------------------------------- + * + * LogSyntaxError -- + * + * This procedure is invoked after an error occurs when compiling an + * expression. It sets the interpreter result to an error message + * describing the error. + * + * Results: + * None. + * + * Side effects: + * Sets the interpreter result to an error message describing the + * expression that was being compiled when the error occurred. + * + *---------------------------------------------------------------------- + */ + +static void +LogSyntaxError(infoPtr) + ExprInfo *infoPtr; /* Describes the compilation state for the + * expression being compiled. */ +{ + int numBytes = (infoPtr->lastChar - infoPtr->expr); + char buffer[100]; + + sprintf(buffer, "syntax error in expression \"%.*s\"", + ((numBytes > 60)? 60 : numBytes), infoPtr->expr); + Tcl_AppendStringsToObj(Tcl_GetObjResult(infoPtr->interp), + buffer, (char *) NULL); } Index: generic/tclCompile.c ================================================================== --- generic/tclCompile.c +++ generic/tclCompile.c @@ -3,21 +3,30 @@ * * 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-1997 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclCompile.c 1.80 97/09/18 18:23:30 + * RCS: @(#) $Id: tclCompile.c,v 1.1.2.10 1999/03/24 01:42:47 surles Exp $ */ #include "tclInt.h" #include "tclCompile.h" +/* + * Table of all AuxData types. + */ + +static Tcl_HashTable auxDataTypeTable; +static int auxDataTypeTableInitialized; /* 0 means not yet initialized. */ + +TCL_DECLARE_MUTEX(tableMutex) + /* * 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 @@ -27,38 +36,15 @@ int tclTraceCompile = 0; static int traceInitialized = 0; /* - * Count of the number of compilations and various other compilation- - * related statistics. - */ - -#ifdef TCL_COMPILE_STATS -long tclNumCompilations = 0; -double tclTotalSourceBytes = 0.0; -double tclTotalCodeBytes = 0.0; - -double tclTotalInstBytes = 0.0; -double tclTotalObjBytes = 0.0; -double tclTotalExceptBytes = 0.0; -double tclTotalAuxBytes = 0.0; -double tclTotalCmdMapBytes = 0.0; - -double tclCurrentSourceBytes = 0.0; -double tclCurrentCodeBytes = 0.0; - -int tclSourceCount[32]; -int tclByteCodeCount[32]; -#endif /* TCL_COMPILE_STATS */ - -/* - * A table describing the Tcl bytecode instructions. The entries in this - * table must correspond to the list of instructions in tclInt.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. + * 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. */ @@ -213,11 +199,11 @@ {"foreach_step4", 5, 1, {OPERAND_UINT4}}, /* "Step" or begin next iteration of foreach loop. Push 0 if to * terminate loop, else push 1. */ {"beginCatch4", 5, 1, {OPERAND_UINT4}}, - /* Record start of catch with the operand's exception range index. + /* Record start of catch with the operand's exception index. * Push the current stack depth onto a special catch stack. */ {"endCatch", 1, 0, {OPERAND_NONE}}, /* End of last catch. Pop the bytecode interpreter's catch stack. */ {"pushResult", 1, 0, {OPERAND_NONE}}, /* Push the interpreter's object result onto the stack. */ @@ -225,658 +211,189 @@ /* Push interpreter's return code (e.g. TCL_OK or TCL_ERROR) as * a new object onto the stack. */ {0} }; -/* - * The following table assigns a type to each character. Only types - * meaningful to Tcl parsing are represented here. 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 0 character value). - */ - -unsigned char tclTypeTable[] = { - /* - * Negative character values, from -128 to -1: - */ - - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - - /* - * Positive character values, from 0-127: - */ - - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_SPACE, TCL_COMMAND_END, TCL_SPACE, - TCL_SPACE, TCL_SPACE, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_SPACE, TCL_NORMAL, TCL_QUOTE, TCL_NORMAL, - TCL_DOLLAR, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_COMMAND_END, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_OPEN_BRACKET, - TCL_BACKSLASH, TCL_COMMAND_END, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_OPEN_BRACE, - TCL_NORMAL, TCL_CLOSE_BRACE, TCL_NORMAL, TCL_NORMAL, - - /* - * Large unsigned character values, from 128-255: - */ - - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, - TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, -}; - /* * Prototypes for procedures defined later in this file: */ -static void AdvanceToNextWord _ANSI_ARGS_((char *string, - CompileEnv *envPtr)); -static int CollectArgInfo _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int flags, - ArgInfo *argInfoPtr)); -static int CompileBraces _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int flags, - CompileEnv *envPtr)); -static int CompileCmdWordInline _ANSI_ARGS_(( - Tcl_Interp *interp, char *string, - char *lastChar, int flags, CompileEnv *envPtr)); -static int CompileExprWord _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int flags, - CompileEnv *envPtr)); -static int CompileMultipartWord _ANSI_ARGS_(( - Tcl_Interp *interp, char *string, - char *lastChar, int flags, CompileEnv *envPtr)); -static int CompileWord _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int flags, - CompileEnv *envPtr)); -static int CreateExceptionRange _ANSI_ARGS_(( - ExceptionRangeType type, CompileEnv *envPtr)); static void DupByteCodeInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)); -static ClientData DupForeachInfo _ANSI_ARGS_((ClientData clientData)); static unsigned char * EncodeCmdLocMap _ANSI_ARGS_(( CompileEnv *envPtr, ByteCode *codePtr, unsigned char *startPtr)); static void EnterCmdExtentData _ANSI_ARGS_(( CompileEnv *envPtr, int cmdNumber, - int numSrcChars, int numCodeBytes)); + int numSrcBytes, int numCodeBytes)); static void EnterCmdStartData _ANSI_ARGS_(( CompileEnv *envPtr, int cmdNumber, int srcOffset, int codeOffset)); -static void ExpandObjectArray _ANSI_ARGS_((CompileEnv *envPtr)); -static void FreeForeachInfo _ANSI_ARGS_(( - ClientData clientData)); static void FreeByteCodeInternalRep _ANSI_ARGS_(( Tcl_Obj *objPtr)); -static void FreeArgInfo _ANSI_ARGS_((ArgInfo *argInfoPtr)); static int GetCmdLocEncodingSize _ANSI_ARGS_(( CompileEnv *envPtr)); -static void InitArgInfo _ANSI_ARGS_((ArgInfo *argInfoPtr)); -static int LookupCompiledLocal _ANSI_ARGS_(( - char *name, int nameChars, int createIfNew, - int flagsIfCreated, Proc *procPtr)); +static void LogCompilationInfo _ANSI_ARGS_((Tcl_Interp *interp, + char *script, char *command, int length)); +#ifdef TCL_COMPILE_STATS +static void RecordByteCodeStats _ANSI_ARGS_(( + ByteCode *codePtr)); +#endif /* TCL_COMPILE_STATS */ static int SetByteCodeFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr)); -static void UpdateStringOfByteCode _ANSI_ARGS_((Tcl_Obj *objPtr)); /* * The structure below defines the bytecode Tcl object type by * means of procedures that can be invoked by generic object code. */ Tcl_ObjType tclByteCodeType = { - "bytecode", /* name */ - FreeByteCodeInternalRep, /* freeIntRepProc */ - DupByteCodeInternalRep, /* dupIntRepProc */ - UpdateStringOfByteCode, /* updateStringProc */ - SetByteCodeFromAny /* setFromAnyProc */ + "bytecode", /* name */ + FreeByteCodeInternalRep, /* freeIntRepProc */ + DupByteCodeInternalRep, /* dupIntRepProc */ + (Tcl_UpdateStringProc *) NULL, /* updateStringProc */ + SetByteCodeFromAny /* setFromAnyProc */ }; /* - *---------------------------------------------------------------------- - * - * TclPrintByteCodeObj -- - * - * This procedure prints ("disassembles") the instructions of a - * bytecode object to stdout. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -TclPrintByteCodeObj(interp, objPtr) - Tcl_Interp *interp; /* Used only for Tcl_GetStringFromObj. */ - Tcl_Obj *objPtr; /* The bytecode object to disassemble. */ -{ - ByteCode* codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; - unsigned char *codeStart, *codeLimit, *pc; - unsigned char *codeDeltaNext, *codeLengthNext; - unsigned char *srcDeltaNext, *srcLengthNext; - int codeOffset, codeLen, srcOffset, srcLen; - int numCmds, numObjs, delta, objBytes, i; - - if (codePtr->refCount <= 0) { - return; /* already freed */ - } - - codeStart = codePtr->codeStart; - codeLimit = (codeStart + codePtr->numCodeBytes); - numCmds = codePtr->numCommands; - numObjs = codePtr->numObjects; - - objBytes = (numObjs * sizeof(Tcl_Obj)); - for (i = 0; i < numObjs; i++) { - Tcl_Obj *litObjPtr = codePtr->objArrayPtr[i]; - if (litObjPtr->bytes != NULL) { - objBytes += litObjPtr->length; - } - } - - /* - * Print header lines describing the ByteCode. - */ - - fprintf(stdout, "\nByteCode 0x%x, ref ct %u, epoch %u, interp 0x%x(epoch %u)\n", - (unsigned int) codePtr, codePtr->refCount, - codePtr->compileEpoch, (unsigned int) codePtr->iPtr, - codePtr->iPtr->compileEpoch); - fprintf(stdout, " Source "); - TclPrintSource(stdout, codePtr->source, - TclMin(codePtr->numSrcChars, 70)); - fprintf(stdout, "\n Cmds %d, chars %d, inst %d, objs %u, aux %d, stk depth %u, code/src %.2f\n", - numCmds, codePtr->numSrcChars, codePtr->numCodeBytes, numObjs, - codePtr->numAuxDataItems, codePtr->maxStackDepth, - (codePtr->numSrcChars? - ((float)codePtr->totalSize)/((float)codePtr->numSrcChars) : 0.0)); - fprintf(stdout, " Code %d = %d(header)+%d(inst)+%d(objs)+%d(exc)+%d(aux)+%d(cmd map)\n", - codePtr->totalSize, sizeof(ByteCode), codePtr->numCodeBytes, - objBytes, (codePtr->numExcRanges * sizeof(ExceptionRange)), - (codePtr->numAuxDataItems * sizeof(AuxData)), - codePtr->numCmdLocBytes); - - /* - * 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; - fprintf(stdout, - " Proc 0x%x, ref ct %d, args %d, compiled locals %d\n", - (unsigned int) procPtr, procPtr->refCount, procPtr->numArgs, - numCompiledLocals); - if (numCompiledLocals > 0) { - CompiledLocal *localPtr = procPtr->firstLocalPtr; - for (i = 0; i < numCompiledLocals; i++) { - fprintf(stdout, " %d: slot %d%s%s%s%s%s", - i, localPtr->frameIndex, - ((localPtr->flags & VAR_SCALAR)? ", scalar" : ""), - ((localPtr->flags & VAR_ARRAY)? ", array" : ""), - ((localPtr->flags & VAR_LINK)? ", link" : ""), - (localPtr->isArg? ", arg" : ""), - (localPtr->isTemp? ", temp" : "")); - if (localPtr->isTemp) { - fprintf(stdout, "\n"); - } else { - fprintf(stdout, ", name=\"%s\"\n", localPtr->name); - } - localPtr = localPtr->nextPtr; - } - } - } - - /* - * Print the ExceptionRange array. - */ - - if (codePtr->numExcRanges > 0) { - fprintf(stdout, " Exception ranges %d, depth %d:\n", - codePtr->numExcRanges, codePtr->maxExcRangeDepth); - for (i = 0; i < codePtr->numExcRanges; i++) { - ExceptionRange *rangePtr = &(codePtr->excRangeArrayPtr[i]); - fprintf(stdout, " %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: - fprintf(stdout, "continue %d, break %d\n", - rangePtr->continueOffset, rangePtr->breakOffset); - break; - case CATCH_EXCEPTION_RANGE: - fprintf(stdout, "catch %d\n", rangePtr->catchOffset); - break; - default: - panic("TclPrintSource: unrecognized ExceptionRange type %d\n", - 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) { - fprintf(stdout, " "); - pc += TclPrintInstruction(codePtr, pc); - } - return; - } - - /* - * Print table showing the code offset, source offset, and source - * length for each command. These are encoded as a sequence of bytes. - */ - - fprintf(stdout, " 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 int) (*codeDeltaNext) == (unsigned int) 0xFF) { - codeDeltaNext++; - delta = TclGetInt4AtPtr(codeDeltaNext); - codeDeltaNext += 4; - } else { - delta = TclGetInt1AtPtr(codeDeltaNext); - codeDeltaNext++; - } - codeOffset += delta; - - if ((unsigned int) (*codeLengthNext) == (unsigned int) 0xFF) { - codeLengthNext++; - codeLen = TclGetInt4AtPtr(codeLengthNext); - codeLengthNext += 4; - } else { - codeLen = TclGetInt1AtPtr(codeLengthNext); - codeLengthNext++; - } - - if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) { - srcDeltaNext++; - delta = TclGetInt4AtPtr(srcDeltaNext); - srcDeltaNext += 4; - } else { - delta = TclGetInt1AtPtr(srcDeltaNext); - srcDeltaNext++; - } - srcOffset += delta; - - if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) { - srcLengthNext++; - srcLen = TclGetInt4AtPtr(srcLengthNext); - srcLengthNext += 4; - } else { - srcLen = TclGetInt1AtPtr(srcLengthNext); - srcLengthNext++; - } - - fprintf(stdout, "%s%4d: pc %d-%d, source %d-%d", - ((i % 2)? " " : "\n "), - (i+1), codeOffset, (codeOffset + codeLen - 1), - srcOffset, (srcOffset + srcLen - 1)); - } - if ((numCmds > 0) && ((numCmds % 2) != 0)) { - fprintf(stdout, "\n"); - } - - /* - * 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 int) (*codeDeltaNext) == (unsigned int) 0xFF) { - codeDeltaNext++; - delta = TclGetInt4AtPtr(codeDeltaNext); - codeDeltaNext += 4; - } else { - delta = TclGetInt1AtPtr(codeDeltaNext); - codeDeltaNext++; - } - codeOffset += delta; - - if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) { - srcDeltaNext++; - delta = TclGetInt4AtPtr(srcDeltaNext); - srcDeltaNext += 4; - } else { - delta = TclGetInt1AtPtr(srcDeltaNext); - srcDeltaNext++; - } - srcOffset += delta; - - if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) { - srcLengthNext++; - srcLen = TclGetInt4AtPtr(srcLengthNext); - srcLengthNext += 4; - } else { - srcLen = TclGetInt1AtPtr(srcLengthNext); - srcLengthNext++; - } - - /* - * Print instructions before command i. - */ - - while ((pc-codeStart) < codeOffset) { - fprintf(stdout, " "); - pc += TclPrintInstruction(codePtr, pc); - } - - fprintf(stdout, " Command %d: ", (i+1)); - TclPrintSource(stdout, (codePtr->source + srcOffset), - TclMin(srcLen, 70)); - fprintf(stdout, "\n"); - } - if (pc < codeLimit) { - /* - * Print instructions after the last command. - */ - - while (pc < codeLimit) { - fprintf(stdout, " "); - pc += TclPrintInstruction(codePtr, pc); - } - } -} - -/* - *---------------------------------------------------------------------- - * - * 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(codePtr, pc) - ByteCode* codePtr; /* Bytecode containing the instruction. */ - unsigned char *pc; /* Points to first byte of instruction. */ -{ - Proc *procPtr = codePtr->procPtr; - unsigned char opCode = *pc; - register InstructionDesc *instDesc = &instructionTable[opCode]; - unsigned char *codeStart = codePtr->codeStart; - unsigned int pcOffset = (pc - codeStart); - int opnd, elemLen, i, j; - Tcl_Obj *elemPtr; + *----------------------------------------------------------------------- + * + * 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(interp, objPtr) + 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. */ +{ + Interp *iPtr = (Interp *) interp; + CompileEnv compEnv; /* Compilation environment structure + * allocated in frame. */ + LiteralTable *localTablePtr = &(compEnv.localLitTable); + register AuxData *auxDataPtr; + LiteralEntry *entryPtr; + register int i; + int length, nested, result; char *string; - - fprintf(stdout, "(%u) %s ", pcOffset, instDesc->name); - for (i = 0; i < instDesc->numOperands; i++) { - switch (instDesc->opTypes[i]) { - case OPERAND_INT1: - opnd = TclGetInt1AtPtr(pc+1+i); - if ((i == 0) && ((opCode == INST_JUMP1) - || (opCode == INST_JUMP_TRUE1) - || (opCode == INST_JUMP_FALSE1))) { - fprintf(stdout, "%d # pc %u", opnd, (pcOffset + opnd)); - } else { - fprintf(stdout, "%d", opnd); - } - break; - case OPERAND_INT4: - opnd = TclGetInt4AtPtr(pc+1+i); - if ((i == 0) && ((opCode == INST_JUMP4) - || (opCode == INST_JUMP_TRUE4) - || (opCode == INST_JUMP_FALSE4))) { - fprintf(stdout, "%d # pc %u", opnd, (pcOffset + opnd)); - } else { - fprintf(stdout, "%d", opnd); - } - break; - case OPERAND_UINT1: - opnd = TclGetUInt1AtPtr(pc+1+i); - if ((i == 0) && (opCode == INST_PUSH1)) { - elemPtr = codePtr->objArrayPtr[opnd]; - string = Tcl_GetStringFromObj(elemPtr, &elemLen); - fprintf(stdout, "%u # ", (unsigned int) opnd); - TclPrintSource(stdout, string, TclMin(elemLen, 40)); - } else if ((i == 0) && ((opCode == INST_LOAD_SCALAR1) - || (opCode == INST_LOAD_ARRAY1) - || (opCode == INST_STORE_SCALAR1) - || (opCode == INST_STORE_ARRAY1))) { - int localCt = procPtr->numCompiledLocals; - CompiledLocal *localPtr = procPtr->firstLocalPtr; - if (opnd >= localCt) { - panic("TclPrintInstruction: bad local var index %u (%u locals)\n", - (unsigned int) opnd, localCt); - return instDesc->numBytes; - } - for (j = 0; j < opnd; j++) { - localPtr = localPtr->nextPtr; - } - if (localPtr->isTemp) { - fprintf(stdout, "%u # temp var %u", - (unsigned int) opnd, (unsigned int) opnd); - } else { - fprintf(stdout, "%u # var ", (unsigned int) opnd); - TclPrintSource(stdout, localPtr->name, 40); - } - } else { - fprintf(stdout, "%u ", (unsigned int) opnd); - } - break; - case OPERAND_UINT4: - opnd = TclGetUInt4AtPtr(pc+1+i); - if (opCode == INST_PUSH4) { - elemPtr = codePtr->objArrayPtr[opnd]; - string = Tcl_GetStringFromObj(elemPtr, &elemLen); - fprintf(stdout, "%u # ", opnd); - TclPrintSource(stdout, string, TclMin(elemLen, 40)); - } else if ((i == 0) && ((opCode == INST_LOAD_SCALAR4) - || (opCode == INST_LOAD_ARRAY4) - || (opCode == INST_STORE_SCALAR4) - || (opCode == INST_STORE_ARRAY4))) { - int localCt = procPtr->numCompiledLocals; - CompiledLocal *localPtr = procPtr->firstLocalPtr; - if (opnd >= localCt) { - panic("TclPrintInstruction: bad local var index %u (%u locals)\n", - (unsigned int) opnd, localCt); - return instDesc->numBytes; - } - for (j = 0; j < opnd; j++) { - localPtr = localPtr->nextPtr; - } - if (localPtr->isTemp) { - fprintf(stdout, "%u # temp var %u", - (unsigned int) opnd, (unsigned int) opnd); - } else { - fprintf(stdout, "%u # var ", (unsigned int) opnd); - TclPrintSource(stdout, localPtr->name, 40); - } - } else { - fprintf(stdout, "%u ", (unsigned int) opnd); - } - break; - case OPERAND_NONE: - default: - break; - } - } - fprintf(stdout, "\n"); - return instDesc->numBytes; + + if (!traceInitialized) { + if (Tcl_LinkVar(interp, "tcl_traceCompile", + (char *) &tclTraceCompile, TCL_LINK_INT) != TCL_OK) { + panic("SetByteCodeFromAny: unable to create link for tcl_traceCompile variable"); + } + traceInitialized = 1; + } + + if (iPtr->evalFlags & TCL_BRACKET_TERM) { + nested = 1; + } else { + nested = 0; + } + string = Tcl_GetStringFromObj(objPtr, &length); + TclInitCompileEnv(interp, &compEnv, string, length); + result = TclCompileScript(interp, string, length, nested, &compEnv); + if (result != TCL_OK) { + /* + * Compilation errors. + */ + + entryPtr = compEnv.literalArrayPtr; + for (i = 0; i < compEnv.literalArrayNext; i++) { + TclReleaseLiteral(interp, entryPtr->objPtr); + entryPtr++; + } +#ifdef TCL_COMPILE_DEBUG + TclVerifyGlobalLiteralTable(iPtr); +#endif /*TCL_COMPILE_DEBUG*/ + + auxDataPtr = compEnv.auxDataArrayPtr; + for (i = 0; i < compEnv.auxDataArrayNext; i++) { + if (auxDataPtr->type->freeProc != NULL) { + auxDataPtr->type->freeProc(auxDataPtr->clientData); + } + auxDataPtr++; + } + goto done; + } + + /* + * Successful compilation. Add a "done" instruction at the end. + */ + + compEnv.numSrcBytes = iPtr->termOffset; + TclEmitOpcode(INST_DONE, &compEnv); + + /* + * 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*/ + TclInitByteCodeObj(objPtr, &compEnv); +#ifdef TCL_COMPILE_DEBUG + if (tclTraceCompile == 2) { + TclPrintByteCodeObj(interp, objPtr); + } +#endif /* TCL_COMPILE_DEBUG */ + + /* + * Free storage allocated during compilation. + */ + + done: + if (localTablePtr->buckets != localTablePtr->staticBuckets) { + ckfree((char *) localTablePtr->buckets); + } + TclFreeCompileEnv(&compEnv); + return result; } /* *---------------------------------------------------------------------- * - * TclPrintSource -- + * DupByteCodeInternalRep -- * - * 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. + * 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: - * Outputs characters to the specified file. + * None. * *---------------------------------------------------------------------- */ -void -TclPrintSource(outFile, string, maxChars) - FILE *outFile; /* The file to print the source to. */ - char *string; /* The string to print. */ - int maxChars; /* Maximum number of chars to print. */ -{ - register char *p; - register int i = 0; - - if (string == NULL) { - fprintf(outFile, "\"\""); - return; - } - - fprintf(outFile, "\""); - p = string; - for (; (*p != '\0') && (i < maxChars); p++, i++) { - switch (*p) { - case '"': - fprintf(outFile, "\\\""); - continue; - case '\f': - fprintf(outFile, "\\f"); - continue; - case '\n': - fprintf(outFile, "\\n"); - continue; - case '\r': - fprintf(outFile, "\\r"); - continue; - case '\t': - fprintf(outFile, "\\t"); - continue; - case '\v': - fprintf(outFile, "\\v"); - continue; - default: - fprintf(outFile, "%c", *p); - continue; - } - } - fprintf(outFile, "\""); +static void +DupByteCodeInternalRep(srcPtr, copyPtr) + Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ + Tcl_Obj *copyPtr; /* Object with internal rep to set. */ +{ + return; } /* *---------------------------------------------------------------------- * @@ -914,216 +431,114 @@ } /* *---------------------------------------------------------------------- * - * CleanupByteCode -- + * 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 and objPtr->internalRep.otherValuePtr NULL. Also - * decrements the ref counts on each object in its object array, - * and frees its auxiliary data items. + * Frees objPtr's bytecode internal representation and sets its type + * and objPtr->internalRep.otherValuePtr NULL. Also releases its + * literals and frees its auxiliary data items. * *---------------------------------------------------------------------- */ void TclCleanupByteCode(codePtr) - ByteCode *codePtr; /* ByteCode to free. */ + register ByteCode *codePtr; /* Points to the ByteCode to free. */ { - Tcl_Obj **objArrayPtr = codePtr->objArrayPtr; - int numObjects = codePtr->numObjects; + Tcl_Interp *interp = (Tcl_Interp *) *codePtr->interpHandle; + int numLitObjects = codePtr->numLitObjects; int numAuxDataItems = codePtr->numAuxDataItems; + register Tcl_Obj **objArrayPtr; register AuxData *auxDataPtr; - register Tcl_Obj *elemPtr; - register int i; + int i; +#ifdef TCL_COMPILE_STATS -#ifdef TCL_COMPILE_STATS - tclCurrentSourceBytes -= (double) codePtr->numSrcChars; - tclCurrentCodeBytes -= (double) codePtr->totalSize; + if (interp != NULL) { + ByteCodeStats *statsPtr; + Tcl_Time destroyTime; + int lifetimeSec, lifetimeMicroSec, log2; + + statsPtr = &((Interp *) interp)->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; + + TclpGetTime(&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 on the objects in its - * object array, 2) call the free procs for the auxiliary data items, - * and 3) free the ByteCode structure's heap object. - */ - - for (i = 0; i < numObjects; i++) { - elemPtr = objArrayPtr[i]; - TclDecrRefCount(elemPtr); - } - - auxDataPtr = codePtr->auxDataArrayPtr; - for (i = 0; i < numAuxDataItems; i++) { - if (auxDataPtr->freeProc != NULL) { - auxDataPtr->freeProc(auxDataPtr->clientData); - } - auxDataPtr++; - } - - ckfree((char *) codePtr); -} - -/* - *---------------------------------------------------------------------- - * - * 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(srcPtr, copyPtr) - Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ - Tcl_Obj *copyPtr; /* Object with internal rep to set. */ -{ - return; -} - -/* - *----------------------------------------------------------------------- - * - * 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(interp, objPtr) - Tcl_Interp *interp; /* The interpreter for which the code is - * compiled. */ - Tcl_Obj *objPtr; /* The object to convert. */ -{ - Interp *iPtr = (Interp *) interp; - char *string; - CompileEnv compEnv; /* Compilation environment structure - * allocated in frame. */ - AuxData *auxDataPtr; - register int i; - int length, result; - - if (!traceInitialized) { - if (Tcl_LinkVar(interp, "tcl_traceCompile", - (char *) &tclTraceCompile, TCL_LINK_INT) != TCL_OK) { - panic("SetByteCodeFromAny: unable to create link for tcl_traceCompile variable"); - } - traceInitialized = 1; - } - - string = Tcl_GetStringFromObj(objPtr, &length); - TclInitCompileEnv(interp, &compEnv, string); - result = TclCompileString(interp, string, string+length, - iPtr->evalFlags, &compEnv); - if (result == TCL_OK) { - /* - * Add a "done" instruction at the end of the instruction sequence. - */ - - TclEmitOpcode(INST_DONE, &compEnv); - - /* - * Convert the object to a ByteCode object. - */ - - TclInitByteCodeObj(objPtr, &compEnv); - } else { - /* - * Compilation errors. Decrement the ref counts on any objects in - * the object array and free any aux data items prior to freeing - * the compilation environment. - */ - - for (i = 0; i < compEnv.objArrayNext; i++) { - Tcl_Obj *elemPtr = compEnv.objArrayPtr[i]; - Tcl_DecrRefCount(elemPtr); - } - - auxDataPtr = compEnv.auxDataArrayPtr; - for (i = 0; i < compEnv.auxDataArrayNext; i++) { - if (auxDataPtr->freeProc != NULL) { - auxDataPtr->freeProc(auxDataPtr->clientData); - } - auxDataPtr++; - } - } - TclFreeCompileEnv(&compEnv); - - if (result == TCL_OK) { - if (tclTraceCompile == 2) { - TclPrintByteCodeObj(interp, objPtr); - } - } - return result; -} - -/* - *---------------------------------------------------------------------- - * - * UpdateStringOfByteCode -- - * - * Part of the bytecode Tcl object type implementation. Called to - * update the string representation for a byte code object. - * Note: This procedure does not free an existing old string rep - * so storage will be lost if this has not already been done. - * - * Results: - * None. - * - * Side effects: - * Generates a panic. - * - *---------------------------------------------------------------------- - */ - -static void -UpdateStringOfByteCode(objPtr) - register Tcl_Obj *objPtr; /* ByteCode object with string rep that - * needs updating. */ -{ - /* - * This procedure is never invoked since the internal representation of - * a bytecode object is never modified. - */ - - panic("UpdateStringOfByteCode should never be called."); + * 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, and 3) free the ByteCode structure's heap object. + */ + + if (interp != NULL) { + /* + * If the interp has already been freed, then Tcl will have already + * forcefully released all the literals used by ByteCodes compiled + * with respect to that interp. + */ + + objArrayPtr = codePtr->objArrayPtr; + for (i = 0; i < numLitObjects; i++) { + /* + * TclReleaseLiteral sets a ByteCode's object array entry NULL to + * indicate that it has already freed the literal. + */ + + if (*objArrayPtr != NULL) { + TclReleaseLiteral(interp, *objArrayPtr); + } + objArrayPtr++; + } + } + + auxDataPtr = codePtr->auxDataArrayPtr; + for (i = 0; i < numAuxDataItems; i++) { + if (auxDataPtr->type->freeProc != NULL) { + (*auxDataPtr->type->freeProc)(auxDataPtr->clientData); + } + auxDataPtr++; + } + + TclHandleRelease(codePtr->interpHandle); + ckfree((char *) codePtr); } /* *---------------------------------------------------------------------- * @@ -1140,48 +555,46 @@ * *---------------------------------------------------------------------- */ void -TclInitCompileEnv(interp, envPtr, string) +TclInitCompileEnv(interp, envPtr, string, numBytes) Tcl_Interp *interp; /* The interpreter for which a CompileEnv * structure is initialized. */ register CompileEnv *envPtr; /* Points to the CompileEnv structure to * initialize. */ char *string; /* The source string to be compiled. */ + int numBytes; /* Number of bytes in source string. */ { Interp *iPtr = (Interp *) interp; envPtr->iPtr = iPtr; envPtr->source = string; + envPtr->numSrcBytes = numBytes; envPtr->procPtr = iPtr->compiledProcPtr; envPtr->numCommands = 0; - envPtr->excRangeDepth = 0; - envPtr->maxExcRangeDepth = 0; + envPtr->exceptDepth = 0; + envPtr->maxExceptDepth = 0; envPtr->maxStackDepth = 0; - Tcl_InitHashTable(&(envPtr->objTable), TCL_STRING_KEYS); - envPtr->pushSimpleWords = 1; - envPtr->wordIsSimple = 0; - envPtr->numSimpleWordChars = 0; + TclInitLiteralTable(&(envPtr->localLitTable)); envPtr->exprIsJustVarRef = 0; envPtr->exprIsComparison = 0; - envPtr->termOffset = 0; envPtr->codeStart = envPtr->staticCodeSpace; envPtr->codeNext = envPtr->codeStart; envPtr->codeEnd = (envPtr->codeStart + COMPILEENV_INIT_CODE_BYTES); envPtr->mallocedCodeArray = 0; - envPtr->objArrayPtr = envPtr->staticObjArraySpace; - envPtr->objArrayNext = 0; - envPtr->objArrayEnd = COMPILEENV_INIT_NUM_OBJECTS; - envPtr->mallocedObjArray = 0; - - envPtr->excRangeArrayPtr = envPtr->staticExcRangeArraySpace; - envPtr->excRangeArrayNext = 0; - envPtr->excRangeArrayEnd = COMPILEENV_INIT_EXCEPT_RANGES; - envPtr->mallocedExcRangeArray = 0; + envPtr->literalArrayPtr = envPtr->staticLiteralSpace; + envPtr->literalArrayNext = 0; + envPtr->literalArrayEnd = COMPILEENV_INIT_NUM_OBJECTS; + envPtr->mallocedLiteralArray = 0; + + envPtr->exceptArrayPtr = envPtr->staticExceptArraySpace; + 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; @@ -1199,44 +612,884 @@ * Free the storage allocated in a CompileEnv compilation environment * structure. * * Results: * None. - * + * * Side effects: * Allocated storage in the CompileEnv structure is freed. Note that - * ref counts for Tcl objects in its object table are not decremented. - * In addition, any storage referenced by any auxiliary data items - * in the CompileEnv structure are not freed either. The expectation - * is that when compilation is successful, "ownership" (i.e., the - * pointers to) these objects and aux data items will just be handed - * over to the corresponding ByteCode structure. + * 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(envPtr) register CompileEnv *envPtr; /* Points to the CompileEnv structure. */ { - Tcl_DeleteHashTable(&(envPtr->objTable)); if (envPtr->mallocedCodeArray) { ckfree((char *) envPtr->codeStart); } - if (envPtr->mallocedObjArray) { - ckfree((char *) envPtr->objArrayPtr); + if (envPtr->mallocedLiteralArray) { + ckfree((char *) envPtr->literalArrayPtr); } - if (envPtr->mallocedExcRangeArray) { - ckfree((char *) envPtr->excRangeArrayPtr); + if (envPtr->mallocedExceptArray) { + ckfree((char *) envPtr->exceptArrayPtr); } if (envPtr->mallocedCmdMap) { ckfree((char *) envPtr->cmdMapPtr); } if (envPtr->mallocedAuxDataArray) { ckfree((char *) envPtr->auxDataArrayPtr); } } + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * interp->termOffset is set to the offset of the character in the + * script just after the last one successfully processed; this will be + * the offset of the ']' if (flags & TCL_BRACKET_TERM). + * envPtr->maxStackDepth is set to the maximum number of stack elements + * needed to execute the script's commands. + * + * Side effects: + * Adds instructions to envPtr to evaluate the script at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileScript(interp, script, numBytes, nested, envPtr) + Tcl_Interp *interp; /* Used for error and status reporting. */ + 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. */ + int nested; /* Non-zero means this is a nested command: + * close bracket ']' should be considered a + * command terminator. If zero, close + * bracket has no special meaning. */ + CompileEnv *envPtr; /* Holds resulting instructions. */ +{ + Interp *iPtr = (Interp *) interp; + Tcl_Parse parse; + int maxDepth = 0; /* Maximum number of stack elements needed + * to execute all cmds. */ + int lastTopLevelCmdIndex = -1; + /* Index of most recent toplevel command in + * the command location table. Initialized + * to avoid compiler warning. */ + int startCodeOffset = -1; /* Offset of first byte of current command's + * code. Init. to avoid compiler warning. */ + unsigned char *entryCodeNext = envPtr->codeNext; + char *p, *next; + Namespace *cmdNsPtr; + Command *cmdPtr; + Tcl_Token *tokenPtr; + int bytesLeft, isFirstCmd, gotParse, wordIdx, currCmdIndex; + int commandLength, objIndex, code; + char prev; + Tcl_DString ds; + + Tcl_DStringInit(&ds); + + if (numBytes < 0) { + numBytes = strlen(script); + } + Tcl_ResetResult(interp); + isFirstCmd = 1; + + /* + * Each iteration through the following loop compiles the next + * command from the script. + */ + + p = script; + bytesLeft = numBytes; + gotParse = 0; + while (bytesLeft > 0) { + if (Tcl_ParseCommand(interp, p, bytesLeft, nested, &parse) != TCL_OK) { + code = TCL_ERROR; + goto error; + } + gotParse = 1; + if (parse.numWords > 0) { + /* + * If not the first command, pop the previous command's result + * and, if we're compiling a top level command, update the last + * command's code size to account for the pop instruction. + */ + + if (!isFirstCmd) { + TclEmitOpcode(INST_POP, envPtr); + if (!nested) { + envPtr->cmdMapPtr[lastTopLevelCmdIndex].numCodeBytes = + (envPtr->codeNext - envPtr->codeStart) + - startCodeOffset; + } + } + + /* + * Determine the actual length of the command. + */ + + commandLength = parse.commandSize; + prev = '\0'; + if (commandLength > 0) { + prev = parse.commandStart[commandLength-1]; + } + if (((parse.commandStart+commandLength) != (script+numBytes)) + || ((prev=='\n') || (nested && (prev==']')))) { + /* + * The command didn't end at the end of the script (i.e. it + * ended at a terminator character such as ";". Reduce the + * length by one so that the trace message doesn't include + * the terminator character. + */ + + commandLength -= 1; + } + + /* + * If tracing, print a line for each top level command compiled. + */ + + if ((tclTraceCompile >= 1) + && !nested && (envPtr->procPtr == NULL)) { + fprintf(stdout, " Compiling: "); + TclPrintSource(stdout, parse.commandStart, + TclMin(commandLength, 55)); + fprintf(stdout, "\n"); + } + + /* + * Each iteration of the following loop compiles one word + * from the command. + */ + + envPtr->numCommands++; + currCmdIndex = (envPtr->numCommands - 1); + if (!nested) { + lastTopLevelCmdIndex = currCmdIndex; + } + startCodeOffset = (envPtr->codeNext - envPtr->codeStart); + EnterCmdStartData(envPtr, currCmdIndex, + (parse.commandStart - envPtr->source), startCodeOffset); + + for (wordIdx = 0, tokenPtr = parse.tokenPtr; + wordIdx < parse.numWords; + wordIdx++, tokenPtr += (tokenPtr->numComponents + 1)) { + if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { + /* + * If this is the first word and the command has a + * compile procedure, let it compile the command. + */ + + if (wordIdx == 0) { + if (envPtr->procPtr != NULL) { + cmdNsPtr = envPtr->procPtr->cmdPtr->nsPtr; + } else { + cmdNsPtr = NULL; /* use current NS */ + } + + /* + * We copy the string before trying to find the command + * by name. We used to modify the string in place, but + * this is not safe because the name resolution + * handlers could have side effects that rely on the + * unmodified string. + */ + + Tcl_DStringSetLength(&ds, 0); + Tcl_DStringAppend(&ds, tokenPtr[1].start, + tokenPtr[1].size); + + cmdPtr = (Command *) Tcl_FindCommand(interp, + Tcl_DStringValue(&ds), + (Tcl_Namespace *) cmdNsPtr, /*flags*/ 0); + + if ((cmdPtr != NULL) + && (cmdPtr->compileProc != NULL) + && !(iPtr->flags & DONT_COMPILE_CMDS_INLINE)) { + code = (*(cmdPtr->compileProc))(interp, &parse, + envPtr); + if (code == TCL_OK) { + maxDepth = TclMax(envPtr->maxStackDepth, + maxDepth); + goto finishCommand; + } else if (code == TCL_OUT_LINE_COMPILE) { + /* do nothing */ + } else { /* an error */ + goto error; + } + } + + /* + * No compile procedure so push the word. If the + * command was found, push a CmdName object to + * reduce runtime lookups. + */ + + objIndex = TclRegisterLiteral(envPtr, + tokenPtr[1].start, tokenPtr[1].size, + /*onHeap*/ 0); + if (cmdPtr != NULL) { + TclSetCmdNameObj(interp, + envPtr->literalArrayPtr[objIndex].objPtr, + cmdPtr); + } + } else { + objIndex = TclRegisterLiteral(envPtr, + tokenPtr[1].start, tokenPtr[1].size, + /*onHeap*/ 0); + } + TclEmitPush(objIndex, envPtr); + maxDepth = TclMax((wordIdx + 1), maxDepth); + } else { + /* + * The word is not a simple string of characters. + */ + + code = TclCompileTokens(interp, tokenPtr+1, + tokenPtr->numComponents, envPtr); + if (code != TCL_OK) { + goto error; + } + maxDepth = TclMax((wordIdx + envPtr->maxStackDepth), + maxDepth); + } + } + + /* + * Emit an invoke instruction for the command. We skip this + * if a compile procedure was found for the command. + */ + + if (wordIdx > 0) { + if (wordIdx <= 255) { + TclEmitInstInt1(INST_INVOKE_STK1, wordIdx, envPtr); + } else { + TclEmitInstInt4(INST_INVOKE_STK4, wordIdx, envPtr); + } + } + + /* + * Update the compilation environment structure and record the + * offsets of the source and code for the command. + */ + + finishCommand: + EnterCmdExtentData(envPtr, currCmdIndex, commandLength, + (envPtr->codeNext-envPtr->codeStart) - startCodeOffset); + isFirstCmd = 0; + } /* end if parse.numWords > 0 */ + + /* + * Advance to the next command in the script. + */ + + next = parse.commandStart + parse.commandSize; + bytesLeft -= (next - p); + p = next; + Tcl_FreeParse(&parse); + gotParse = 0; + if (nested && (p[-1] == ']')) { + /* + * We get here in the special case where TCL_BRACKET_TERM was + * set in the interpreter and we reached a close bracket in the + * script. Stop compilation. + */ + + break; + } + } + + /* + * If the source script yielded no instructions (e.g., if it was empty), + * push an empty string as the command's result. + */ + + if (envPtr->codeNext == entryCodeNext) { + TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*alreadyAlloced*/ 0), + envPtr); + maxDepth = 1; + } + + if ((nested != 0) && (p > script) && (p[-1] == ']')) { + iPtr->termOffset = (p - 1) - script; + } else { + iPtr->termOffset = (p - script); + } + envPtr->maxStackDepth = maxDepth; + Tcl_DStringFree(&ds); + return TCL_OK; + + error: + /* + * Generate various pieces of error information, such as the line + * number where the error occurred and information to add to the + * errorInfo variable. Then free resources that had been allocated + * to the command. + */ + + commandLength = parse.commandSize; + prev = '\0'; + if (commandLength > 0) { + prev = parse.commandStart[commandLength-1]; + } + if (((parse.commandStart+commandLength) != (script+numBytes)) + || ((prev == '\n') || (nested && (prev == ']')))) { + /* + * The command where the error occurred didn't end at the end + * of the script (i.e. it ended at a terminator character such + * as ";". Reduce the length by one so that the error message + * doesn't include the terminator character. + */ + + commandLength -= 1; + } + LogCompilationInfo(interp, script, parse.commandStart, commandLength); + if (gotParse) { + Tcl_FreeParse(&parse); + } + iPtr->termOffset = (p - script); + envPtr->maxStackDepth = maxDepth; + Tcl_DStringFree(&ds); + return code; +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to evaluate the tokens. + * + * Side effects: + * Instructions are added to envPtr to push and evaluate the tokens + * at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileTokens(interp, tokenPtr, count, envPtr) + 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]; + char *name, *p; + int numObjsToConcat, nameBytes, hasNsQualifiers, localVar; + int length, maxDepth, depthForVar, i, code; + unsigned char *entryCodeNext = envPtr->codeNext; + + Tcl_DStringInit(&textBuffer); + maxDepth = 0; + numObjsToConcat = 0; + for ( ; count > 0; count--, tokenPtr++) { + switch (tokenPtr->type) { + case TCL_TOKEN_TEXT: + Tcl_DStringAppend(&textBuffer, tokenPtr->start, + tokenPtr->size); + break; + + case TCL_TOKEN_BS: + length = Tcl_UtfBackslash(tokenPtr->start, (int *) NULL, + buffer); + Tcl_DStringAppend(&textBuffer, buffer, length); + break; + + case TCL_TOKEN_COMMAND: + /* + * Push any accumulated chars appearing before the command. + */ + + if (Tcl_DStringLength(&textBuffer) > 0) { + int literal; + + literal = TclRegisterLiteral(envPtr, + Tcl_DStringValue(&textBuffer), + Tcl_DStringLength(&textBuffer), /*onHeap*/ 0); + TclEmitPush(literal, envPtr); + numObjsToConcat++; + maxDepth = TclMax(numObjsToConcat, maxDepth); + Tcl_DStringFree(&textBuffer); + } + + code = TclCompileScript(interp, tokenPtr->start+1, + tokenPtr->size-2, /*nested*/ 1, envPtr); + if (code != TCL_OK) { + goto error; + } + maxDepth = TclMax((numObjsToConcat + envPtr->maxStackDepth), + maxDepth); + numObjsToConcat++; + break; + + case TCL_TOKEN_VARIABLE: + /* + * Push any accumulated chars appearing before the $. + */ + + if (Tcl_DStringLength(&textBuffer) > 0) { + int literal; + + literal = TclRegisterLiteral(envPtr, + Tcl_DStringValue(&textBuffer), + Tcl_DStringLength(&textBuffer), /*onHeap*/ 0); + TclEmitPush(literal, envPtr); + numObjsToConcat++; + maxDepth = TclMax(numObjsToConcat, maxDepth); + Tcl_DStringFree(&textBuffer); + } + + /* + * Check if the name contains any namespace qualifiers. + */ + + name = tokenPtr[1].start; + nameBytes = tokenPtr[1].size; + hasNsQualifiers = 0; + for (i = 0, p = name; i < nameBytes; i++, p++) { + if ((*p == ':') && (i < (nameBytes-1)) + && (*(p+1) == ':')) { + hasNsQualifiers = 1; + break; + } + } + + /* + * Either push the variable's name, or find its index in + * the array of local variables in a procedure frame. + */ + + depthForVar = 0; + if ((envPtr->procPtr == NULL) || hasNsQualifiers) { + localVar = -1; + TclEmitPush(TclRegisterLiteral(envPtr, name, nameBytes, + /*onHeap*/ 0), envPtr); + depthForVar = 1; + } else { + localVar = TclFindCompiledLocal(name, nameBytes, + /*create*/ 0, /*flags*/ 0, envPtr->procPtr); + if (localVar < 0) { + TclEmitPush(TclRegisterLiteral(envPtr, name, + nameBytes, /*onHeap*/ 0), envPtr); + depthForVar = 1; + } + } + + /* + * Emit instructions to load the variable. + */ + + if (tokenPtr->numComponents == 1) { + if (localVar < 0) { + TclEmitOpcode(INST_LOAD_SCALAR_STK, envPtr); + } else if (localVar <= 255) { + TclEmitInstInt1(INST_LOAD_SCALAR1, localVar, + envPtr); + } else { + TclEmitInstInt4(INST_LOAD_SCALAR4, localVar, + envPtr); + } + } else { + code = TclCompileTokens(interp, tokenPtr+2, + tokenPtr->numComponents-1, envPtr); + if (code != TCL_OK) { + sprintf(buffer, + "\n (parsing index for array \"%.*s\")", + ((nameBytes > 100)? 100 : nameBytes), name); + Tcl_AddObjErrorInfo(interp, buffer, -1); + goto error; + } + depthForVar += envPtr->maxStackDepth; + 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); + } + } + maxDepth = TclMax(numObjsToConcat + depthForVar, maxDepth); + numObjsToConcat++; + count -= tokenPtr->numComponents; + tokenPtr += tokenPtr->numComponents; + break; + + default: + panic("Unexpected token type in TclCompileTokens"); + } + } + + /* + * Push any accumulated characters appearing at the end. + */ + + if (Tcl_DStringLength(&textBuffer) > 0) { + int literal; + + literal = TclRegisterLiteral(envPtr, Tcl_DStringValue(&textBuffer), + Tcl_DStringLength(&textBuffer), /*onHeap*/ 0); + TclEmitPush(literal, envPtr); + numObjsToConcat++; + maxDepth = TclMax(numObjsToConcat, maxDepth); + } + + /* + * If necessary, concatenate the parts of the word. + */ + + while (numObjsToConcat > 255) { + TclEmitInstInt1(INST_CONCAT1, 255, envPtr); + numObjsToConcat -= 254; /* concat pushes 1 obj, the result */ + } + if (numObjsToConcat > 1) { + TclEmitInstInt1(INST_CONCAT1, numObjsToConcat, envPtr); + } + + /* + * If the tokens yielded no instructions, push an empty string. + */ + + if (envPtr->codeNext == entryCodeNext) { + TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*alreadyAlloced*/ 0), + envPtr); + maxDepth = 1; + } + Tcl_DStringFree(&textBuffer); + envPtr->maxStackDepth = maxDepth; + return TCL_OK; + + error: + Tcl_DStringFree(&textBuffer); + envPtr->maxStackDepth = maxDepth; + return code; +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the tokens. + * + * Side effects: + * Instructions are added to envPtr to execute the tokens at runtime. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileCmdWord(interp, tokenPtr, count, envPtr) + 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. */ +{ + int code; + + /* + * Handle the common case: if there is a single text token, compile it + * into an inline sequence of instructions. + */ + + envPtr->maxStackDepth = 0; + if ((count == 1) && (tokenPtr->type == TCL_TOKEN_TEXT)) { + code = TclCompileScript(interp, tokenPtr->start, tokenPtr->size, + /*nested*/ 0, envPtr); + return code; + } + + /* + * 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. + */ + + code = TclCompileTokens(interp, tokenPtr, count, envPtr); + if (code != TCL_OK) { + return code; + } + TclEmitOpcode(INST_EVAL_STK, envPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * envPtr->maxStackDepth is updated with the maximum number of stack + * elements needed to execute the expression. + * + * Side effects: + * Instructions are added to envPtr to execute the expression. + * + *---------------------------------------------------------------------- + */ + +int +TclCompileExprWords(interp, tokenPtr, numWords, envPtr) + 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, *partPtr; + JumpFixup jumpFixup; + int maxDepth, doExprInline, range, numBytes, i, j, code; + char *script; + char saveChar; + int saveExprIsJustVarRef = envPtr->exprIsJustVarRef; + int saveExprIsComparison = envPtr->exprIsComparison; + + envPtr->maxStackDepth = 0; + maxDepth = 0; + range = -1; + code = TCL_OK; + + /* + * If the expression is a single word that doesn't require + * substitutions, just compile it's string into inline instructions. + */ + + if ((numWords == 1) && (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD)) { + /* + * Temporarily overwrite the character just after the end of the + * string with a 0 byte. + */ + + script = tokenPtr[1].start; + numBytes = tokenPtr[1].size; + saveChar = script[numBytes]; + script[numBytes] = 0; + code = TclCompileExpr(interp, script, numBytes, envPtr); + script[numBytes] = saveChar; + return code; + } + + /* + * Multiple words or the single word requires substitutions. We may + * need to call expr's command proc at runtime. This often recompiles + * the expression each time and is slow. However, there are some + * circumstances where we can still compile inline code "optimistically" + * and check for type errors during execution that signal when double + * substitutions must be done. + */ + + doExprInline = 1; + wordPtr = tokenPtr; + for (i = 0; ((i < numWords) && doExprInline); i++) { + if (wordPtr->type == TCL_TOKEN_WORD) { + for (j = 0, partPtr = wordPtr+1; j < wordPtr->numComponents; + j++, partPtr++) { + if ((partPtr->type == TCL_TOKEN_BS) + || (partPtr->type == TCL_TOKEN_COMMAND)) { + doExprInline = 0; + break; + } + } + } + wordPtr += (wordPtr->numComponents + 1); + } + + /* + * If only variable substitutions appear (no backslash or command + * substitutions), inline compile the expr inside a "catch" so that if + * there is any error, we call expr's command proc at runtime. + */ + + if (doExprInline) { + Tcl_DString exprBuffer; + int startCodeOffset = (envPtr->codeNext - envPtr->codeStart); + int startExceptNext = envPtr->exceptArrayNext; + + envPtr->exceptDepth++; + envPtr->maxExceptDepth = + TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth); + range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); + TclEmitInstInt4(INST_BEGIN_CATCH4, range, envPtr); + + Tcl_DStringInit(&exprBuffer); + wordPtr = tokenPtr; + for (i = 0; i < numWords; i++) { + if (i > 0) { + Tcl_DStringAppend(&exprBuffer, " ", 1); + } + for (j = 0, partPtr = wordPtr+1; j < wordPtr->numComponents; + j++, partPtr++) { + switch (partPtr->type) { + case TCL_TOKEN_TEXT: + Tcl_DStringAppend(&exprBuffer, partPtr->start, + partPtr->size); + break; + + case TCL_TOKEN_VARIABLE: + Tcl_DStringAppend(&exprBuffer, partPtr->start, + partPtr->size); + j += partPtr->numComponents; + partPtr += partPtr->numComponents; + break; + + default: + panic("unexpected token type in TclCompileExprWords"); + } + } + wordPtr += (wordPtr->numComponents + 1); + } + envPtr->exceptArrayPtr[range].codeOffset = + (envPtr->codeNext - envPtr->codeStart); + code = TclCompileExpr(interp, Tcl_DStringValue(&exprBuffer), + Tcl_DStringLength(&exprBuffer), envPtr); + envPtr->exceptArrayPtr[range].numCodeBytes = + (envPtr->codeNext - envPtr->codeStart) + - envPtr->exceptArrayPtr[range].codeOffset; + maxDepth = envPtr->maxStackDepth; + Tcl_DStringFree(&exprBuffer); + + if ((code != TCL_OK) || (envPtr->exprIsJustVarRef) + || (envPtr->exprIsComparison)) { + /* + * Delete the inline code and call the expr command proc at + * runtime. There was a compilation error or the inline code + * might not have the right 2 level substitution semantics: + * e.g., if the expr consisted of a single variable ref or the + * top-level operator is a comparison (which might operate on + * strings). The code might appear to execute successfully but + * produce the wrong result. We depend on execution failing if a + * second level of substitutions is required. + */ + + envPtr->codeNext = (envPtr->codeStart + startCodeOffset); + envPtr->exceptArrayNext = startExceptNext; + doExprInline = 0; + } else { + TclEmitOpcode(INST_END_CATCH, envPtr); /* for ok case */ + TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); + envPtr->exceptArrayPtr[range].catchOffset = + (envPtr->codeNext - envPtr->codeStart); + TclEmitOpcode(INST_END_CATCH, envPtr); /* for error case */ + } + } + + /* + * 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++) { + code = TclCompileTokens(interp, wordPtr+1, wordPtr->numComponents, + envPtr); + if (code != TCL_OK) { + break; + } + if (i < (numWords - 1)) { + TclEmitPush(TclRegisterLiteral(envPtr, " ", 1, /*onHeap*/ 0), + envPtr); + maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); + } else { + maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); + } + wordPtr += (wordPtr->numComponents + 1); + } + if (code == TCL_OK) { + int concatItems = 2*numWords - 1; + while (concatItems > 255) { + TclEmitInstInt1(INST_CONCAT1, 255, envPtr); + concatItems -= 254; + } + if (concatItems > 1) { + TclEmitInstInt1(INST_CONCAT1, concatItems, envPtr); + } + TclEmitOpcode(INST_EXPR_STK, envPtr); + } + + /* + * If generating inline code, update the target of the jump at the end. + */ + + if (doExprInline) { + int jumpDist = (envPtr->codeNext - envPtr->codeStart) + - jumpFixup.codeOffset; + if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) { + /* + * Update the inline expression code's catch ExceptionRange + * target since it, being after the jump, also moved down. + */ + + envPtr->exceptArrayPtr[range].catchOffset += 3; + } + envPtr->exceptDepth--; + } + + envPtr->exprIsJustVarRef = saveExprIsJustVarRef; + envPtr->exprIsComparison = saveExprIsComparison; + envPtr->maxStackDepth = maxDepth; + return code; +} /* *---------------------------------------------------------------------- * * TclInitByteCodeObj -- @@ -1269,5286 +1522,244 @@ 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; - register size_t size, objBytes, totalSize; + size_t auxDataArrayBytes, structureSize; register unsigned char *p; unsigned char *nextPtr; - int srcLen = envPtr->termOffset; - int numObjects, i; -#ifdef TCL_COMPILE_STATS - int srcLenLog2, sizeLog2; -#endif /*TCL_COMPILE_STATS*/ + int numLitObjects = envPtr->literalArrayNext; + Namespace *namespacePtr; + int i; + Interp *iPtr; + + iPtr = envPtr->iPtr; codeBytes = (envPtr->codeNext - envPtr->codeStart); - numObjects = envPtr->objArrayNext; - objArrayBytes = (envPtr->objArrayNext * sizeof(Tcl_Obj *)); - exceptArrayBytes = (envPtr->excRangeArrayNext * sizeof(ExceptionRange)); + objArrayBytes = (envPtr->literalArrayNext * sizeof(Tcl_Obj *)); + exceptArrayBytes = (envPtr->exceptArrayNext * sizeof(ExceptionRange)); auxDataArrayBytes = (envPtr->auxDataArrayNext * sizeof(AuxData)); cmdLocBytes = GetCmdLocEncodingSize(envPtr); - size = sizeof(ByteCode); - size += TCL_ALIGN(codeBytes); /* align object array */ - size += TCL_ALIGN(objArrayBytes); /* align exception range array */ - size += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */ - size += auxDataArrayBytes; - size += cmdLocBytes; - /* - * Compute the total number of bytes needed for this bytecode - * including the storage for the Tcl objects in its object array. + * Compute the total number of bytes needed for this bytecode. */ - objBytes = (numObjects * sizeof(Tcl_Obj)); - for (i = 0; i < numObjects; i++) { - Tcl_Obj *litObjPtr = envPtr->objArrayPtr[i]; - if (litObjPtr->bytes != NULL) { - objBytes += litObjPtr->length; - } - } - totalSize = (size + objBytes); - -#ifdef TCL_COMPILE_STATS - tclNumCompilations++; - tclTotalSourceBytes += (double) srcLen; - tclTotalCodeBytes += (double) totalSize; - - tclTotalInstBytes += (double) codeBytes; - tclTotalObjBytes += (double) objBytes; - tclTotalExceptBytes += exceptArrayBytes; - tclTotalAuxBytes += (double) auxDataArrayBytes; - tclTotalCmdMapBytes += (double) cmdLocBytes; - - tclCurrentSourceBytes += (double) srcLen; - tclCurrentCodeBytes += (double) totalSize; - - srcLenLog2 = TclLog2(srcLen); - sizeLog2 = TclLog2((int) totalSize); - if ((srcLenLog2 > 31) || (sizeLog2 > 31)) { - panic("TclInitByteCodeObj: bad source or code sizes\n"); - } - tclSourceCount[srcLenLog2]++; - tclByteCodeCount[sizeLog2]++; -#endif /* TCL_COMPILE_STATS */ - - p = (unsigned char *) ckalloc(size); + 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 = (unsigned char *) ckalloc((size_t) structureSize); codePtr = (ByteCode *) p; - codePtr->iPtr = envPtr->iPtr; - codePtr->compileEpoch = envPtr->iPtr->compileEpoch; + codePtr->interpHandle = TclHandlePreserve(iPtr->handle); + codePtr->compileEpoch = iPtr->compileEpoch; + codePtr->nsPtr = namespacePtr; + codePtr->nsEpoch = namespacePtr->resolverEpoch; codePtr->refCount = 1; + codePtr->flags = 0; codePtr->source = envPtr->source; codePtr->procPtr = envPtr->procPtr; - codePtr->totalSize = totalSize; + codePtr->numCommands = envPtr->numCommands; - codePtr->numSrcChars = srcLen; + codePtr->numSrcBytes = envPtr->numSrcBytes; codePtr->numCodeBytes = codeBytes; - codePtr->numObjects = numObjects; - codePtr->numExcRanges = envPtr->excRangeArrayNext; + codePtr->numLitObjects = numLitObjects; + codePtr->numExceptRanges = envPtr->exceptArrayNext; codePtr->numAuxDataItems = envPtr->auxDataArrayNext; - codePtr->auxDataArrayPtr = NULL; codePtr->numCmdLocBytes = cmdLocBytes; - codePtr->maxExcRangeDepth = envPtr->maxExcRangeDepth; + codePtr->maxExceptDepth = envPtr->maxExceptDepth; codePtr->maxStackDepth = envPtr->maxStackDepth; p += sizeof(ByteCode); codePtr->codeStart = p; - memcpy((VOID *) p, (VOID *) envPtr->codeStart, codeBytes); + memcpy((VOID *) p, (VOID *) envPtr->codeStart, (size_t) codeBytes); p += TCL_ALIGN(codeBytes); /* align object array */ codePtr->objArrayPtr = (Tcl_Obj **) p; - memcpy((VOID *) p, (VOID *) envPtr->objArrayPtr, objArrayBytes); + for (i = 0; i < numLitObjects; i++) { + codePtr->objArrayPtr[i] = envPtr->literalArrayPtr[i].objPtr; + } p += TCL_ALIGN(objArrayBytes); /* align exception range array */ if (exceptArrayBytes > 0) { - codePtr->excRangeArrayPtr = (ExceptionRange *) p; - memcpy((VOID *) p, (VOID *) envPtr->excRangeArrayPtr, - exceptArrayBytes); + codePtr->exceptArrayPtr = (ExceptionRange *) p; + memcpy((VOID *) p, (VOID *) envPtr->exceptArrayPtr, + (size_t) exceptArrayBytes); + } else { + codePtr->exceptArrayPtr = NULL; } p += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */ if (auxDataArrayBytes > 0) { codePtr->auxDataArrayPtr = (AuxData *) p; memcpy((VOID *) p, (VOID *) envPtr->auxDataArrayPtr, - auxDataArrayBytes); + (size_t) auxDataArrayBytes); + } else { + codePtr->auxDataArrayPtr = NULL; } p += auxDataArrayBytes; nextPtr = EncodeCmdLocMap(envPtr, codePtr, (unsigned char *) p); +#ifdef TCL_COMPILE_DEBUG if (((size_t)(nextPtr - p)) != cmdLocBytes) { panic("TclInitByteCodeObj: encoded cmd location bytes %d != expected size %d\n", (nextPtr - p), 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)); + TclpGetTime(&(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. */ if ((objPtr->typePtr != NULL) && (objPtr->typePtr->freeIntRepProc != NULL)) { - objPtr->typePtr->freeIntRepProc(objPtr); + (*objPtr->typePtr->freeIntRepProc)(objPtr); } objPtr->internalRep.otherValuePtr = (VOID *) codePtr; objPtr->typePtr = &tclByteCodeType; } /* *---------------------------------------------------------------------- * - * 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(envPtr) - 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) { - 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) { - 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)) { - srcDeltaNext++; - } else { - srcDeltaNext += 5; /* 1 byte for 0xFF, 4 for delta */ - } - prevSrcOffset = mapPtr[i].srcOffset; - - srcLen = mapPtr[i].numSrcChars; - if (srcLen < 0) { - 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(envPtr, codePtr, startPtr) - 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) { - 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) { - 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)) { - 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].numSrcChars; - if (srcLen < 0) { - 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; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileString -- - * - * Compile a Tcl script in a null-terminated binary 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. - * - * envPtr->termOffset and interp->termOffset are filled in with the - * offset of the character in the string just after the last one - * successfully processed; this might be the offset of the ']' (if - * flags & TCL_BRACKET_TERM), or the offset of the '\0' at the end of - * the string. Also updates envPtr->maxStackDepth with the maximum - * number of stack elements needed to execute the string's commands. - * - * Side effects: - * Adds instructions to envPtr to evaluate the string at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileString(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - Interp *iPtr = (Interp *) interp; - register char *src = string;/* Points to current source char. */ - register char c = *src; /* The current char. */ - register int type; /* Current char's CHAR_TYPE type. */ - char termChar = (char)((flags & TCL_BRACKET_TERM)? ']' : '\0'); - /* Return when this character is found - * (either ']' or '\0'). Zero means newlines - * terminate cmds. */ - int isFirstCmd = 1; /* 1 if compiling the first cmd. */ - char *cmdSrcStart = NULL; /* Points to first non-blank char in each - * command. Initialized to avoid compiler - * warning. */ - int cmdIndex; /* The index of the current command in the - * compilation environment's command - * location table. */ - int lastTopLevelCmdIndex = -1; - /* Index of most recent toplevel command in - * the command location table. Initialized - * to avoid compiler warning. */ - int cmdCodeOffset = -1; /* Offset of first byte of current command's - * code. Initialized to avoid compiler - * warning. */ - int cmdWords; /* Number of words in current command. */ - Tcl_Command cmd; /* Used to search for commands. */ - Command *cmdPtr; /* Points to command's Command structure if - * first word is simple and command was - * found; else NULL. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute all cmds. */ - char *termPtr; /* Points to char that terminated word. */ - char savedChar; /* Holds the character from string - * termporarily replaced by a null character - * during processing of words. */ - int objIndex = -1; /* The object array index for a pushed - * object holding a word or word part - * Initialized to avoid compiler warning. */ - unsigned char *entryCodeNext = envPtr->codeNext; - /* Value of envPtr's current instruction - * pointer at entry. Used to tell if any - * instructions generated. */ - char *ellipsis = ""; /* Used to set errorInfo variable; "..." - * indicates that not all of offending - * command is included in errorInfo. "" - * means that the command is all there. */ - Tcl_Obj *objPtr; - int numChars; - int result = TCL_OK; - int savePushSimpleWords = envPtr->pushSimpleWords; - - /* - * commands: command {(';' | '\n') command} - */ - - while ((src != lastChar) && (c != termChar)) { - /* - * Skip white space, semicolons, backslash-newlines (treated as - * spaces), and comments before command. - */ - - type = CHAR_TYPE(src, lastChar); - while ((type & (TCL_SPACE | TCL_BACKSLASH)) - || (c == '\n') || (c == ';')) { - if (type == TCL_BACKSLASH) { - if (src[1] == '\n') { - src += 2; - } else { - break; - } - } else { - src++; - } - c = *src; - type = CHAR_TYPE(src, lastChar); - } - - if (c == '#') { - while (src != lastChar) { - if (c == '\\') { - int numRead; - Tcl_Backslash(src, &numRead); - src += numRead; - } else if (c == '\n') { - src++; - c = *src; - envPtr->termOffset = (src - string); - break; - } else { - src++; - } - c = *src; - } - continue; /* end of comment, restart outer command loop */ - } - - /* - * Compile one command: zero or more words terminated by a '\n', - * ';', ']' (if command is terminated by close bracket), or - * the end of string. - * - * command: word* - */ - - type = CHAR_TYPE(src, lastChar); - if ((type == TCL_COMMAND_END) - && ((c != ']') || (flags & TCL_BRACKET_TERM))) { - continue; /* empty command; restart outer cmd loop */ - } - - /* - * If not the first command, discard the previous command's result. - */ - - if (!isFirstCmd) { - TclEmitOpcode(INST_POP, envPtr); - if (!(flags & TCL_BRACKET_TERM)) { - /* - * We are compiling a top level command. Update the number - * of code bytes for the last command to account for the pop - * instruction. - */ - - (envPtr->cmdMapPtr[lastTopLevelCmdIndex]).numCodeBytes = - (envPtr->codeNext-envPtr->codeStart) - cmdCodeOffset; - } - } - - /* - * Compile the words of the command. Process the first word - * specially, since it is the name of a command. If it is a "simple" - * string (just a sequence of characters), look it up in the table - * of compilation procedures. If a word other than the first is - * simple and represents an integer whose formatted representation - * is the same as the word, just push an integer object. Also record - * starting source and object information for the command. - */ - - envPtr->numCommands++; - cmdIndex = (envPtr->numCommands - 1); - if (!(flags & TCL_BRACKET_TERM)) { - lastTopLevelCmdIndex = cmdIndex; - } - - cmdSrcStart = src; - cmdCodeOffset = (envPtr->codeNext - envPtr->codeStart); - cmdWords = 0; - EnterCmdStartData(envPtr, cmdIndex, src-envPtr->source, - cmdCodeOffset); - - if ((!(flags & TCL_BRACKET_TERM)) - && (tclTraceCompile >= 1) && (envPtr->procPtr == NULL)) { - /* - * Display a line summarizing the top level command we are about - * to compile. - */ - - char *p = cmdSrcStart; - int numChars, complete; - - while ((CHAR_TYPE(p, lastChar) != TCL_COMMAND_END) - || ((*p == ']') && !(flags & TCL_BRACKET_TERM))) { - p++; - } - numChars = (p - cmdSrcStart); - complete = 1; - if (numChars > 60) { - numChars = 60; - complete = 0; - } else if ((numChars >= 2) && (*p == '\n') && (*(p-1) == '{')) { - complete = 0; - } - fprintf(stdout, "Compiling: %.*s%s\n", - numChars, cmdSrcStart, (complete? "" : " ...")); - } - - while ((type != TCL_COMMAND_END) - || ((c == ']') && !(flags & TCL_BRACKET_TERM))) { - /* - * Skip any leading white space at the start of a word. Note - * that a backslash-newline is treated as a space. - */ - - while (type & (TCL_SPACE | TCL_BACKSLASH)) { - if (type == TCL_BACKSLASH) { - if (src[1] == '\n') { - src += 2; - } else { - break; - } - } else { - src++; - } - c = *src; - type = CHAR_TYPE(src, lastChar); - } - if ((type == TCL_COMMAND_END) - && ((c != ']') || (flags & TCL_BRACKET_TERM))) { - break; /* no words remain for command. */ - } - - /* - * Compile one word. We use an inline version of CompileWord to - * avoid an extra procedure call. - */ - - envPtr->pushSimpleWords = 0; - if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) { - src++; - if (type == TCL_QUOTE) { - result = TclCompileQuotes(interp, src, lastChar, - '"', flags, envPtr); - } else { - result = CompileBraces(interp, src, lastChar, - flags, envPtr); - } - termPtr = (src + envPtr->termOffset); - if (result != TCL_OK) { - src = termPtr; - goto done; - } - - /* - * Make sure terminating character of the quoted or braced - * string is the end of word. - */ - - c = *termPtr; - if ((c == '\\') && (*(termPtr+1) == '\n')) { - /* - * Line is continued on next line; the backslash- - * newline turns into space, which terminates the word. - */ - } else { - type = CHAR_TYPE(termPtr, lastChar); - if ((type != TCL_SPACE) && (type != TCL_COMMAND_END)) { - Tcl_ResetResult(interp); - if (*(src-1) == '"') { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "extra characters after close-quote", -1); - } else { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "extra characters after close-brace", -1); - } - result = TCL_ERROR; - } - } - } else { - result = CompileMultipartWord(interp, src, lastChar, - flags, envPtr); - termPtr = (src + envPtr->termOffset); - } - if (result != TCL_OK) { - ellipsis = "..."; - src = termPtr; - goto done; - } - - if (envPtr->wordIsSimple) { - /* - * A simple word. Temporarily replace the terminating - * character with a null character. - */ - - numChars = envPtr->numSimpleWordChars; - savedChar = src[numChars]; - src[numChars] = '\0'; - - if ((cmdWords == 0) - && (!(iPtr->flags & DONT_COMPILE_CMDS_INLINE))) { - /* - * The first word of a command and inline command - * compilation has not been disabled (e.g., by command - * traces). Look up the first word in the interpreter's - * hashtable of commands. If a compilation procedure is - * found, let it compile the command after resetting - * error logging information. Note that if we are - * compiling a procedure, we must look up the command - * in the procedure's namespace and not the current - * namespace. - */ - - Namespace *cmdNsPtr; - - if (envPtr->procPtr != NULL) { - cmdNsPtr = envPtr->procPtr->cmdPtr->nsPtr; - } else { - cmdNsPtr = NULL; - } - - cmdPtr = NULL; - cmd = Tcl_FindCommand(interp, src, - (Tcl_Namespace *) cmdNsPtr, /*flags*/ 0); - if (cmd != (Tcl_Command) NULL) { - cmdPtr = (Command *) cmd; - } - if ((cmdPtr != NULL) && (cmdPtr->compileProc != NULL)) { - char *firstArg = termPtr; - src[numChars] = savedChar; - iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS - | ERROR_CODE_SET); - result = (*(cmdPtr->compileProc))(interp, - firstArg, lastChar, flags, envPtr); - if (result == TCL_OK) { - src = (firstArg + envPtr->termOffset); - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - goto finishCommand; - } else if (result == TCL_OUT_LINE_COMPILE) { - result = TCL_OK; - src[numChars] = '\0'; - } else { - src = firstArg; - goto done; /* an error */ - } - } - - /* - * No compile procedure was found for the command: push - * the word and continue to compile the remaining - * words. If a hashtable entry was found for the - * command, push a CmdName object instead to avoid - * runtime lookups. If necessary, convert the pushed - * object to be a CmdName object. If this is the first - * CmdName object in this code unit that refers to the - * command, increment the reference count in the - * Command structure to reflect the new reference from - * the CmdName object and, if the command is deleted - * later, to keep the Command structure from being freed - * until TclExecuteByteCode has a chance to recognize - * that the command was deleted. - */ - - objIndex = TclObjIndexForString(src, numChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - if (cmdPtr != NULL) { - objPtr = envPtr->objArrayPtr[objIndex]; - if ((objPtr->typePtr != &tclCmdNameType) - && (objPtr->bytes != NULL)) { - ResolvedCmdName *resPtr = (ResolvedCmdName *) - ckalloc(sizeof(ResolvedCmdName)); - Namespace *nsPtr = (Namespace *) - Tcl_GetCurrentNamespace(interp); - - resPtr->cmdPtr = cmdPtr; - resPtr->refNsPtr = nsPtr; - resPtr->refNsId = nsPtr->nsId; - resPtr->refNsCmdEpoch = nsPtr->cmdRefEpoch; - resPtr->cmdEpoch = cmdPtr->cmdEpoch; - resPtr->refCount = 1; - objPtr->internalRep.twoPtrValue.ptr1 = - (VOID *) resPtr; - objPtr->internalRep.twoPtrValue.ptr2 = NULL; - objPtr->typePtr = &tclCmdNameType; - cmdPtr->refCount++; - } - } - } else { - /* - * See if the word represents an integer whose formatted - * representation is the same as the word (e.g., this is - * true for 123 and -1 but not for 00005). If so, just - * push an integer object. - */ - - int isCompilableInt = 0; - long n; - char buf[40]; - - if (TclLooksLikeInt(src)) { - int code = TclGetLong(interp, src, &n); - if (code == TCL_OK) { - TclFormatInt(buf, n); - if (strcmp(src, buf) == 0) { - isCompilableInt = 1; - objIndex = TclObjIndexForString(src, - numChars, /*allocStrRep*/ 0, - /*inHeap*/ 0, envPtr); - objPtr = envPtr->objArrayPtr[objIndex]; - - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.longValue = n; - objPtr->typePtr = &tclIntType; - } - } else { - Tcl_ResetResult(interp); - } - } - if (!isCompilableInt) { - objIndex = TclObjIndexForString(src, numChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - } - } - src[numChars] = savedChar; - TclEmitPush(objIndex, envPtr); - maxDepth = TclMax((cmdWords + 1), maxDepth); - } else { /* not a simple word */ - maxDepth = TclMax((cmdWords + envPtr->maxStackDepth), - maxDepth); - } - src = termPtr; - c = *src; - type = CHAR_TYPE(src, lastChar); - cmdWords++; - } - - /* - * Emit an invoke instruction for the command. If a compile command - * was found for the command we called it and skipped this. - */ - - if (cmdWords > 0) { - if (cmdWords <= 255) { - TclEmitInstUInt1(INST_INVOKE_STK1, cmdWords, envPtr); - } else { - TclEmitInstUInt4(INST_INVOKE_STK4, cmdWords, envPtr); - } - } - - /* - * Update the compilation environment structure. Record - * source/object information for the command. - */ - - finishCommand: - EnterCmdExtentData(envPtr, cmdIndex, src-cmdSrcStart, - (envPtr->codeNext-envPtr->codeStart) - cmdCodeOffset); - - isFirstCmd = 0; - envPtr->termOffset = (src - string); - c = *src; - } - - done: - if (result == TCL_OK) { - /* - * If the source string yielded no instructions (e.g., if it was - * empty), push an empty string object as the command's result. - */ - - if (entryCodeNext == envPtr->codeNext) { - int objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0, - /*inHeap*/ 0, envPtr); - TclEmitPush(objIndex, envPtr); - maxDepth = 1; - } - } else { - /* - * Add additional error information. First compute the line number - * where the error occurred. - */ - - register char *p; - int numChars; - char buf[200]; - - iPtr->errorLine = 1; - for (p = string; p != cmdSrcStart; p++) { - if (*p == '\n') { - iPtr->errorLine++; - } - } - for ( ; isspace(UCHAR(*p)) || (*p == ';'); p++) { - if (*p == '\n') { - iPtr->errorLine++; - } - } - - /* - * Figure out how much of the command to print (up to a certain - * number of characters, or up to the end of the command). - */ - - p = cmdSrcStart; - while ((CHAR_TYPE(p, lastChar) != TCL_COMMAND_END) - || ((*p == ']') && !(flags & TCL_BRACKET_TERM))) { - p++; - } - numChars = (p - cmdSrcStart); - if (numChars > 150) { - numChars = 150; - ellipsis = " ..."; - } else if ((numChars >= 2) && (*p == '\n') && (*(p-1) == '{')) { - ellipsis = " ..."; - } - - sprintf(buf, "\n while compiling\n\"%.*s%s\"", - numChars, cmdSrcStart, ellipsis); - Tcl_AddObjErrorInfo(interp, buf, -1); - } - - envPtr->termOffset = (src - string); - iPtr->termOffset = envPtr->termOffset; - envPtr->maxStackDepth = maxDepth; - envPtr->pushSimpleWords = savePushSimpleWords; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileWord -- - * - * This procedure compiles one word from a command string. It skips - * any leading white space. - * - * Ordinarily, callers set envPtr->pushSimpleWords to 1 and this - * procedure emits push and other instructions to compute the - * word on the Tcl evaluation stack at execution time. If a caller sets - * envPtr->pushSimpleWords to 0, CompileWord will _not_ compile - * "simple" words: words that are just a sequence of characters without - * backslashes. It will leave their compilation up to the caller. - * - * As an important special case, if the word is simple, this procedure - * sets envPtr->wordIsSimple to 1 and envPtr->numSimpleWordChars to the - * number of characters in the simple word. This allows the caller to - * process these words specially. - * - * Results: - * The return value is a standard Tcl result. If an error occurs, an - * error message is left in the interpreter's result. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed in the last - * word. This is normally the character just after the last one in a - * word (perhaps the command terminator), or the vicinity of an error - * (if the result is not TCL_OK). - * - * envPtr->wordIsSimple is set 1 if the word is simple: just a - * sequence of characters without backslashes. If so, the word's - * characters are the envPtr->numSimpleWordChars characters starting - * at string. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to evaluate the word. This is not changed if - * the word is simple and envPtr->pushSimpleWords was 0 (false). - * - * Side effects: - * Instructions are added to envPtr to compute and push the word - * at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileWord(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Interpreter to use for nested command - * evaluations and error messages. */ - char *string; /* First character of word. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same values - * passed to Tcl_EvalObj). */ - CompileEnv *envPtr; /* Holds the resulting instructions. */ -{ - /* - * Compile one word: approximately - * - * word: quoted_string | braced_string | multipart_word - * quoted_string: '"' char* '"' - * braced_string: '{' char* '}' - * multipart_word (see CompileMultipartWord below) - */ - - register char *src = string; /* Points to current source char. */ - register int type = CHAR_TYPE(src, lastChar); - /* Current char's CHAR_TYPE type. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to compute and push the word. */ - char *termPtr = src; /* Points to the character that terminated - * the word. */ - int result = TCL_OK; - - /* - * Skip any leading white space at the start of a word. Note that a - * backslash-newline is treated as a space. - */ - - while (type & (TCL_SPACE | TCL_BACKSLASH)) { - if (type == TCL_BACKSLASH) { - if (src[1] == '\n') { - src += 2; - } else { - break; /* no longer white space */ - } - } else { - src++; - } - type = CHAR_TYPE(src, lastChar); - } - if (type == TCL_COMMAND_END) { - goto done; - } - - /* - * Compile the word. Handle quoted and braced string words here in order - * to avoid an extra procedure call. - */ - - if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) { - src++; - if (type == TCL_QUOTE) { - result = TclCompileQuotes(interp, src, lastChar, '"', flags, - envPtr); - } else { - result = CompileBraces(interp, src, lastChar, flags, envPtr); - } - termPtr = (src + envPtr->termOffset); - if (result != TCL_OK) { - goto done; - } - - /* - * Make sure terminating character of the quoted or braced string is - * the end of word. - */ - - if ((*termPtr == '\\') && (*(termPtr+1) == '\n')) { - /* - * Line is continued on next line; the backslash-newline turns - * into space, which terminates the word. - */ - } else { - type = CHAR_TYPE(termPtr, lastChar); - if (!(type & (TCL_SPACE | TCL_COMMAND_END))) { - Tcl_ResetResult(interp); - if (*(src-1) == '"') { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "extra characters after close-quote", -1); - } else { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "extra characters after close-brace", -1); - } - result = TCL_ERROR; - goto done; - } - } - maxDepth = envPtr->maxStackDepth; - } else { - result = CompileMultipartWord(interp, src, lastChar, flags, envPtr); - termPtr = (src + envPtr->termOffset); - maxDepth = envPtr->maxStackDepth; - } - - /* - * Done processing the word. The values of envPtr->wordIsSimple and - * envPtr->numSimpleWordChars are left at the values returned by - * TclCompileQuotes/Braces/MultipartWord. - */ - - done: - envPtr->termOffset = (termPtr - string); - envPtr->maxStackDepth = maxDepth; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileMultipartWord -- - * - * This procedure compiles one multipart word: a word comprised of some - * number of nested commands, variable references, or arbitrary - * characters. This procedure assumes that quoted string and braced - * string words and the end of command have already been handled by its - * caller. It also assumes that any leading white space has already - * been consumed. - * - * Ordinarily, callers set envPtr->pushSimpleWords to 1 and this - * procedure emits push and other instructions to compute the word on - * the Tcl evaluation stack at execution time. If a caller sets - * envPtr->pushSimpleWords to 0, it will _not_ compile "simple" words: - * words that are just a sequence of characters without backslashes. - * It will leave their compilation up to the caller. This is done, for - * example, to provide special support for the first word of commands, - * which are almost always the (simple) name of a command. - * - * As an important special case, if the word is simple, this procedure - * sets envPtr->wordIsSimple to 1 and envPtr->numSimpleWordChars to the - * number of characters in the simple word. This allows the caller to - * process these words specially. - * - * Results: - * The return value is a standard Tcl result. If an error occurs, an - * error message is left in the interpreter's result. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed in the last - * word. This is normally the character just after the last one in a - * word (perhaps the command terminator), or the vicinity of an error - * (if the result is not TCL_OK). - * - * envPtr->wordIsSimple is set 1 if the word is simple: just a - * sequence of characters without backslashes. If so, the word's - * characters are the envPtr->numSimpleWordChars characters starting - * at string. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to evaluate the word. This is not changed if - * the word is simple and envPtr->pushSimpleWords was 0 (false). - * - * Side effects: - * Instructions are added to envPtr to compute and push the word - * at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileMultipartWord(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Interpreter to use for nested command - * evaluations and error messages. */ - char *string; /* First character of word. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same values - * passed to Tcl_EvalObj). */ - CompileEnv *envPtr; /* Holds the resulting instructions. */ -{ - /* - * Compile one multi_part word: - * - * multi_part_word: word_part+ - * word_part: nested_cmd | var_reference | char+ - * nested_cmd: '[' command ']' - * var_reference: '$' name | '$' name '(' index_string ')' | - * '$' '{' braced_name '}') - * name: (letter | digit | underscore)+ - * braced_name: (non_close_brace_char)* - * index_string: (non_close_paren_char)* - */ - - register char *src = string; /* Points to current source char. */ - register char c = *src; /* The current char. */ - register int type; /* Current char's CHAR_TYPE type. */ - int bracketNormal = !(flags & TCL_BRACKET_TERM); - int simpleWord = 0; /* Set 1 if word is simple. */ - int numParts = 0; /* Count of word_part objs pushed. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to compute and push the word. */ - char *start; /* Starting position of char+ word_part. */ - int hasBackslash; /* Nonzero if '\' in char+ word_part. */ - int numChars; /* Number of chars in char+ word_part. */ - char savedChar; /* Holds the character from string - * termporarily replaced by a null character - * during word_part processing. */ - int objIndex; /* The object array index for a pushed - * object holding a word_part. */ - int savePushSimpleWords = envPtr->pushSimpleWords; - int result = TCL_OK; - int numRead; - - type = CHAR_TYPE(src, lastChar); - while (1) { - /* - * Process a word_part: a sequence of chars, a var reference, or - * a nested command. - */ - - if ((type & (TCL_NORMAL | TCL_CLOSE_BRACE | TCL_BACKSLASH | - TCL_QUOTE | TCL_OPEN_BRACE)) || - ((c == ']') && bracketNormal)) { - /* - * A char+ word part. Scan first looking for any backslashes. - * Note that a backslash-newline must be treated as a word - * separator, as if the backslash-newline had been collapsed - * before command parsing began. - */ - - start = src; - hasBackslash = 0; - do { - if (type == TCL_BACKSLASH) { - hasBackslash = 1; - Tcl_Backslash(src, &numRead); - if (src[1] == '\n') { - src += numRead; - type = TCL_SPACE; /* force word end */ - break; - } - src += numRead; - } else { - src++; - } - c = *src; - type = CHAR_TYPE(src, lastChar); - } while (type & (TCL_NORMAL | TCL_BACKSLASH | TCL_QUOTE | - TCL_OPEN_BRACE | TCL_CLOSE_BRACE) - || ((c == ']') && bracketNormal)); - - if ((numParts == 0) && !hasBackslash - && (type & (TCL_SPACE | TCL_COMMAND_END))) { - /* - * The word is "simple": just a sequence of characters - * without backslashes terminated by a TCL_SPACE or - * TCL_COMMAND_END. Just return if we are not to compile - * simple words. - */ - - simpleWord = 1; - if (!envPtr->pushSimpleWords) { - envPtr->wordIsSimple = 1; - envPtr->numSimpleWordChars = (src - string); - envPtr->termOffset = envPtr->numSimpleWordChars; - envPtr->pushSimpleWords = savePushSimpleWords; - return TCL_OK; - } - } - - /* - * Create and push a string object for the char+ word_part, - * which starts at "start" and ends at the char just before - * src. If backslashes were found, copy the word_part's - * characters with substituted backslashes into a heap-allocated - * buffer and use it to create the string object. Temporarily - * replace the terminating character with a null character. - */ - - numChars = (src - start); - savedChar = start[numChars]; - start[numChars] = '\0'; - if ((numChars > 0) && (hasBackslash)) { - char *buffer = ckalloc((unsigned) numChars + 1); - register char *dst = buffer; - register char *p = start; - while (p < src) { - if (*p == '\\') { - *dst = Tcl_Backslash(p, &numRead); - if (p[1] == '\n') { - break; - } - p += numRead; - dst++; - } else { - *dst++ = *p++; - } - } - *dst = '\0'; - objIndex = TclObjIndexForString(buffer, dst-buffer, - /*allocStrRep*/ 1, /*inHeap*/ 1, envPtr); - } else { - objIndex = TclObjIndexForString(start, numChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - } - start[numChars] = savedChar; - TclEmitPush(objIndex, envPtr); - maxDepth = TclMax((numParts + 1), maxDepth); - } else if (type == TCL_DOLLAR) { - result = TclCompileDollarVar(interp, src, lastChar, - flags, envPtr); - src += envPtr->termOffset; - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((numParts + envPtr->maxStackDepth), maxDepth); - c = *src; - type = CHAR_TYPE(src, lastChar); - } else if (type == TCL_OPEN_BRACKET) { - char *termPtr; - envPtr->pushSimpleWords = 1; - src++; - result = TclCompileString(interp, src, lastChar, - (flags | TCL_BRACKET_TERM), envPtr); - termPtr = (src + envPtr->termOffset); - if (*termPtr == ']') { - termPtr++; - } else if (*termPtr == '\0') { - /* - * Missing ] at end of nested command. - */ - - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "missing close-bracket", -1); - result = TCL_ERROR; - } - src = termPtr; - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((numParts + envPtr->maxStackDepth), maxDepth); - c = *src; - type = CHAR_TYPE(src, lastChar); - } else if (type & (TCL_SPACE | TCL_COMMAND_END)) { - goto wordEnd; - } - numParts++; - } /* end of infinite loop */ - - wordEnd: - /* - * End of a non-simple word: TCL_SPACE, TCL_COMMAND_END, or - * backslash-newline. Concatenate the word_parts if necessary. - */ - - while (numParts > 255) { - TclEmitInstUInt1(INST_CONCAT1, 255, envPtr); - numParts -= 254; /* concat pushes 1 obj, the result */ - } - if (numParts > 1) { - TclEmitInstUInt1(INST_CONCAT1, numParts, envPtr); - } - - done: - if (simpleWord) { - envPtr->wordIsSimple = 1; - envPtr->numSimpleWordChars = (src - string); - } else { - envPtr->wordIsSimple = 0; - envPtr->numSimpleWordChars = 0; - } - envPtr->termOffset = (src - string); - envPtr->maxStackDepth = maxDepth; - envPtr->pushSimpleWords = savePushSimpleWords; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileQuotes -- - * - * This procedure compiles a double-quoted string such as a quoted Tcl - * command argument or a quoted value in a Tcl expression. This - * procedure is also used to compile array element names within - * parentheses (where the termChar will be ')' instead of '"'), or - * anything else that needs the substitutions that happen in quotes. - * - * Ordinarily, callers set envPtr->pushSimpleWords to 1 and - * TclCompileQuotes always emits push and other instructions to compute - * the word on the Tcl evaluation stack at execution time. If a caller - * sets envPtr->pushSimpleWords to 0, TclCompileQuotes will not compile - * "simple" words: words that are just a sequence of characters without - * backslashes. It will leave their compilation up to the caller. This - * is done to provide special support for the first word of commands, - * which are almost always the (simple) name of a command. - * - * As an important special case, if the word is simple, this procedure - * sets envPtr->wordIsSimple to 1 and envPtr->numSimpleWordChars to the - * number of characters in the simple word. This allows the caller to - * process these words specially. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK unless - * there was an error while parsing the quoted string. If an error - * occurs then the interpreter's result contains a standard error - * message. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed; this is - * usually the character just after the matching close-quote. - * - * envPtr->wordIsSimple is set 1 if the word is simple: just a - * sequence of characters without backslashes. If so, the word's - * characters are the envPtr->numSimpleWordChars characters starting - * at string. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to evaluate the word. This is not changed if - * the word is simple and envPtr->pushSimpleWords was 0 (false). - * - * Side effects: - * Instructions are added to envPtr to push the quoted-string - * at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileQuotes(interp, string, lastChar, termChar, flags, envPtr) - Tcl_Interp *interp; /* Interpreter to use for nested command - * evaluations and error messages. */ - char *string; /* Points to the character just after - * the opening '"' or '('. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int termChar; /* Character that terminates the "quoted" - * string (usually double-quote, but might - * be right-paren or something else). */ - int flags; /* Flags to control compilation (same - * values passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds the resulting instructions. */ -{ - register char *src = string; /* Points to current source char. */ - register char c = *src; /* The current char. */ - int simpleWord = 0; /* Set 1 if a simple quoted string word. */ - char *start; /* Start position of char+ string_part. */ - int hasBackslash; /* 1 if '\' found in char+ string_part. */ - int numRead; /* Count of chars read by Tcl_Backslash. */ - int numParts = 0; /* Count of string_part objs pushed. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to compute and push the string. */ - char savedChar; /* Holds the character from string - * termporarily replaced by a null - * char during string_part processing. */ - int objIndex; /* The object array index for a pushed - * object holding a string_part. */ - int numChars; /* Number of chars in string_part. */ - int savePushSimpleWords = envPtr->pushSimpleWords; - int result = TCL_OK; - - /* - * quoted_string: '"' string_part* '"' (or termChar instead of ") - * string_part: var_reference | nested_cmd | char+ - */ - - - while ((src != lastChar) && (c != termChar)) { - if (c == '$') { - result = TclCompileDollarVar(interp, src, lastChar, flags, - envPtr); - src += envPtr->termOffset; - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax((numParts + envPtr->maxStackDepth), maxDepth); - c = *src; - } else if (c == '[') { - char *termPtr; - envPtr->pushSimpleWords = 1; - src++; - result = TclCompileString(interp, src, lastChar, - (flags | TCL_BRACKET_TERM), envPtr); - termPtr = (src + envPtr->termOffset); - if (*termPtr == ']') { - termPtr++; - } - src = termPtr; - if (result != TCL_OK) { - goto done; - } - if (termPtr == lastChar) { - /* - * Missing ] at end of nested command. - */ - - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "missing close-bracket", -1); - result = TCL_ERROR; - goto done; - } - maxDepth = TclMax((numParts + envPtr->maxStackDepth), maxDepth); - c = *src; - } else { - /* - * Start of a char+ string_part. Scan first looking for any - * backslashes. - */ - - start = src; - hasBackslash = 0; - do { - if (c == '\\') { - hasBackslash = 1; - Tcl_Backslash(src, &numRead); - src += numRead; - } else { - src++; - } - c = *src; - } while ((src != lastChar) && (c != '$') && (c != '[') - && (c != termChar)); - - if ((numParts == 0) && !hasBackslash - && ((src == lastChar) && (c == termChar))) { - /* - * The quoted string is "simple": just a sequence of - * characters without backslashes terminated by termChar or - * a null character. Just return if we are not to compile - * simple words. - */ - - simpleWord = 1; - if (!envPtr->pushSimpleWords) { - if ((src == lastChar) && (termChar != '\0')) { - char buf[40]; - sprintf(buf, "missing %c", termChar); - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); - result = TCL_ERROR; - } else { - src++; - } - envPtr->wordIsSimple = 1; - envPtr->numSimpleWordChars = (src - string - 1); - envPtr->termOffset = (src - string); - envPtr->pushSimpleWords = savePushSimpleWords; - return result; - } - } - - /* - * Create and push a string object for the char+ string_part - * that starts at "start" and ends at the char just before - * src. If backslashes were found, copy the string_part's - * characters with substituted backslashes into a heap-allocated - * buffer and use it to create the string object. Temporarily - * replace the terminating character with a null character. - */ - - numChars = (src - start); - savedChar = start[numChars]; - start[numChars] = '\0'; - if ((numChars > 0) && (hasBackslash)) { - char *buffer = ckalloc((unsigned) numChars + 1); - register char *dst = buffer; - register char *p = start; - while (p < src) { - if (*p == '\\') { - *dst++ = Tcl_Backslash(p, &numRead); - p += numRead; - } else { - *dst++ = *p++; - } - } - *dst = '\0'; - objIndex = TclObjIndexForString(buffer, (dst - buffer), - /*allocStrRep*/ 1, /*inHeap*/ 1, envPtr); - } else { - objIndex = TclObjIndexForString(start, numChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - } - start[numChars] = savedChar; - TclEmitPush(objIndex, envPtr); - maxDepth = TclMax((numParts + 1), maxDepth); - } - numParts++; - } - - /* - * End of the quoted string: src points at termChar or '\0'. If - * necessary, concatenate the string_part objects on the stack. - */ - - if ((src == lastChar) && (termChar != '\0')) { - char buf[40]; - sprintf(buf, "missing %c", termChar); - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); - result = TCL_ERROR; - goto done; - } else { - src++; - } - - if (numParts == 0) { - /* - * The quoted string was empty. Push an empty string object. - */ - - int objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0, - /*inHeap*/ 0, envPtr); - TclEmitPush(objIndex, envPtr); - } else { - /* - * Emit any needed concat instructions. - */ - - while (numParts > 255) { - TclEmitInstUInt1(INST_CONCAT1, 255, envPtr); - numParts -= 254; /* concat pushes 1 obj, the result */ - } - if (numParts > 1) { - TclEmitInstUInt1(INST_CONCAT1, numParts, envPtr); - } - } - - done: - if (simpleWord) { - envPtr->wordIsSimple = 1; - envPtr->numSimpleWordChars = (src - string - 1); - } else { - envPtr->wordIsSimple = 0; - envPtr->numSimpleWordChars = 0; - } - envPtr->termOffset = (src - string); - envPtr->maxStackDepth = maxDepth; - envPtr->pushSimpleWords = savePushSimpleWords; - return result; -} - -/* - *-------------------------------------------------------------- - * - * CompileBraces -- - * - * This procedure compiles characters between matching curly braces. - * - * Ordinarily, callers set envPtr->pushSimpleWords to 1 and - * CompileBraces always emits a push instruction to compute the word on - * the Tcl evaluation stack at execution time. However, if a caller - * sets envPtr->pushSimpleWords to 0, CompileBraces will _not_ compile - * "simple" words: words that are just a sequence of characters without - * backslash-newlines. It will leave their compilation up to the - * caller. - * - * As an important special case, if the word is simple, this procedure - * sets envPtr->wordIsSimple to 1 and envPtr->numSimpleWordChars to the - * number of characters in the simple word. This allows the caller to - * process these words specially. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK unless - * there was an error while parsing string. If an error occurs then - * the interpreter's result contains a standard error message. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. This is - * usually the character just after the matching close-brace. - * - * envPtr->wordIsSimple is set 1 if the word is simple: just a - * sequence of characters without backslash-newlines. If so, the word's - * characters are the envPtr->numSimpleWordChars characters starting - * at string. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to evaluate the word. This is not changed if - * the word is simple and envPtr->pushSimpleWords was 0 (false). - * - * Side effects: - * Instructions are added to envPtr to push the braced string - * at runtime. - * - *-------------------------------------------------------------- - */ - -static int -CompileBraces(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Interpreter to use for nested command - * evaluations and error messages. */ - char *string; /* Character just after opening bracket. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same - * values passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds the resulting instructions. */ -{ - register char *src = string; /* Points to current source char. */ - register char c; /* The current char. */ - int simpleWord = 0; /* Set 1 if a simple braced string word. */ - int level = 1; /* {} nesting level. Initially 1 since { - * was parsed before we were called. */ - int hasBackslashNewline = 0; /* Nonzero if '\' found. */ - char *last; /* Points just before terminating '}'. */ - int numChars; /* Number of chars in braced string. */ - char savedChar; /* Holds the character from string - * termporarily replaced by a null - * char during braced string processing. */ - int objIndex; /* The object array index for a pushed - * object holding a braced string. */ - int numRead; - int result = TCL_OK; - - /* - * Check for any backslash-newlines, since we must treat - * backslash-newlines specially (they must be replaced by spaces). - */ - - while (1) { - c = *src; - if (src == lastChar) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "missing close-brace", -1); - result = TCL_ERROR; - goto done; - } - if (CHAR_TYPE(src, lastChar) != TCL_NORMAL) { - if (c == '{') { - level++; - } else if (c == '}') { - --level; - if (level == 0) { - src++; - last = (src - 2); /* point just before terminating } */ - break; - } - } else if (c == '\\') { - if (*(src+1) == '\n') { - hasBackslashNewline = 1; - } - (void) Tcl_Backslash(src, &numRead); - src += numRead - 1; - } - } - src++; - } - - if (!hasBackslashNewline) { - /* - * The braced word is "simple": just a sequence of characters - * without backslash-newlines. Just return if we are not to compile - * simple words. - */ - - simpleWord = 1; - if (!envPtr->pushSimpleWords) { - envPtr->wordIsSimple = 1; - envPtr->numSimpleWordChars = (src - string - 1); - envPtr->termOffset = (src - string); - return TCL_OK; - } - } - - /* - * Create and push a string object for the braced string. This starts at - * "string" and ends just after "last" (which points to the final - * character before the terminating '}'). If backslash-newlines were - * found, we copy characters one at a time into a heap-allocated buffer - * and do backslash-newline substitutions. - */ - - numChars = (last - string + 1); - savedChar = string[numChars]; - string[numChars] = '\0'; - if ((numChars > 0) && (hasBackslashNewline)) { - char *buffer = ckalloc((unsigned) numChars + 1); - register char *dst = buffer; - register char *p = string; - while (p <= last) { - c = *dst++ = *p++; - if (c == '\\') { - if (*p == '\n') { - dst[-1] = Tcl_Backslash(p-1, &numRead); - p += numRead - 1; - } else { - (void) Tcl_Backslash(p-1, &numRead); - while (numRead > 1) { - *dst++ = *p++; - numRead--; - } - } - } - } - *dst = '\0'; - objIndex = TclObjIndexForString(buffer, (dst - buffer), - /*allocStrRep*/ 1, /*inHeap*/ 1, envPtr); - } else { - objIndex = TclObjIndexForString(string, numChars, /*allocStrRep*/ 1, - /*inHeap*/ 0, envPtr); - } - string[numChars] = savedChar; - TclEmitPush(objIndex, envPtr); - - done: - if (simpleWord) { - envPtr->wordIsSimple = 1; - envPtr->numSimpleWordChars = (src - string - 1); - } else { - envPtr->wordIsSimple = 0; - envPtr->numSimpleWordChars = 0; - } - envPtr->termOffset = (src - string); - envPtr->maxStackDepth = 1; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileDollarVar -- - * - * Given a string starting with a $ sign, parse a variable name - * and compile instructions to push its value. If the variable - * reference is just a '$' (i.e. the '$' isn't followed by anything - * that could possibly be a variable name), just push a string object - * containing '$'. - * - * Results: - * The return value is a standard Tcl result. If an error occurs - * then an error message is left in the interpreter's result. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one in the variable reference. - * - * envPtr->wordIsSimple is set 0 (false) because the word is not - * simple: it is not just a sequence of characters without backslashes. - * For the same reason, envPtr->numSimpleWordChars is set 0. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the string's commands. - * - * Side effects: - * Instructions are added to envPtr to look up the variable and - * push its value at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileDollarVar(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Interpreter to use for nested command - * evaluations and error messages. */ - char *string; /* First char (i.e. $) of var reference. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same - * values passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds the resulting instructions. */ -{ - register char *src = string; /* Points to current source char. */ - register char c; /* The current char. */ - char *name; /* Start of 1st part of variable name. */ - int nameChars; /* Count of chars in name. */ - int nameHasNsSeparators = 0; /* Set 1 if name contains "::"s. */ - char savedChar; /* Holds the character from string - * termporarily replaced by a null - * char during name processing. */ - int objIndex; /* The object array index for a pushed - * object holding a name part. */ - int isArrayRef = 0; /* 1 if reference to array element. */ - int localIndex = -1; /* Frame index of local if found. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to push the variable. */ - int savePushSimpleWords = envPtr->pushSimpleWords; - int result = TCL_OK; - - /* - * var_reference: '$' '{' braced_name '}' | - * '$' name ['(' index_string ')'] - * - * There are three cases: - * 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, underscore, or a "::" namespace separator. If the - * following character is an open parenthesis, then the information - * between parentheses is the array element name, which can include - * any of the substitutions permissible between quotes. - * 3. The $ sign is followed by something that isn't a letter, digit, - * underscore, or a "::" namespace separator: in this case, - * there is no variable name, and "$" is pushed. - */ - - src++; /* advance over the '$'. */ - - /* - * Collect the first part of the variable's name into "name" and - * determine if it is an array reference and if it contains any - * namespace separator (::'s). - */ - - if (*src == '{') { - /* - * A scalar name in braces. - */ - - char *p; - - src++; - name = src; - c = *src; - while (c != '}') { - if (src == lastChar) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "missing close-brace for variable name", -1); - result = TCL_ERROR; - goto done; - } - src++; - c = *src; - } - nameChars = (src - name); - for (p = name; p < src; p++) { - if ((*p == ':') && (*(p+1) == ':')) { - nameHasNsSeparators = 1; - break; - } - } - src++; /* advance over the '}'. */ - } else { - /* - * Scalar name or array reference not in braces. - */ - - name = src; - c = *src; - while (isalnum(UCHAR(c)) || (c == '_') || (c == ':')) { - if (c == ':') { - if (*(src+1) == ':') { - nameHasNsSeparators = 1; - src += 2; - while (*src == ':') { - src++; - } - c = *src; - } else { - break; /* : by itself */ - } - } else { - src++; - c = *src; - } - } - if (src == name) { - /* - * A '$' by itself, not a name reference. Push a "$" string. - */ - - objIndex = TclObjIndexForString("$", 1, /*allocStrRep*/ 1, - /*inHeap*/ 0, envPtr); - TclEmitPush(objIndex, envPtr); - maxDepth = 1; - goto done; - } - nameChars = (src - name); - isArrayRef = (c == '('); - } - - /* - * Now emit instructions to load the variable. First either push the - * name of the scalar or array, or determine its index in the array of - * local variables in a procedure frame. Push the name if we are not - * compiling a procedure body or if the name has namespace - * qualifiers ("::"s). - */ - - if (!isArrayRef) { /* scalar reference */ - if ((envPtr->procPtr == NULL) || nameHasNsSeparators) { - savedChar = name[nameChars]; - name[nameChars] = '\0'; - objIndex = TclObjIndexForString(name, nameChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - name[nameChars] = savedChar; - TclEmitPush(objIndex, envPtr); - TclEmitOpcode(INST_LOAD_SCALAR_STK, envPtr); - maxDepth = 1; - } else { - localIndex = LookupCompiledLocal(name, nameChars, - /*createIfNew*/ 0, /*flagsIfCreated*/ 0, - envPtr->procPtr); - if (localIndex >= 0) { - if (localIndex <= 255) { - TclEmitInstUInt1(INST_LOAD_SCALAR1, localIndex, envPtr); - } else { - TclEmitInstUInt4(INST_LOAD_SCALAR4, localIndex, envPtr); - } - maxDepth = 0; - } else { - savedChar = name[nameChars]; - name[nameChars] = '\0'; - objIndex = TclObjIndexForString(name, nameChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - name[nameChars] = savedChar; - TclEmitPush(objIndex, envPtr); - TclEmitOpcode(INST_LOAD_SCALAR_STK, envPtr); - maxDepth = 1; - } - } - } else { /* array reference */ - if ((envPtr->procPtr == NULL) || nameHasNsSeparators) { - savedChar = name[nameChars]; - name[nameChars] = '\0'; - objIndex = TclObjIndexForString(name, nameChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - name[nameChars] = savedChar; - TclEmitPush(objIndex, envPtr); - maxDepth = 1; - } else { - localIndex = LookupCompiledLocal(name, nameChars, - /*createIfNew*/ 0, /*flagsIfCreated*/ 0, - envPtr->procPtr); - if (localIndex < 0) { - savedChar = name[nameChars]; - name[nameChars] = '\0'; - objIndex = TclObjIndexForString(name, nameChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - name[nameChars] = savedChar; - TclEmitPush(objIndex, envPtr); - maxDepth = 1; - } - } - - /* - * Parse and push the array element. Perform substitutions on it, - * just as is done for quoted strings. - */ - - src++; - envPtr->pushSimpleWords = 1; - result = TclCompileQuotes(interp, src, lastChar, ')', flags, - envPtr); - src += envPtr->termOffset; - if (result != TCL_OK) { - char msg[200]; - sprintf(msg, "\n (parsing index for array \"%.*s\")", - (nameChars > 100? 100 : nameChars), name); - Tcl_AddObjErrorInfo(interp, msg, -1); - goto done; - } - maxDepth += envPtr->maxStackDepth; - - /* - * Now emit the appropriate load instruction for the array element. - */ - - if (localIndex < 0) { /* a global or an unknown local */ - TclEmitOpcode(INST_LOAD_ARRAY_STK, envPtr); - } else { - if (localIndex <= 255) { - TclEmitInstUInt1(INST_LOAD_ARRAY1, localIndex, envPtr); - } else { - TclEmitInstUInt4(INST_LOAD_ARRAY4, localIndex, envPtr); - } - } - } - - done: - envPtr->termOffset = (src - string); - envPtr->wordIsSimple = 0; - envPtr->numSimpleWordChars = 0; - envPtr->maxStackDepth = maxDepth; - envPtr->pushSimpleWords = savePushSimpleWords; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileBreakCmd -- - * - * Procedure called to compile the "break" command. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK unless - * there was an error while parsing string. If an error occurs then - * the interpreter's result contains a standard error message. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * - * Side effects: - * Instructions are added to envPtr to evaluate the "break" command - * at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileBreakCmd(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - register char *src = string;/* Points to current source char. */ - register int type; /* Current char's CHAR_TYPE type. */ - int result = TCL_OK; - - /* - * There should be no argument after the "break". - */ - - type = CHAR_TYPE(src, lastChar); - if (type != TCL_COMMAND_END) { - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type != TCL_COMMAND_END) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: should be \"break\"", -1); - result = TCL_ERROR; - goto done; - } - } - - /* - * Emit a break instruction. - */ - - TclEmitOpcode(INST_BREAK, envPtr); - - done: - envPtr->termOffset = (src - string); - envPtr->maxStackDepth = 0; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileCatchCmd -- - * - * Procedure called to compile the "catch" command. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK if - * compilation was successful. If an error occurs then the - * interpreter's result contains a standard error message and TCL_ERROR - * is returned. If compilation failed because the command is too - * complex for TclCompileCatchCmd, TCL_OUT_LINE_COMPILE is returned - * indicating that the catch command should be compiled "out of line" - * by emitting code to invoke its command procedure at runtime. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * - * Side effects: - * Instructions are added to envPtr to evaluate the "catch" command - * at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileCatchCmd(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - Proc *procPtr = envPtr->procPtr; - /* Points to structure describing procedure - * containing the catch cmd, else NULL. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute cmd. */ - ArgInfo argInfo; /* Structure holding information about the - * start and end of each argument word. */ - int range = -1; /* If we compile the catch command, the - * index for its catch range record in the - * ExceptionRange array. -1 if we are not - * compiling the command. */ - char *name; /* If a var name appears for a scalar local - * to a procedure, this points to the name's - * 1st char and nameChars is its length. */ - int nameChars; /* Length of the variable name, if any. */ - int localIndex = -1; /* Index of the variable in the current - * procedure's array of local variables. - * Otherwise -1 if not in a procedure or - * the variable wasn't found. */ - char savedChar; /* Holds the character from string - * termporarily replaced by a null character - * during processing of words. */ - JumpFixup jumpFixup; /* Used to emit the jump after the "no - * errors" epilogue code. */ - int numWords, objIndex, jumpDist, result; - char *bodyStart, *bodyEnd; - Tcl_Obj *objPtr; - int savePushSimpleWords = envPtr->pushSimpleWords; - - /* - * Scan the words of the command and record the start and finish of - * each argument word. - */ - - InitArgInfo(&argInfo); - result = CollectArgInfo(interp, string, lastChar, flags, &argInfo); - numWords = argInfo.numArgs; /* i.e., the # after the command name */ - if (result != TCL_OK) { - goto done; - } - if ((numWords != 1) && (numWords != 2)) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: should be \"catch command ?varName?\"", -1); - result = TCL_ERROR; - goto done; - } - - /* - * If a variable was specified and the catch command is at global level - * (not in a procedure), don't compile it inline: the payoff is - * too small. - */ - - if ((numWords == 2) && (procPtr == NULL)) { - result = TCL_OUT_LINE_COMPILE; - goto done; - } - - /* - * Make sure the variable name, if any, has no substitutions and just - * refers to a local scaler. - */ - - if (numWords == 2) { - char *firstChar = argInfo.startArray[1]; - char *lastChar = argInfo.endArray[1]; - - if (*firstChar == '{') { - if (*lastChar != '}') { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "extra characters after close-brace", -1); - result = TCL_ERROR; - goto done; - } - firstChar++; - lastChar--; - } - - nameChars = (lastChar - firstChar + 1); - if (nameChars > 0) { - char *p = firstChar; - while (p != lastChar) { - if (CHAR_TYPE(p, lastChar) != TCL_NORMAL) { - result = TCL_OUT_LINE_COMPILE; - goto done; - } - if (*p == '(') { - if (*lastChar == ')') { /* we have an array element */ - result = TCL_OUT_LINE_COMPILE; - goto done; - } - } - p++; - } - } - - name = firstChar; - localIndex = LookupCompiledLocal(name, nameChars, - /*createIfNew*/ 1, /*flagsIfCreated*/ VAR_SCALAR, - procPtr); - } - - /* - *==== At this point we believe we can compile the catch command ==== - */ - - /* - * Create and initialize a ExceptionRange record to hold information - * about this catch command. - */ - - envPtr->excRangeDepth++; - envPtr->maxExcRangeDepth = - TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth); - range = CreateExceptionRange(CATCH_EXCEPTION_RANGE, envPtr); - - /* - * Emit the instruction to mark the start of the catch command. - */ - - TclEmitInstUInt4(INST_BEGIN_CATCH4, range, envPtr); - - /* - * Inline compile the catch's body word: the command it controls. Also - * register the body's starting PC offset and byte length in the - * ExceptionRange record. - */ - - envPtr->excRangeArrayPtr[range].codeOffset = TclCurrCodeOffset(); - - bodyStart = argInfo.startArray[0]; - bodyEnd = argInfo.endArray[0]; - savedChar = *(bodyEnd+1); - *(bodyEnd+1) = '\0'; - result = CompileCmdWordInline(interp, bodyStart, (bodyEnd+1), - flags, envPtr); - *(bodyEnd+1) = savedChar; - - if (result != TCL_OK) { - if (result == TCL_ERROR) { - char msg[60]; - sprintf(msg, "\n (\"catch\" body line %d)", - interp->errorLine); - Tcl_AddObjErrorInfo(interp, msg, -1); - } - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - envPtr->excRangeArrayPtr[range].numCodeBytes = - TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range].codeOffset; - - /* - * Now emit the "no errors" epilogue code for the catch. First, if a - * variable was specified, store the body's result into the - * variable; otherwise, just discard the body's result. Then push - * a "0" object as the catch command's "no error" TCL_OK result, - * and jump around the "error case" epilogue code. - */ - - if (localIndex != -1) { - if (localIndex <= 255) { - TclEmitInstUInt1(INST_STORE_SCALAR1, localIndex, envPtr); - } else { - TclEmitInstUInt4(INST_STORE_SCALAR4, localIndex, envPtr); - } - } - TclEmitOpcode(INST_POP, envPtr); - - objIndex = TclObjIndexForString("0", 1, /*allocStrRep*/ 0, /*inHeap*/ 0, - envPtr); - objPtr = envPtr->objArrayPtr[objIndex]; - - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.longValue = 0; - objPtr->typePtr = &tclIntType; - - TclEmitPush(objIndex, envPtr); - if (maxDepth == 0) { - maxDepth = 1; /* since we just pushed one object */ - } - - TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); - - /* - * Now emit the "error case" epilogue code. First, if a variable was - * specified, emit instructions to push the interpreter's object result - * and store it into the variable. Then emit an instruction to push the - * nonzero error result. Note that the initial PC offset here is the - * catch's error target. - */ - - envPtr->excRangeArrayPtr[range].catchOffset = TclCurrCodeOffset(); - if (localIndex != -1) { - TclEmitOpcode(INST_PUSH_RESULT, envPtr); - if (localIndex <= 255) { - TclEmitInstUInt1(INST_STORE_SCALAR1, localIndex, envPtr); - } else { - TclEmitInstUInt4(INST_STORE_SCALAR4, localIndex, envPtr); - } - TclEmitOpcode(INST_POP, envPtr); - } - TclEmitOpcode(INST_PUSH_RETURN_CODE, envPtr); - - /* - * Now that we know the target of the jump after the "no errors" - * epilogue, update it with the correct distance. This is less - * than 127 bytes. - */ - - jumpDist = (TclCurrCodeOffset() - jumpFixup.codeOffset); - if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) { - panic("TclCompileCatchCmd: bad jump distance %d\n", jumpDist); - } - - /* - * Emit the instruction to mark the end of the catch command. - */ - - TclEmitOpcode(INST_END_CATCH, envPtr); - - done: - if (numWords == 0) { - envPtr->termOffset = 0; - } else { - envPtr->termOffset = (argInfo.endArray[numWords-1] + 1 - string); - } - if (range != -1) { /* we compiled the catch command */ - envPtr->excRangeDepth--; - } - envPtr->pushSimpleWords = savePushSimpleWords; - envPtr->maxStackDepth = maxDepth; - FreeArgInfo(&argInfo); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileContinueCmd -- - * - * Procedure called to compile the "continue" command. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK unless - * there was an error while parsing string. If an error occurs then - * the interpreter's result contains a standard error message. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * - * Side effects: - * Instructions are added to envPtr to evaluate the "continue" command - * at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileContinueCmd(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - register char *src = string;/* Points to current source char. */ - register int type; /* Current char's CHAR_TYPE type. */ - int result = TCL_OK; - - /* - * There should be no argument after the "continue". - */ - - type = CHAR_TYPE(src, lastChar); - if (type != TCL_COMMAND_END) { - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type != TCL_COMMAND_END) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: should be \"continue\"", -1); - result = TCL_ERROR; - goto done; - } - } - - /* - * Emit a continue instruction. - */ - - TclEmitOpcode(INST_CONTINUE, envPtr); - - done: - envPtr->termOffset = (src - string); - envPtr->maxStackDepth = 0; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileExprCmd -- - * - * Procedure called to compile the "expr" command. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK - * unless there was an error while parsing string. If an error occurs - * then the interpreter's result contains a standard error message. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the "expr" command. - * - * Side effects: - * Instructions are added to envPtr to evaluate the "expr" command - * at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileExprCmd(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute cmd. */ - ArgInfo argInfo; /* Structure holding information about the - * start and end of each argument word. */ - Tcl_DString buffer; /* Holds the concatenated expr command - * argument words. */ - int firstWord; /* 1 if processing the first word; 0 if - * processing subsequent words. */ - char *first, *last; /* Points to the first and last significant - * chars of the concatenated expression. */ - int inlineCode; /* 1 if inline "optimistic" code is - * emitted for the expression; else 0. */ - int range = -1; /* If we inline compile the concatenated - * expression, the index for its catch range - * record in the ExceptionRange array. - * Initialized to avoid compile warning. */ - JumpFixup jumpFixup; /* Used to emit the "success" jump after - * the inline concat. expression's code. */ - char savedChar; /* Holds the character termporarily replaced - * by a null character during compilation - * of the concatenated expression. */ - int numWords, objIndex, i, result; - char *wordStart, *wordEnd, *p; - char c; - int savePushSimpleWords = envPtr->pushSimpleWords; - int saveExprIsJustVarRef = envPtr->exprIsJustVarRef; - int saveExprIsComparison = envPtr->exprIsComparison; - - /* - * Scan the words of the command and record the start and finish of - * each argument word. - */ - - InitArgInfo(&argInfo); - result = CollectArgInfo(interp, string, lastChar, flags, &argInfo); - numWords = argInfo.numArgs; /* i.e., the # after the command name */ - if (result != TCL_OK) { - goto done; - } - if (numWords == 0) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: should be \"expr arg ?arg ...?\"", -1); - result = TCL_ERROR; - goto done; - } - - /* - * If there is a single argument word and it is enclosed in {}s, we may - * strip them off and safely compile the expr command into an inline - * sequence of instructions using TclCompileExpr. We know these - * instructions will have the right Tcl7.x expression semantics. - * - * Otherwise, if the word is not enclosed in {}s, or there are multiple - * words, we may need to call the expr command (Tcl_ExprObjCmd) at - * runtime. This recompiles the expression each time (typically) and so - * is slow. However, there are some circumstances where we can still - * compile inline instructions "optimistically" and check, during their - * execution, for double substitutions (these appear as nonnumeric - * operands). We check for any backslash or command substitutions. If - * none appear, and only variable substitutions are found, we generate - * inline instructions. If there is a compilation error, we must emit - * instructions that return the error at runtime, since this is when - * scripts in Tcl7.x would "see" the error. - * - * For now, if there are multiple words, or the single argument word is - * not in {}s, we concatenate the argument words and strip off any - * enclosing {}s or ""s. We call the expr command at runtime if - * either command or backslash substitutions appear (but not if - * only variable substitutions appear). - */ - - if (numWords == 1) { - wordStart = argInfo.startArray[0]; /* start of 1st arg word */ - wordEnd = argInfo.endArray[0]; /* last char of 1st arg word */ - if ((*wordStart == '{') && (*wordEnd == '}')) { - /* - * Simple case: a single argument word in {}'s. - */ - - *wordEnd = '\0'; - result = TclCompileExpr(interp, (wordStart + 1), wordEnd, - flags, envPtr); - *wordEnd = '}'; - - envPtr->termOffset = (wordEnd + 1) - string; - envPtr->pushSimpleWords = savePushSimpleWords; - FreeArgInfo(&argInfo); - return result; - } - } - - /* - * There are multiple words or no braces around the single word. - * Concatenate the expression's argument words while stripping off - * any enclosing {}s or ""s. - */ - - Tcl_DStringInit(&buffer); - firstWord = 1; - for (i = 0; i < numWords; i++) { - wordStart = argInfo.startArray[i]; - wordEnd = argInfo.endArray[i]; - if (((*wordStart == '{') && (*wordEnd == '}')) - || ((*wordStart == '"') && (*wordEnd == '"'))) { - wordStart++; - wordEnd--; - } - if (!firstWord) { - Tcl_DStringAppend(&buffer, " ", 1); - } - firstWord = 0; - if (wordEnd >= wordStart) { - Tcl_DStringAppend(&buffer, wordStart, (wordEnd-wordStart+1)); - } - } - - /* - * Scan the concatenated expression's characters looking for any - * '['s or (for now) '\'s. If any are found, just call the expr cmd - * at runtime. - */ - - inlineCode = 1; - first = Tcl_DStringValue(&buffer); - last = first + (Tcl_DStringLength(&buffer) - 1); - for (p = first; p <= last; p++) { - c = *p; - if ((c == '[') || (c == '\\')) { - inlineCode = 0; - break; - } - } - - if (inlineCode) { - /* - * Inline compile the concatenated expression inside a "catch" - * so that a runtime error will back off to a (slow) call on expr. - */ - - int startCodeOffset = (envPtr->codeNext - envPtr->codeStart); - int startRangeNext = envPtr->excRangeArrayNext; - - /* - * Create a ExceptionRange record to hold information about the - * "catch" range for the expression's inline code. Also emit the - * instruction to mark the start of the range. - */ - - envPtr->excRangeDepth++; - envPtr->maxExcRangeDepth = - TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth); - range = CreateExceptionRange(CATCH_EXCEPTION_RANGE, envPtr); - TclEmitInstUInt4(INST_BEGIN_CATCH4, range, envPtr); - - /* - * Inline compile the concatenated expression. - */ - - envPtr->excRangeArrayPtr[range].codeOffset = TclCurrCodeOffset(); - savedChar = *(last + 1); - *(last + 1) = '\0'; - result = TclCompileExpr(interp, first, last + 1, flags, envPtr); - *(last + 1) = savedChar; - - maxDepth = envPtr->maxStackDepth; - envPtr->excRangeArrayPtr[range].numCodeBytes = - TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range].codeOffset; - - if ((result != TCL_OK) || (envPtr->exprIsJustVarRef) - || (envPtr->exprIsComparison)) { - /* - * We must call the expr command at runtime. Either there was a - * compilation error or the inline code might fail to give the - * correct 2 level substitution semantics. - * - * The latter can happen if the expression consisted of just a - * single variable reference or if the top-level operator in the - * expr is a comparison (which might operate on strings). In the - * latter case, the expression's code might execute (apparently) - * successfully but produce the wrong result. We depend on its - * execution failing if a second level of substitutions is - * required. This causes the "catch" code we generate around the - * inline code to back off to a call on the expr command at - * runtime, and this always gives the right 2 level substitution - * semantics. - * - * We delete the inline code by backing up the code pc and catch - * index. Note that if there was a compilation error, we can't - * report the error yet since the expression might be valid - * after the second round of substitutions. - */ - - envPtr->codeNext = (envPtr->codeStart + startCodeOffset); - envPtr->excRangeArrayNext = startRangeNext; - inlineCode = 0; - } else { - TclEmitOpcode(INST_END_CATCH, envPtr); /* for ok case */ - TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); - envPtr->excRangeArrayPtr[range].catchOffset = TclCurrCodeOffset(); - TclEmitOpcode(INST_END_CATCH, envPtr); /* for error case */ - } - } - - /* - * Emit code for the (slow) call on the expr command at runtime. - * Generate code to concatenate the (already substituted once) - * expression words with a space between each word. - */ - - for (i = 0; i < numWords; i++) { - wordStart = argInfo.startArray[i]; - wordEnd = argInfo.endArray[i]; - savedChar = *(wordEnd + 1); - *(wordEnd + 1) = '\0'; - envPtr->pushSimpleWords = 1; - result = CompileWord(interp, wordStart, wordEnd+1, flags, envPtr); - *(wordEnd + 1) = savedChar; - if (result != TCL_OK) { - break; - } - if (i != (numWords - 1)) { - objIndex = TclObjIndexForString(" ", 1, /*allocStrRep*/ 1, - /*inHeap*/ 0, envPtr); - TclEmitPush(objIndex, envPtr); - maxDepth = TclMax((envPtr->maxStackDepth + 1), maxDepth); - } else { - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - } - } - if (result == TCL_OK) { - int concatItems = 2*numWords - 1; - while (concatItems > 255) { - TclEmitInstUInt1(INST_CONCAT1, 255, envPtr); - concatItems -= 254; /* concat pushes 1 obj, the result */ - } - if (concatItems > 1) { - TclEmitInstUInt1(INST_CONCAT1, concatItems, envPtr); - } - TclEmitOpcode(INST_EXPR_STK, envPtr); - } - - /* - * If emitting inline code, update the target of the jump after - * that inline code. - */ - - if (inlineCode) { - int jumpDist = (TclCurrCodeOffset() - jumpFixup.codeOffset); - if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) { - /* - * Update the inline expression code's catch ExceptionRange - * target since it, being after the jump, also moved down. - */ - - envPtr->excRangeArrayPtr[range].catchOffset += 3; - } - } - Tcl_DStringFree(&buffer); - - done: - if (numWords == 0) { - envPtr->termOffset = 0; - } else { - envPtr->termOffset = (argInfo.endArray[numWords-1] + 1 - string); - } - if (range != -1) { /* we inline compiled the expr */ - envPtr->excRangeDepth--; - } - envPtr->pushSimpleWords = savePushSimpleWords; - envPtr->exprIsJustVarRef = saveExprIsJustVarRef; - envPtr->exprIsComparison = saveExprIsComparison; - envPtr->maxStackDepth = maxDepth; - FreeArgInfo(&argInfo); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileForCmd -- - * - * Procedure called to compile the "for" command. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK unless - * there was an error while parsing string. If an error occurs then - * the interpreter's result contains a standard error message. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * - * Side effects: - * Instructions are added to envPtr to evaluate the "for" command - * at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileForCmd(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute cmd. */ - ArgInfo argInfo; /* Structure holding information about the - * start and end of each argument word. */ - int range1, range2; /* Indexes in the ExceptionRange array of - * the loop ranges for this loop: one for - * its body and one for its "next" cmd. */ - JumpFixup jumpFalseFixup; /* Used to update or replace the ifFalse - * jump after the "for" test when its target - * PC is determined. */ - int jumpBackDist, jumpBackOffset, testCodeOffset, jumpDist, objIndex; - unsigned char *jumpPc; - int savePushSimpleWords = envPtr->pushSimpleWords; - int numWords, result; - - /* - * Scan the words of the command and record the start and finish of - * each argument word. - */ - - InitArgInfo(&argInfo); - result = CollectArgInfo(interp, string, lastChar, flags, &argInfo); - numWords = argInfo.numArgs; /* i.e., the # after the command name */ - if (result != TCL_OK) { - goto done; - } - if (numWords != 4) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: should be \"for start test next command\"", -1); - result = TCL_ERROR; - goto done; - } - - /* - * If the test expression is enclosed in quotes (""s), don't compile - * the for inline. As a result of Tcl's two level substitution - * semantics for expressions, the expression might have a constant - * value that results in the loop never executing, or executing forever. - * Consider "set x 0; for {} "$x > 5" {incr x} {}": the loop body - * should never be executed. - */ - - if (*(argInfo.startArray[1]) == '"') { - result = TCL_OUT_LINE_COMPILE; - goto done; - } - - /* - * Create a ExceptionRange record for the for loop's body. This is used - * to implement break and continue commands inside the body. - * Then create a second ExceptionRange record for the "next" command in - * order to implement break (but not continue) inside it. The second, - * "next" ExceptionRange will always have a -1 continueOffset. - */ - - envPtr->excRangeDepth++; - envPtr->maxExcRangeDepth = - TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth); - range1 = CreateExceptionRange(LOOP_EXCEPTION_RANGE, envPtr); - range2 = CreateExceptionRange(LOOP_EXCEPTION_RANGE, envPtr); - - /* - * Compile inline the next word: the initial command. - */ - - result = CompileCmdWordInline(interp, argInfo.startArray[0], - (argInfo.endArray[0] + 1), flags, envPtr); - if (result != TCL_OK) { - if (result == TCL_ERROR) { - Tcl_AddObjErrorInfo(interp, "\n (\"for\" initial command)", -1); - } - goto done; - } - maxDepth = envPtr->maxStackDepth; - - /* - * Discard the start command's result. - */ - - TclEmitOpcode(INST_POP, envPtr); - - /* - * Compile the next word: the test expression. - */ - - testCodeOffset = TclCurrCodeOffset(); - envPtr->pushSimpleWords = 1; /* process words normally */ - result = CompileExprWord(interp, argInfo.startArray[1], - (argInfo.endArray[1] + 1), flags, envPtr); - if (result != TCL_OK) { - if (result == TCL_ERROR) { - Tcl_AddObjErrorInfo(interp, "\n (\"for\" test expression)", -1); - } - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - - /* - * Emit the jump that terminates the for command if the test was - * false. We emit a one byte (relative) jump here, and replace it later - * with a four byte jump if the jump target is > 127 bytes away. - */ - - TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup); - - /* - * Compile the loop body word inline. Also register the loop body's - * starting PC offset and byte length in the its ExceptionRange record. - */ - - envPtr->excRangeArrayPtr[range1].codeOffset = TclCurrCodeOffset(); - result = CompileCmdWordInline(interp, argInfo.startArray[3], - (argInfo.endArray[3] + 1), flags, envPtr); - if (result != TCL_OK) { - if (result == TCL_ERROR) { - char msg[60]; - sprintf(msg, "\n (\"for\" body line %d)", interp->errorLine); - Tcl_AddObjErrorInfo(interp, msg, -1); - } - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - envPtr->excRangeArrayPtr[range1].numCodeBytes = - (TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range1].codeOffset); - - /* - * Discard the loop body's result. - */ - - TclEmitOpcode(INST_POP, envPtr); - - /* - * Finally, compile the "next" subcommand word inline. - */ - - envPtr->excRangeArrayPtr[range1].continueOffset = TclCurrCodeOffset(); - envPtr->excRangeArrayPtr[range2].codeOffset = TclCurrCodeOffset(); - result = CompileCmdWordInline(interp, argInfo.startArray[2], - (argInfo.endArray[2] + 1), flags, envPtr); - if (result != TCL_OK) { - if (result == TCL_ERROR) { - Tcl_AddObjErrorInfo(interp, "\n (\"for\" loop-end command)", -1); - } - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - envPtr->excRangeArrayPtr[range2].numCodeBytes = - TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range2].codeOffset; - - /* - * Discard the "next" subcommand's result. - */ - - TclEmitOpcode(INST_POP, envPtr); - - /* - * Emit the unconditional jump back to the test at the top of the for - * loop. We generate a four byte jump if the distance to the test is - * greater than 120 bytes. This is conservative, and ensures that we - * won't have to replace this unconditional jump if we later need to - * replace the ifFalse jump with a four-byte jump. - */ - - jumpBackOffset = TclCurrCodeOffset(); - jumpBackDist = (jumpBackOffset - testCodeOffset); - if (jumpBackDist > 120) { - TclEmitInstInt4(INST_JUMP4, /*offset*/ -jumpBackDist, envPtr); - } else { - TclEmitInstInt1(INST_JUMP1, /*offset*/ -jumpBackDist, envPtr); - } - - /* - * Now that we know the target of the jumpFalse after the test, update - * it with the correct distance. If the distance is too great (more - * than 127 bytes), replace that jump with a four byte instruction and - * move the instructions after the jump down. - */ - - jumpDist = (TclCurrCodeOffset() - jumpFalseFixup.codeOffset); - if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) { - /* - * Update the loop body's ExceptionRange record since it moved down: - * i.e., increment both its start and continue PC offsets. Also, - * update the "next" command's start PC offset in its ExceptionRange - * record since it also moved down. - */ - - envPtr->excRangeArrayPtr[range1].codeOffset += 3; - envPtr->excRangeArrayPtr[range1].continueOffset += 3; - envPtr->excRangeArrayPtr[range2].codeOffset += 3; - - /* - * Update the distance for the unconditional jump back to the test - * at the top of the loop since it moved down 3 bytes too. - */ - - jumpBackOffset += 3; - jumpPc = (envPtr->codeStart + jumpBackOffset); - if (jumpBackDist > 120) { - jumpBackDist += 3; - TclUpdateInstInt4AtPc(INST_JUMP4, /*offset*/ -jumpBackDist, - jumpPc); - } else { - jumpBackDist += 3; - TclUpdateInstInt1AtPc(INST_JUMP1, /*offset*/ -jumpBackDist, - jumpPc); - } - } - - /* - * The current PC offset (after the loop's body and "next" subcommand) - * is the loop's break target. - */ - - envPtr->excRangeArrayPtr[range1].breakOffset = - envPtr->excRangeArrayPtr[range2].breakOffset = TclCurrCodeOffset(); - - /* - * Push an empty string object as the for command's result. - */ - - objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0, /*inHeap*/ 0, - envPtr); - TclEmitPush(objIndex, envPtr); - if (maxDepth == 0) { - maxDepth = 1; - } - - done: - if (numWords == 0) { - envPtr->termOffset = 0; - } else { - envPtr->termOffset = (argInfo.endArray[numWords-1] + 1 - string); - } - envPtr->pushSimpleWords = savePushSimpleWords; - envPtr->maxStackDepth = maxDepth; - envPtr->excRangeDepth--; - FreeArgInfo(&argInfo); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileForeachCmd -- - * - * Procedure called to compile the "foreach" command. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK if - * compilation was successful. If an error occurs then the - * interpreter's result contains a standard error message and TCL_ERROR - * is returned. If complation failed because the command is too complex - * for TclCompileForeachCmd, TCL_OUT_LINE_COMPILE is returned - * indicating that the foreach command should be compiled "out of line" - * by emitting code to invoke its command procedure at runtime. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the "while" command. - * - * Side effects: - * Instructions are added to envPtr to evaluate the "foreach" command - * at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileForeachCmd(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - Proc *procPtr = envPtr->procPtr; - /* Points to structure describing procedure - * containing foreach command, else NULL. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute cmd. */ - ArgInfo argInfo; /* Structure holding information about the - * start and end of each argument word. */ - int numLists = 0; /* Count of variable (and value) lists. */ - int range; /* Index in the ExceptionRange array of the - * ExceptionRange record for this loop. */ - ForeachInfo *infoPtr; /* Points to the structure describing this - * foreach command. Stored in a AuxData - * record in the ByteCode. */ - JumpFixup jumpFalseFixup; /* Used to update or replace the ifFalse - * jump after test when its target PC is - * determined. */ - char savedChar; /* Holds the char from string termporarily - * replaced by a null character during - * processing of argument words. */ - int firstListTmp = -1; /* If we decide to compile this foreach - * command, this is the index or "slot - * number" for the first temp var allocated - * in the proc frame that holds a pointer to - * a value list. Initialized to avoid a - * compiler warning. */ - int loopIterNumTmp; /* If we decide to compile this foreach - * command, the index for the temp var that - * holds the current iteration count. */ - char *varListStart, *varListEnd, *valueListStart, *bodyStart, *bodyEnd; - unsigned char *jumpPc; - int jumpDist, jumpBackDist, jumpBackOffset; - int numWords, numVars, infoIndex, tmpIndex, objIndex, i, j, result; - int savePushSimpleWords = envPtr->pushSimpleWords; - - /* - * We parse the variable list argument words and create two arrays: - * varcList[i] gives the number of variables in the i-th var list - * varvList[i] points to an array of the names in the i-th var list - * These are initially allocated on the stack, and are allocated on - * the heap if necessary. - */ - -#define STATIC_VAR_LIST_SIZE 4 - int varcListStaticSpace[STATIC_VAR_LIST_SIZE]; - char **varvListStaticSpace[STATIC_VAR_LIST_SIZE]; - - int *varcList = varcListStaticSpace; - char ***varvList = varvListStaticSpace; - - /* - * If the foreach command is at global level (not in a procedure), - * don't compile it inline: the payoff is too small. - */ - - if (procPtr == NULL) { - return TCL_OUT_LINE_COMPILE; - } - - /* - * Scan the words of the command and record the start and finish of - * each argument word. - */ - - InitArgInfo(&argInfo); - result = CollectArgInfo(interp, string, lastChar, flags, &argInfo); - numWords = argInfo.numArgs; - if (result != TCL_OK) { - goto done; - } - if ((numWords < 3) || (numWords%2 != 1)) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: should be \"foreach varList list ?varList list ...? command\"", -1); - result = TCL_ERROR; - goto done; - } - - /* - * Initialize the varcList and varvList arrays; allocate heap storage, - * if necessary, for them. Also make sure the variable names - * have no substitutions: that they're just "var" or "var(elem)" - */ - - numLists = (numWords - 1)/2; - if (numLists > STATIC_VAR_LIST_SIZE) { - varcList = (int *) ckalloc(numLists * sizeof(int)); - varvList = (char ***) ckalloc(numLists * sizeof(char **)); - } - for (i = 0; i < numLists; i++) { - varcList[i] = 0; - varvList[i] = (char **) NULL; - } - for (i = 0; i < numLists; i++) { - /* - * Break each variable list into its component variables. If the - * lists is enclosed in {}s or ""s, strip them off first. - */ - - varListStart = argInfo.startArray[i*2]; - varListEnd = argInfo.endArray[i*2]; - if ((*varListStart == '{') || (*varListStart == '"')) { - if ((*varListEnd != '}') && (*varListEnd != '"')) { - Tcl_ResetResult(interp); - if (*varListStart == '"') { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "extra characters after close-quote", -1); - } else { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "extra characters after close-brace", -1); - } - result = TCL_ERROR; - goto done; - } - varListStart++; - varListEnd--; - } - - /* - * NOTE: THIS NEEDS TO BE CONVERTED TO AN OBJECT LIST. - */ - - savedChar = *(varListEnd+1); - *(varListEnd+1) = '\0'; - result = Tcl_SplitList(interp, varListStart, - &varcList[i], &varvList[i]); - *(varListEnd+1) = savedChar; - if (result != TCL_OK) { - goto done; - } - - /* - * Check that each variable name has no substitutions and that - * it is a scalar name. - */ - - numVars = varcList[i]; - for (j = 0; j < numVars; j++) { - char *varName = varvList[i][j]; - char *p = varName; - while (*p != '\0') { - if (CHAR_TYPE(p, p+1) != TCL_NORMAL) { - result = TCL_OUT_LINE_COMPILE; - goto done; - } - if (*p == '(') { - char *q = p; - do { - q++; - } while (*q != '\0'); - q--; - if (*q == ')') { /* we have an array element */ - result = TCL_OUT_LINE_COMPILE; - goto done; - } - } - p++; - } - } - } - - /* - *==== At this point we believe we can compile the foreach command ==== - */ - - /* - * Create and initialize a ExceptionRange record to hold information - * about this loop. This is used to implement break and continue. - */ - - envPtr->excRangeDepth++; - envPtr->maxExcRangeDepth = - TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth); - range = CreateExceptionRange(LOOP_EXCEPTION_RANGE, envPtr); - - /* - * Reserve (numLists + 1) temporary variables: - * - numLists temps for each value list - * - a temp for the "next value" index into each value list - * At this time we don't try to reuse temporaries; if there are two - * nonoverlapping foreach loops, they don't share any temps. - */ - - for (i = 0; i < numLists; i++) { - tmpIndex = LookupCompiledLocal(NULL, /*nameChars*/ 0, - /*createIfNew*/ 1, /*flagsIfCreated*/ VAR_SCALAR, procPtr); - if (i == 0) { - firstListTmp = tmpIndex; - } - } - loopIterNumTmp = LookupCompiledLocal(NULL, /*nameChars*/ 0, - /*createIfNew*/ 1, /*flagsIfCreated*/ VAR_SCALAR, procPtr); - - /* - * Create and initialize the ForeachInfo and ForeachVarList data - * structures describing this command. Then create a AuxData record - * pointing to the ForeachInfo structure in the compilation environment. - */ - - infoPtr = (ForeachInfo *) ckalloc((unsigned) - (sizeof(ForeachInfo) + (numLists * sizeof(ForeachVarList *)))); - infoPtr->numLists = numLists; - infoPtr->firstListTmp = firstListTmp; - infoPtr->loopIterNumTmp = loopIterNumTmp; - for (i = 0; i < numLists; i++) { - ForeachVarList *varListPtr; - numVars = varcList[i]; - varListPtr = (ForeachVarList *) ckalloc((unsigned) - sizeof(ForeachVarList) + numVars*sizeof(int)); - varListPtr->numVars = numVars; - for (j = 0; j < numVars; j++) { - char *varName = varvList[i][j]; - int nameChars = strlen(varName); - varListPtr->varIndexes[j] = LookupCompiledLocal(varName, - nameChars, /*createIfNew*/ 1, - /*flagsIfCreated*/ VAR_SCALAR, procPtr); - } - infoPtr->varLists[i] = varListPtr; - } - infoIndex = TclCreateAuxData((ClientData) infoPtr, - DupForeachInfo, FreeForeachInfo, envPtr); - - /* - * Emit code to store each value list into the associated temporary. - */ - - for (i = 0; i < numLists; i++) { - valueListStart = argInfo.startArray[2*i + 1]; - envPtr->pushSimpleWords = 1; - result = CompileWord(interp, valueListStart, lastChar, flags, - envPtr); - if (result != TCL_OK) { - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - - tmpIndex = (firstListTmp + i); - if (tmpIndex <= 255) { - TclEmitInstUInt1(INST_STORE_SCALAR1, tmpIndex, envPtr); - } else { - TclEmitInstUInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - } - TclEmitOpcode(INST_POP, envPtr); - } - - /* - * Emit the instruction to initialize the foreach loop's index temp var. - */ - - TclEmitInstUInt4(INST_FOREACH_START4, infoIndex, envPtr); - - /* - * Emit the top of loop code that assigns each loop variable and checks - * whether to terminate the loop. - */ - - envPtr->excRangeArrayPtr[range].continueOffset = TclCurrCodeOffset(); - TclEmitInstUInt4(INST_FOREACH_STEP4, infoIndex, envPtr); - - /* - * Emit the ifFalse jump that terminates the foreach if all value lists - * are exhausted. We emit a one byte (relative) jump here, and replace - * it later with a four byte jump if the jump target is more than - * 127 bytes away. - */ - - TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup); - - /* - * Compile the loop body word inline. Also register the loop body's - * starting PC offset and byte length in the ExceptionRange record. - */ - - bodyStart = argInfo.startArray[numWords - 1]; - bodyEnd = argInfo.endArray[numWords - 1]; - savedChar = *(bodyEnd+1); - *(bodyEnd+1) = '\0'; - envPtr->excRangeArrayPtr[range].codeOffset = TclCurrCodeOffset(); - result = CompileCmdWordInline(interp, bodyStart, bodyEnd+1, flags, - envPtr); - *(bodyEnd+1) = savedChar; - if (result != TCL_OK) { - if (result == TCL_ERROR) { - char msg[60]; - sprintf(msg, "\n (\"foreach\" body line %d)", - interp->errorLine); - Tcl_AddObjErrorInfo(interp, msg, -1); - } - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - envPtr->excRangeArrayPtr[range].numCodeBytes = - TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range].codeOffset; - - /* - * Discard the loop body's result. - */ - - TclEmitOpcode(INST_POP, envPtr); - - /* - * Emit the unconditional jump back to the test at the top of the - * loop. We generate a four byte jump if the distance to the to of - * the foreach is greater than 120 bytes. This is conservative and - * ensures that we won't have to replace this unconditional jump if - * we later need to replace the ifFalse jump with a four-byte jump. - */ - - jumpBackOffset = TclCurrCodeOffset(); - jumpBackDist = - (jumpBackOffset - envPtr->excRangeArrayPtr[range].continueOffset); - if (jumpBackDist > 120) { - TclEmitInstInt4(INST_JUMP4, /*offset*/ -jumpBackDist, envPtr); - } else { - TclEmitInstInt1(INST_JUMP1, /*offset*/ -jumpBackDist, envPtr); - } - - /* - * Now that we know the target of the jumpFalse after the foreach_step - * test, update it with the correct distance. If the distance is too - * great (more than 127 bytes), replace that jump with a four byte - * instruction and move the instructions after the jump down. - */ - - jumpDist = (TclCurrCodeOffset() - jumpFalseFixup.codeOffset); - if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) { - /* - * Update the loop body's starting PC offset since it moved down. - */ - - envPtr->excRangeArrayPtr[range].codeOffset += 3; - - /* - * Update the distance for the unconditional jump back to the test - * at the top of the loop since it moved down 3 bytes too. - */ - - jumpBackOffset += 3; - jumpPc = (envPtr->codeStart + jumpBackOffset); - if (jumpBackDist > 120) { - jumpBackDist += 3; - TclUpdateInstInt4AtPc(INST_JUMP4, /*offset*/ -jumpBackDist, - jumpPc); - } else { - jumpBackDist += 3; - TclUpdateInstInt1AtPc(INST_JUMP1, /*offset*/ -jumpBackDist, - jumpPc); - } - } - - /* - * The current PC offset (after the loop's body) is the loop's - * break target. - */ - - envPtr->excRangeArrayPtr[range].breakOffset = TclCurrCodeOffset(); - - /* - * Push an empty string object as the foreach command's result. - */ - - objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0, /*inHeap*/ 0, - envPtr); - TclEmitPush(objIndex, envPtr); - if (maxDepth == 0) { - maxDepth = 1; - } - - done: - for (i = 0; i < numLists; i++) { - if (varvList[i] != (char **) NULL) { - ckfree((char *) varvList[i]); - } - } - if (varcList != varcListStaticSpace) { - ckfree((char *) varcList); - ckfree((char *) varvList); - } - envPtr->termOffset = (argInfo.endArray[numWords-1] + 1 - string); - envPtr->pushSimpleWords = savePushSimpleWords; - envPtr->maxStackDepth = maxDepth; - envPtr->excRangeDepth--; - FreeArgInfo(&argInfo); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * 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 clientData; /* The foreach command's compilation - * auxiliary data to duplicate. */ -{ - register ForeachInfo *srcPtr = (ForeachInfo *) clientData; - ForeachInfo *dupPtr; - register ForeachVarList *srcListPtr, *dupListPtr; - int numLists = srcPtr->numLists; - int numVars, i, j; - - dupPtr = (ForeachInfo *) ckalloc((unsigned) - (sizeof(ForeachInfo) + (numLists * sizeof(ForeachVarList *)))); - dupPtr->numLists = numLists; - dupPtr->firstListTmp = srcPtr->firstListTmp; - dupPtr->loopIterNumTmp = srcPtr->loopIterNumTmp; - - for (i = 0; i < numLists; i++) { - srcListPtr = srcPtr->varLists[i]; - numVars = srcListPtr->numVars; - dupListPtr = (ForeachVarList *) ckalloc((unsigned) - 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 (ClientData) 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. + * LogCompilationInfo -- + * + * This procedure is invoked after an error occurs during compilation. + * It adds information to the "errorInfo" variable to describe the + * command that was being compiled when the error occurred. + * + * Results: + * None. + * + * Side effects: + * Information about the command is added to errorInfo and the + * line number stored internally in the interpreter is set. If this + * is the first call to this procedure or Tcl_AddObjErrorInfo since + * an error occurred, then old information in errorInfo is + * deleted. * *---------------------------------------------------------------------- */ static void -FreeForeachInfo(clientData) - ClientData clientData; /* The foreach command's compilation - * auxiliary data to free. */ -{ - register ForeachInfo *infoPtr = (ForeachInfo *) clientData; - register ForeachVarList *listPtr; - int numLists = infoPtr->numLists; - register int i; - - for (i = 0; i < numLists; i++) { - listPtr = infoPtr->varLists[i]; - ckfree((char *) listPtr); - } - ckfree((char *) infoPtr); -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileIfCmd -- - * - * Procedure called to compile the "if" command. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK unless - * there was an error while parsing string. If an error occurs then - * the interpreter's result contains a standard error message. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * - * Side effects: - * Instructions are added to envPtr to evaluate the "if" command - * at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileIfCmd(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - register char *src = string;/* Points to current source char. */ - register int type; /* Current char's CHAR_TYPE type. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute cmd. */ - JumpFixupArray jumpFalseFixupArray; - /* Used to fix up the ifFalse jump after - * each "if"/"elseif" test when its target - * PC is determined. */ - JumpFixupArray jumpEndFixupArray; - /* Used to fix up the unconditional jump - * after each "then" command to the end of - * the "if" when that PC is determined. */ - char *testSrcStart; - int jumpDist, jumpFalseDist, jumpIndex, objIndex, j, result; - unsigned char *ifFalsePc; - unsigned char opCode; - int savePushSimpleWords = envPtr->pushSimpleWords; - - /* - * Loop compiling "expr then body" clauses after an "if" or "elseif". - */ - - TclInitJumpFixupArray(&jumpFalseFixupArray); - TclInitJumpFixupArray(&jumpEndFixupArray); - while (1) { - /* - * At this point in the loop, we have an expression to test, either - * 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. - */ - - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type == TCL_COMMAND_END) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: no expression after \"if\" argument", -1); - result = TCL_ERROR; - goto done; - } - - /* - * Compile the "if"/"elseif" test expression. - */ - - testSrcStart = src; - envPtr->pushSimpleWords = 1; - result = CompileExprWord(interp, src, lastChar, flags, envPtr); - if (result != TCL_OK) { - if (result == TCL_ERROR) { - Tcl_AddObjErrorInfo(interp, - "\n (\"if\" test expression)", -1); - } - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - src += envPtr->termOffset; - - /* - * Emit the ifFalse jump around the "then" part if the test was - * false. We emit a one byte (relative) jump here, and replace it - * later with a four byte jump if the jump target is more than 127 - * bytes away. - */ - - if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) { - TclExpandJumpFixupArray(&jumpFalseFixupArray); - } - jumpIndex = jumpFalseFixupArray.next; - jumpFalseFixupArray.next++; - TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, - &(jumpFalseFixupArray.fixup[jumpIndex])); - - /* - * Skip over the optional "then" before the then clause. - */ - - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type == TCL_COMMAND_END) { - char buf[100]; - sprintf(buf, "wrong # args: no script following \"%.20s\" argument", testSrcStart); - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); - result = TCL_ERROR; - goto done; - } - if ((*src == 't') && (strncmp(src, "then", 4) == 0)) { - type = CHAR_TYPE(src+4, lastChar); - if ((type == TCL_SPACE) || (type == TCL_COMMAND_END)) { - src += 4; - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type == TCL_COMMAND_END) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: no script following \"then\" argument", -1); - result = TCL_ERROR; - goto done; - } - } - } - - /* - * Compile the "then" command word inline. - */ - - result = CompileCmdWordInline(interp, src, lastChar, flags, envPtr); - if (result != TCL_OK) { - if (result == TCL_ERROR) { - char msg[60]; - sprintf(msg, "\n (\"if\" then script line %d)", - interp->errorLine); - Tcl_AddObjErrorInfo(interp, msg, -1); - } - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - src += envPtr->termOffset; - - /* - * Emit an unconditional jump to the end of the "if" command. We - * emit a one byte jump here, and replace it later with a four byte - * jump if the jump target is more than 127 bytes away. Note that - * both the jumpFalseFixupArray and the jumpEndFixupArray are - * indexed by the same index, "jumpIndex". - */ - - if (jumpEndFixupArray.next >= jumpEndFixupArray.end) { - TclExpandJumpFixupArray(&jumpEndFixupArray); - } - jumpEndFixupArray.next++; - TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, - &(jumpEndFixupArray.fixup[jumpIndex])); - - /* - * Now that we know the target of the jumpFalse after the if test, - * update it with the correct distance. We generate a four byte - * jump if the distance is greater than 120 bytes. This is - * conservative, and ensures that we won't have to replace this - * jump if we later also need to replace the preceeding - * unconditional jump to the end of the "if" with a four-byte jump. - */ - - jumpDist = (TclCurrCodeOffset() - jumpFalseFixupArray.fixup[jumpIndex].codeOffset); - if (TclFixupForwardJump(envPtr, - &(jumpFalseFixupArray.fixup[jumpIndex]), jumpDist, 120)) { - /* - * Adjust the code offset for the unconditional jump at the end - * of the last "then" clause. - */ - - jumpEndFixupArray.fixup[jumpIndex].codeOffset += 3; - } - - /* - * Check now for a "elseif" word. If we find one, keep looping. - */ - - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if ((type != TCL_COMMAND_END) - && ((*src == 'e') && (strncmp(src, "elseif", 6) == 0))) { - type = CHAR_TYPE(src+6, lastChar); - if ((type == TCL_SPACE) || (type == TCL_COMMAND_END)) { - src += 6; - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type == TCL_COMMAND_END) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: no expression after \"elseif\" argument", -1); - result = TCL_ERROR; - goto done; - } - continue; /* continue the "expr then body" loop */ - } - } - break; - } /* end of the "expr then body" loop */ - - /* - * No more "elseif expr then body" clauses. Check now for an "else" - * clause. If there is another word, we are at its start. - */ - - if (type != TCL_COMMAND_END) { - if ((*src == 'e') && (strncmp(src, "else", 4) == 0)) { - type = CHAR_TYPE(src+4, lastChar); - if ((type == TCL_SPACE) || (type == TCL_COMMAND_END)) { - src += 4; - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type == TCL_COMMAND_END) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: no script following \"else\" argument", -1); - result = TCL_ERROR; - goto done; - } - } - } - - /* - * Compile the "else" command word inline. - */ - - result = CompileCmdWordInline(interp, src, lastChar, flags, envPtr); - if (result != TCL_OK) { - if (result == TCL_ERROR) { - char msg[60]; - sprintf(msg, "\n (\"if\" else script line %d)", - interp->errorLine); - Tcl_AddObjErrorInfo(interp, msg, -1); - } - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - src += envPtr->termOffset; - - /* - * Skip over white space until the end of the command. - */ - - type = CHAR_TYPE(src, lastChar); - if (type != TCL_COMMAND_END) { - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type != TCL_COMMAND_END) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: extra words after \"else\" clause in \"if\" command", -1); - result = TCL_ERROR; - goto done; - } - } - } else { - /* - * The "if" command has no "else" clause: push an empty string - * object as its result. - */ - - objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0, - /*inHeap*/ 0, envPtr); - TclEmitPush(objIndex, envPtr); - maxDepth = TclMax(1, maxDepth); - } - - /* - * Now that we know the target of the unconditional jumps to the end of - * the "if" command, update them with the correct distance. If the - * distance is too great (> 127 bytes), replace the jump with a four - * byte instruction and move instructions after the jump down. - */ - - for (j = jumpEndFixupArray.next; j > 0; j--) { - jumpIndex = (j - 1); /* i.e. process the closest jump first */ - jumpDist = (TclCurrCodeOffset() - jumpEndFixupArray.fixup[jumpIndex].codeOffset); - if (TclFixupForwardJump(envPtr, - &(jumpEndFixupArray.fixup[jumpIndex]), jumpDist, 127)) { - /* - * Adjust the jump distance for the "ifFalse" jump that - * immediately preceeds this jump. We've moved it's target - * (just after this unconditional jump) three bytes down. - */ - - ifFalsePc = (envPtr->codeStart + jumpFalseFixupArray.fixup[jumpIndex].codeOffset); - 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 { - panic("TclCompileIfCmd: unexpected opcode updating ifFalse jump"); - } - } - } - - /* - * Free the jumpFixupArray array if malloc'ed storage was used. - */ - - done: - TclFreeJumpFixupArray(&jumpFalseFixupArray); - TclFreeJumpFixupArray(&jumpEndFixupArray); - envPtr->termOffset = (src - string); - envPtr->maxStackDepth = maxDepth; - envPtr->pushSimpleWords = savePushSimpleWords; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileIncrCmd -- - * - * Procedure called to compile the "incr" command. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK unless - * there was an error while parsing string. If an error occurs then - * the interpreter's result contains a standard error message. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the "incr" command. - * - * Side effects: - * Instructions are added to envPtr to evaluate the "incr" command - * at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileIncrCmd(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - Proc *procPtr = envPtr->procPtr; - /* Points to structure describing procedure - * containing incr command, else NULL. */ - register char *src = string; - /* Points to current source char. */ - register int type; /* Current char's CHAR_TYPE type. */ - int simpleVarName; /* 1 if name is just sequence of chars with - * an optional element name in parens. */ - char *name = NULL; /* If simpleVarName, points to first char of - * variable name and nameChars is length. - * Otherwise NULL. */ - char *elName = NULL; /* If simpleVarName, points to first char of - * element name and elNameChars is length. - * Otherwise NULL. */ - int nameChars = 0; /* Length of the var name. Initialized to - * avoid a compiler warning. */ - int elNameChars = 0; /* Length of array's element name, if any. - * Initialized to avoid a compiler - * warning. */ - int incrementGiven; /* 1 if an increment amount was given. */ - int isImmIncrValue = 0; /* 1 if increment amount is a literal - * integer in [-127..127]. */ - int immIncrValue = 0; /* if isImmIncrValue is 1, the immediate - * integer value. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute cmd. */ - int localIndex = -1; /* Index of the variable in the current - * procedure's array of local variables. - * Otherwise -1 if not in a procedure or - * the variable wasn't found. */ - char savedChar; /* Holds the character from string - * termporarily replaced by a null char - * during name processing. */ - int objIndex; /* The object array index for a pushed - * object holding a name part. */ - int savePushSimpleWords = envPtr->pushSimpleWords; - char *p; - int i, result; - - /* - * Parse the next word: the variable name. If it is "simple" (requires - * no substitutions at runtime), divide it up into a simple "name" plus - * an optional "elName". Otherwise, if not simple, just push the name. - */ - - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type == TCL_COMMAND_END) { - badArgs: - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: should be \"incr varName ?increment?\"", -1); - result = TCL_ERROR; - goto done; - } - - envPtr->pushSimpleWords = 0; - result = CompileWord(interp, src, lastChar, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - simpleVarName = envPtr->wordIsSimple; - if (simpleVarName) { - name = src; - nameChars = envPtr->numSimpleWordChars; - if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) { - name++; - } - elName = NULL; - elNameChars = 0; - p = name; - for (i = 0; i < nameChars; i++) { - if (*p == '(') { - char *openParen = p; - p = (src + nameChars-1); - if (*p == ')') { /* last char is ')' => array reference */ - nameChars = (openParen - name); - elName = openParen+1; - elNameChars = (p - elName); - } - break; - } - p++; - } - } else { - maxDepth = envPtr->maxStackDepth; - } - src += envPtr->termOffset; - - /* - * See if there is a next word. If so, we are incrementing the variable - * by that value (which must be an integer). - */ - - incrementGiven = 0; - type = CHAR_TYPE(src, lastChar); - if (type != TCL_COMMAND_END) { - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - incrementGiven = (type != TCL_COMMAND_END); - } - - /* - * Non-simple names have already been pushed. If this is a simple - * variable, either push its name (if a global or an unknown local - * variable) or look up the variable's local frame index. If a local is - * not found, push its name and do the lookup at runtime. If this is an - * array reference, also push the array element. - */ - - if (simpleVarName) { - if (procPtr == NULL) { - savedChar = name[nameChars]; - name[nameChars] = '\0'; - objIndex = TclObjIndexForString(name, nameChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - name[nameChars] = savedChar; - TclEmitPush(objIndex, envPtr); - maxDepth = 1; - } else { - localIndex = LookupCompiledLocal(name, nameChars, - /*createIfNew*/ 0, /*flagsIfCreated*/ 0, - envPtr->procPtr); - if ((localIndex < 0) || (localIndex > 255)) { - if (localIndex > 255) { /* we'll push the name */ - localIndex = -1; - } - savedChar = name[nameChars]; - name[nameChars] = '\0'; - objIndex = TclObjIndexForString(name, nameChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - name[nameChars] = savedChar; - TclEmitPush(objIndex, envPtr); - maxDepth = 1; - } else { - maxDepth = 0; - } - } - - if (elName != NULL) { - /* - * Parse and push the array element's name. Perform - * substitutions on it, just as is done for quoted strings. - */ - - savedChar = elName[elNameChars]; - elName[elNameChars] = '\0'; - envPtr->pushSimpleWords = 1; - result = TclCompileQuotes(interp, elName, elName+elNameChars, - 0, flags, envPtr); - elName[elNameChars] = savedChar; - if (result != TCL_OK) { - char msg[200]; - sprintf(msg, "\n (parsing index for array \"%.*s\")", - TclMin(nameChars, 100), name); - Tcl_AddObjErrorInfo(interp, msg, -1); - goto done; - } - maxDepth += envPtr->maxStackDepth; - } - } - - /* - * If an increment was given, push the new value. - */ - - if (incrementGiven) { - type = CHAR_TYPE(src, lastChar); - envPtr->pushSimpleWords = 0; - result = CompileWord(interp, src, lastChar, flags, envPtr); - if (result != TCL_OK) { - if (result == TCL_ERROR) { - Tcl_AddObjErrorInfo(interp, - "\n (increment expression)", -1); - } - goto done; - } - if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) { - src++; - } - if (envPtr->wordIsSimple) { - /* - * See if the word represents an integer whose formatted - * representation is the same as the word (e.g., this is - * true for 123 and -1 but not for 00005). If so, just - * push an integer object. - */ - - int isCompilableInt = 0; - int numChars = envPtr->numSimpleWordChars; - char savedChar = src[numChars]; - char buf[40]; - Tcl_Obj *objPtr; - long n; - - src[numChars] = '\0'; - if (TclLooksLikeInt(src)) { - int code = TclGetLong(interp, src, &n); - if (code == TCL_OK) { - if ((-127 <= n) && (n <= 127)) { - isCompilableInt = 1; - isImmIncrValue = 1; - immIncrValue = n; - } else { - TclFormatInt(buf, n); - if (strcmp(src, buf) == 0) { - isCompilableInt = 1; - isImmIncrValue = 0; - objIndex = TclObjIndexForString(src, numChars, - /*allocStrRep*/ 0, /*inHeap*/ 0, envPtr); - objPtr = envPtr->objArrayPtr[objIndex]; - - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.longValue = n; - objPtr->typePtr = &tclIntType; - - TclEmitPush(objIndex, envPtr); - maxDepth += 1; - } - } - } else { - Tcl_ResetResult(interp); - } - } - if (!isCompilableInt) { - objIndex = TclObjIndexForString(src, numChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - TclEmitPush(objIndex, envPtr); - maxDepth += 1; - } - src[numChars] = savedChar; - } else { - maxDepth += envPtr->maxStackDepth; - } - if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) { - src += (envPtr->termOffset - 1); /* already advanced 1 above */ - } else { - src += envPtr->termOffset; - } - } else { /* no incr amount given so use 1 */ - isImmIncrValue = 1; - immIncrValue = 1; - } - - /* - * Now emit instructions to increment the variable. - */ - - if (simpleVarName) { - if (elName == NULL) { /* scalar */ - if (localIndex >= 0) { - if (isImmIncrValue) { - TclEmitInstUInt1(INST_INCR_SCALAR1_IMM, localIndex, - envPtr); - TclEmitInt1(immIncrValue, envPtr); - } else { - TclEmitInstUInt1(INST_INCR_SCALAR1, localIndex, envPtr); - } - } else { - if (isImmIncrValue) { - TclEmitInstInt1(INST_INCR_SCALAR_STK_IMM, immIncrValue, - envPtr); - } else { - TclEmitOpcode(INST_INCR_SCALAR_STK, envPtr); - } - } - } else { /* array */ - if (localIndex >= 0) { - if (isImmIncrValue) { - TclEmitInstUInt1(INST_INCR_ARRAY1_IMM, localIndex, - envPtr); - TclEmitInt1(immIncrValue, envPtr); - } else { - TclEmitInstUInt1(INST_INCR_ARRAY1, localIndex, envPtr); - } - } else { - if (isImmIncrValue) { - TclEmitInstInt1(INST_INCR_ARRAY_STK_IMM, immIncrValue, - envPtr); - } else { - TclEmitOpcode(INST_INCR_ARRAY_STK, envPtr); - } - } - } - } else { /* non-simple variable name */ - if (isImmIncrValue) { - TclEmitInstInt1(INST_INCR_STK_IMM, immIncrValue, envPtr); - } else { - TclEmitOpcode(INST_INCR_STK, envPtr); - } - } - - /* - * Skip over white space until the end of the command. - */ - - type = CHAR_TYPE(src, lastChar); - if (type != TCL_COMMAND_END) { - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type != TCL_COMMAND_END) { - goto badArgs; - } - } - - done: - envPtr->termOffset = (src - string); - envPtr->maxStackDepth = maxDepth; - envPtr->pushSimpleWords = savePushSimpleWords; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileSetCmd -- - * - * Procedure called to compile the "set" command. - * - * Results: - * The return value is a standard Tcl result, which is normally TCL_OK - * unless there was an error while parsing string. If an error occurs - * then the interpreter's result contains a standard error message. If - * complation fails because the set command requires a second level of - * substitutions, TCL_OUT_LINE_COMPILE is returned indicating that the - * set command should be compiled "out of line" by emitting code to - * invoke its command procedure (Tcl_SetCmd) at runtime. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the incr command. - * - * Side effects: - * Instructions are added to envPtr to evaluate the "set" command - * at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileSetCmd(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - Proc *procPtr = envPtr->procPtr; - /* Points to structure describing procedure - * containing the set command, else NULL. */ - ArgInfo argInfo; /* Structure holding information about the - * start and end of each argument word. */ - int simpleVarName; /* 1 if name is just sequence of chars with - * an optional element name in parens. */ - char *elName = NULL; /* If simpleVarName, points to first char of - * element name and elNameChars is length. - * Otherwise NULL. */ - int isAssignment; /* 1 if assigning value to var, else 0. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute cmd. */ - int localIndex = -1; /* Index of the variable in the current - * procedure's array of local variables. - * Otherwise -1 if not in a procedure, the - * name contains "::"s, or the variable - * wasn't found. */ - char savedChar; /* Holds the character from string - * termporarily replaced by a null char - * during name processing. */ - int objIndex = -1; /* The object array index for a pushed - * object holding a name part. Initialized - * to avoid a compiler warning. */ - char *wordStart, *p; - int numWords, isCompilableInt, i, result; - Tcl_Obj *objPtr; - int savePushSimpleWords = envPtr->pushSimpleWords; - - /* - * Scan the words of the command and record the start and finish of - * each argument word. - */ - - InitArgInfo(&argInfo); - result = CollectArgInfo(interp, string, lastChar, flags, &argInfo); - numWords = argInfo.numArgs; /* i.e., the # after the command name */ - if (result != TCL_OK) { - goto done; - } - if ((numWords < 1) || (numWords > 2)) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: should be \"set varName ?newValue?\"", -1); - result = TCL_ERROR; - goto done; - } - isAssignment = (numWords == 2); - - /* - * Parse the next word: the variable name. If the name is enclosed in - * quotes or braces, we return TCL_OUT_LINE_COMPILE and call the set - * command procedure at runtime since this makes sure that a second - * round of substitutions is done properly. - */ - - wordStart = argInfo.startArray[0]; /* start of 1st arg word: varname */ - if ((*wordStart == '{') || (*wordStart == '"')) { - result = TCL_OUT_LINE_COMPILE; - goto done; - } - - /* - * Check whether the name is "simple": requires no substitutions at - * runtime. - */ - - envPtr->pushSimpleWords = 0; - result = CompileWord(interp, wordStart, argInfo.endArray[0] + 1, - flags, envPtr); - if (result != TCL_OK) { - goto done; - } - simpleVarName = envPtr->wordIsSimple; - - if (!simpleVarName) { - /* - * The name isn't simple. CompileWord already pushed it. - */ - - maxDepth = envPtr->maxStackDepth; - } else { - char *name; /* If simpleVarName, points to first char of - * variable name and nameChars is length. - * Otherwise NULL. */ - int nameChars; /* Length of the var name. */ - int nameHasNsSeparators = 0; - /* Set 1 if name contains "::"s. */ - int elNameChars; /* Length of array's element name if any. */ - - /* - * A simple name. First divide it up into "name" plus "elName" - * for an array element name, if any. - */ - - name = wordStart; - nameChars = envPtr->numSimpleWordChars; - elName = NULL; - elNameChars = 0; - - p = name; - for (i = 0; i < nameChars; i++) { - if (*p == '(') { - char *openParen = p; - p = (name + nameChars-1); - if (*p == ')') { /* last char is ')' => array reference */ - nameChars = (openParen - name); - elName = openParen+1; - elNameChars = (p - elName); - } - break; - } - p++; - } - - /* - * Determine if name has any namespace separators (::'s). - */ - - p = name; - for (i = 0; i < nameChars; i++) { - if ((*p == ':') && ((i+1) < nameChars) && (*(p+1) == ':')) { - nameHasNsSeparators = 1; - break; - } - p++; - } - - /* - * Now either push the name or determine its index in the array of - * local variables in a procedure frame. Note that if we are - * compiling a procedure the variable must be local unless its - * name has namespace separators ("::"s). Note also that global - * variables are implemented by a local variable that "points" to - * the real global. There are two cases: - * 1) We are not compiling a procedure body. Push the global - * variable's name and do the lookup at runtime. - * 2) We are compiling a procedure and the name has "::"s. - * Push the namespace variable's name and do the lookup at - * runtime. - * 3) We are compiling a procedure and the name has no "::"s. - * If the variable has already been allocated an local index, - * just look it up. If the variable is unknown and we are - * doing an assignment, allocate a new index. Otherwise, - * push the name and try to do the lookup at runtime. - */ - - if ((procPtr == NULL) || nameHasNsSeparators) { - savedChar = name[nameChars]; - name[nameChars] = '\0'; - objIndex = TclObjIndexForString(name, nameChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - name[nameChars] = savedChar; - TclEmitPush(objIndex, envPtr); - maxDepth = 1; - } else { - localIndex = LookupCompiledLocal(name, nameChars, - /*createIfNew*/ isAssignment, - /*flagsIfCreated*/ - ((elName == NULL)? VAR_SCALAR : VAR_ARRAY), - envPtr->procPtr); - if (localIndex >= 0) { - maxDepth = 0; - } else { - savedChar = name[nameChars]; - name[nameChars] = '\0'; - objIndex = TclObjIndexForString(name, nameChars, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - name[nameChars] = savedChar; - TclEmitPush(objIndex, envPtr); - maxDepth = 1; - } - } - - /* - * If we are dealing with a reference to an array element, push the - * array element. Perform substitutions on it, just as is done - * for quoted strings. - */ - - if (elName != NULL) { - savedChar = elName[elNameChars]; - elName[elNameChars] = '\0'; - envPtr->pushSimpleWords = 1; - result = TclCompileQuotes(interp, elName, elName+elNameChars, - 0, flags, envPtr); - elName[elNameChars] = savedChar; - if (result != TCL_OK) { - char msg[200]; - sprintf(msg, "\n (parsing index for array \"%.*s\")", - TclMin(nameChars, 100), name); - Tcl_AddObjErrorInfo(interp, msg, -1); - goto done; - } - maxDepth += envPtr->maxStackDepth; - } - } - - /* - * If we are doing an assignment, push the new value. - */ - - if (isAssignment) { - wordStart = argInfo.startArray[1]; /* start of 2nd arg word */ - envPtr->pushSimpleWords = 0; /* we will handle simple words */ - result = CompileWord(interp, wordStart, argInfo.endArray[1] + 1, - flags, envPtr); - if (result != TCL_OK) { - goto done; - } - if (!envPtr->wordIsSimple) { - /* - * The value isn't simple. CompileWord already pushed it. - */ - - maxDepth += envPtr->maxStackDepth; - } else { - /* - * The value is simple. See if the word represents an integer - * whose formatted representation is the same as the word (e.g., - * this is true for 123 and -1 but not for 00005). If so, just - * push an integer object. - */ - - char buf[40]; - long n; - - p = wordStart; - if ((*wordStart == '"') || (*wordStart == '{')) { - p++; - } - savedChar = p[envPtr->numSimpleWordChars]; - p[envPtr->numSimpleWordChars] = '\0'; - isCompilableInt = 0; - if (TclLooksLikeInt(p)) { - int code = TclGetLong(interp, p, &n); - if (code == TCL_OK) { - TclFormatInt(buf, n); - if (strcmp(p, buf) == 0) { - isCompilableInt = 1; - objIndex = TclObjIndexForString(p, - envPtr->numSimpleWordChars, - /*allocStrRep*/ 0, /*inHeap*/ 0, envPtr); - objPtr = envPtr->objArrayPtr[objIndex]; - - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.longValue = n; - objPtr->typePtr = &tclIntType; - } - } else { - Tcl_ResetResult(interp); - } - } - if (!isCompilableInt) { - objIndex = TclObjIndexForString(p, - envPtr->numSimpleWordChars, /*allocStrRep*/ 1, - /*inHeap*/ 0, envPtr); - } - p[envPtr->numSimpleWordChars] = savedChar; - TclEmitPush(objIndex, envPtr); - maxDepth += 1; - } - } - - /* - * Now emit instructions to set/retrieve the variable. - */ - - if (simpleVarName) { - if (elName == NULL) { /* scalar */ - if (localIndex >= 0) { - if (localIndex <= 255) { - TclEmitInstUInt1((isAssignment? - INST_STORE_SCALAR1 : INST_LOAD_SCALAR1), - localIndex, envPtr); - } else { - TclEmitInstUInt4((isAssignment? - INST_STORE_SCALAR4 : INST_LOAD_SCALAR4), - localIndex, envPtr); - } - } else { - TclEmitOpcode((isAssignment? - INST_STORE_SCALAR_STK : INST_LOAD_SCALAR_STK), - envPtr); - } - } else { /* array */ - if (localIndex >= 0) { - if (localIndex <= 255) { - TclEmitInstUInt1((isAssignment? - INST_STORE_ARRAY1 : INST_LOAD_ARRAY1), - localIndex, envPtr); - } else { - TclEmitInstUInt4((isAssignment? - INST_STORE_ARRAY4 : INST_LOAD_ARRAY4), - localIndex, envPtr); - } - } else { - TclEmitOpcode((isAssignment? - INST_STORE_ARRAY_STK : INST_LOAD_ARRAY_STK), - envPtr); - } - } - } else { /* non-simple variable name */ - TclEmitOpcode((isAssignment? INST_STORE_STK : INST_LOAD_STK), envPtr); - } - - done: - if (numWords == 0) { - envPtr->termOffset = 0; - } else { - envPtr->termOffset = (argInfo.endArray[numWords-1] + 1 - string); - } - envPtr->pushSimpleWords = savePushSimpleWords; - envPtr->maxStackDepth = maxDepth; - FreeArgInfo(&argInfo); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclCompileWhileCmd -- - * - * Procedure called to compile the "while" command. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK if - * compilation was successful. If an error occurs then the - * interpreter's result contains a standard error message and TCL_ERROR - * is returned. If compilation failed because the command is too - * complex for TclCompileWhileCmd, TCL_OUT_LINE_COMPILE is returned - * indicating that the while command should be compiled "out of line" - * by emitting code to invoke its command procedure at runtime. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the "while" command. - * - * Side effects: - * Instructions are added to envPtr to evaluate the "while" command - * at runtime. - * - *---------------------------------------------------------------------- - */ - -int -TclCompileWhileCmd(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - register char *src = string;/* Points to current source char. */ - register int type; /* Current char's CHAR_TYPE type. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute cmd. */ - int range; /* Index in the ExceptionRange array of the - * ExceptionRange record for this loop. */ - JumpFixup jumpFalseFixup; /* Used to update or replace the ifFalse - * jump after test when its target PC is - * determined. */ - unsigned char *jumpPc; - int jumpDist, jumpBackDist, jumpBackOffset, objIndex, result; - int savePushSimpleWords = envPtr->pushSimpleWords; - - envPtr->excRangeDepth++; - envPtr->maxExcRangeDepth = - TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth); - - /* - * Create and initialize a ExceptionRange record to hold information - * about this loop. This is used to implement break and continue. - */ - - range = CreateExceptionRange(LOOP_EXCEPTION_RANGE, envPtr); - envPtr->excRangeArrayPtr[range].continueOffset = TclCurrCodeOffset(); - - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type == TCL_COMMAND_END) { - badArgs: - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "wrong # args: should be \"while test command\"", -1); - result = TCL_ERROR; - goto done; - } - - /* - * If the test expression is enclosed in quotes (""s), don't compile - * the while inline. As a result of Tcl's two level substitution - * semantics for expressions, the expression might have a constant - * value that results in the loop never executing, or executing forever. - * Consider "set x 0; while "$x < 5" {incr x}": the loop body should - * never be executed. - */ - - if (*src == '"') { - result = TCL_OUT_LINE_COMPILE; - goto done; - } - - /* - * Compile the next word: the test expression. - */ - - envPtr->pushSimpleWords = 1; - result = CompileExprWord(interp, src, lastChar, flags, envPtr); - if (result != TCL_OK) { - if (result == TCL_ERROR) { - Tcl_AddObjErrorInfo(interp, "\n (\"while\" test expression)", -1); - } - goto done; - } - maxDepth = envPtr->maxStackDepth; - src += envPtr->termOffset; - - /* - * Emit the ifFalse jump that terminates the while if the test was - * false. We emit a one byte (relative) jump here, and replace it - * later with a four byte jump if the jump target is more than - * 127 bytes away. - */ - - TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup); - - /* - * Compile the loop body word inline. Also register the loop body's - * starting PC offset and byte length in the its ExceptionRange record. - */ - - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type == TCL_COMMAND_END) { - goto badArgs; - } - - envPtr->excRangeArrayPtr[range].codeOffset = TclCurrCodeOffset(); - result = CompileCmdWordInline(interp, src, lastChar, - flags, envPtr); - if (result != TCL_OK) { - if (result == TCL_ERROR) { - char msg[60]; - sprintf(msg, "\n (\"while\" body line %d)", interp->errorLine); - Tcl_AddObjErrorInfo(interp, msg, -1); - } - goto done; - } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); - src += envPtr->termOffset; - envPtr->excRangeArrayPtr[range].numCodeBytes = - (TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range].codeOffset); - - /* - * Discard the loop body's result. - */ - - TclEmitOpcode(INST_POP, envPtr); - - /* - * Emit the unconditional jump back to the test at the top of the - * loop. We generate a four byte jump if the distance to the while's - * test is greater than 120 bytes. This is conservative, and ensures - * that we won't have to replace this unconditional jump if we later - * need to replace the ifFalse jump with a four-byte jump. - */ - - jumpBackOffset = TclCurrCodeOffset(); - jumpBackDist = - (jumpBackOffset - envPtr->excRangeArrayPtr[range].continueOffset); - if (jumpBackDist > 120) { - TclEmitInstInt4(INST_JUMP4, /*offset*/ -jumpBackDist, envPtr); - } else { - TclEmitInstInt1(INST_JUMP1, /*offset*/ -jumpBackDist, envPtr); - } - - /* - * Now that we know the target of the jumpFalse after the test, update - * it with the correct distance. If the distance is too great (more - * than 127 bytes), replace that jump with a four byte instruction and - * move the instructions after the jump down. - */ - - jumpDist = (TclCurrCodeOffset() - jumpFalseFixup.codeOffset); - if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) { - /* - * Update the loop body's starting PC offset since it moved down. - */ - - envPtr->excRangeArrayPtr[range].codeOffset += 3; - - /* - * Update the distance for the unconditional jump back to the test - * at the top of the loop since it moved down 3 bytes too. - */ - - jumpBackOffset += 3; - jumpPc = (envPtr->codeStart + jumpBackOffset); - if (jumpBackDist > 120) { - jumpBackDist += 3; - TclUpdateInstInt4AtPc(INST_JUMP4, /*offset*/ -jumpBackDist, - jumpPc); - } else { - jumpBackDist += 3; - TclUpdateInstInt1AtPc(INST_JUMP1, /*offset*/ -jumpBackDist, - jumpPc); - } - } - - /* - * The current PC offset (after the loop's body) is the loop's - * break target. - */ - - envPtr->excRangeArrayPtr[range].breakOffset = TclCurrCodeOffset(); - - /* - * Push an empty string object as the while command's result. - */ - - objIndex = TclObjIndexForString("", 0, /*allocStrRep*/ 0, /*inHeap*/ 0, - envPtr); - TclEmitPush(objIndex, envPtr); - if (maxDepth == 0) { - maxDepth = 1; - } - - /* - * Skip over white space until the end of the command. - */ - - type = CHAR_TYPE(src, lastChar); - if (type != TCL_COMMAND_END) { - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type != TCL_COMMAND_END) { - goto badArgs; - } - } - - done: - envPtr->termOffset = (src - string); - envPtr->pushSimpleWords = savePushSimpleWords; - envPtr->maxStackDepth = maxDepth; - envPtr->excRangeDepth--; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileExprWord -- - * - * Procedure that compiles a Tcl expression in a command word. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK unless - * there was an error while compiling string. If an error occurs then - * the interpreter's result contains a standard error message. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the "expr" word. - * - * Side effects: - * Instructions are added to envPtr to evaluate the expression word - * at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileExprWord(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - register char *src = string;/* Points to current source char. */ - register int type; /* Current char's CHAR_TYPE type. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute the expression. */ - int nestedCmd = (flags & TCL_BRACKET_TERM); - /* 1 if script being compiled is a nested - * command and is terminated by a ']'; - * otherwise 0. */ - char *first, *last; /* Points to the first and last significant - * characters of the word. */ - char savedChar; /* Holds the character termporarily replaced - * by a null character during compilation - * of the expression. */ - int inlineCode; /* 1 if inline "optimistic" code is - * emitted for the expression; else 0. */ - int range = -1; /* If we inline compile an un-{}'d - * expression, the index for its catch range - * record in the ExceptionRange array. - * Initialized to avoid compile warning. */ - JumpFixup jumpFixup; /* Used to emit the "success" jump after - * the inline expression code. */ - char *p; - char c; - int savePushSimpleWords = envPtr->pushSimpleWords; - int saveExprIsJustVarRef = envPtr->exprIsJustVarRef; - int saveExprIsComparison = envPtr->exprIsComparison; - int numChars, result; - - /* - * Skip over leading white space. - */ - - AdvanceToNextWord(src, envPtr); - src += envPtr->termOffset; - type = CHAR_TYPE(src, lastChar); - if (type == TCL_COMMAND_END) { - badArgs: - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "malformed expression word", -1); - result = TCL_ERROR; - goto done; - } - - /* - * If the word is enclosed in {}s, we may strip them off and safely - * compile the expression into an inline sequence of instructions using - * TclCompileExpr. We know these instructions will have the right Tcl7.x - * expression semantics. - * - * Otherwise, if the word is not enclosed in {}s, we may need to call - * the expr command (Tcl_ExprObjCmd) at runtime. This recompiles the - * expression each time (typically) and so is slow. However, there are - * some circumstances where we can still compile inline instructions - * "optimistically" and check, during their execution, for double - * substitutions (these appear as nonnumeric operands). We check for any - * backslash or command substitutions. If none appear, and only variable - * substitutions are found, we generate inline instructions. - * - * For now, if the expression is not enclosed in {}s, we call the expr - * command at runtime if either command or backslash substitutions - * appear (but not if only variable substitutions appear). - */ - - if (*src == '{') { - /* - * Inline compile the expression inside {}s. - */ - - first = src+1; - src = TclWordEnd(src, lastChar, nestedCmd, NULL); - if (*src == 0) { - goto badArgs; - } - if (*src != '}') { - goto badArgs; - } - last = (src-1); - - numChars = (last - first + 1); - savedChar = first[numChars]; - first[numChars] = '\0'; - result = TclCompileExpr(interp, first, first+numChars, - flags, envPtr); - first[numChars] = savedChar; - - src++; - maxDepth = envPtr->maxStackDepth; - } else { - /* - * No braces. If the expression is enclosed in '"'s, call the expr - * cmd at runtime. Otherwise, scan the word's characters looking for - * any '['s or (for now) '\'s. If any are found, just call expr cmd - * at runtime. - */ - - first = src; - last = TclWordEnd(first, lastChar, nestedCmd, NULL); - if (*last == 0) { /* word doesn't end properly. */ - src = last; - goto badArgs; - } - - inlineCode = 1; - if ((*first == '"') && (*last == '"')) { - inlineCode = 0; - } else { - for (p = first; p <= last; p++) { - c = *p; - if ((c == '[') || (c == '\\')) { - inlineCode = 0; - break; - } - } - } - - if (inlineCode) { - /* - * Inline compile the expression inside a "catch" so that a - * runtime error will back off to make a (slow) call on expr. - */ - - int startCodeOffset = (envPtr->codeNext - envPtr->codeStart); - int startRangeNext = envPtr->excRangeArrayNext; - - /* - * Create a ExceptionRange record to hold information about - * the "catch" range for the expression's inline code. Also - * emit the instruction to mark the start of the range. - */ - - envPtr->excRangeDepth++; - envPtr->maxExcRangeDepth = - TclMax(envPtr->excRangeDepth, envPtr->maxExcRangeDepth); - range = CreateExceptionRange(CATCH_EXCEPTION_RANGE, envPtr); - TclEmitInstUInt4(INST_BEGIN_CATCH4, range, envPtr); - - /* - * Inline compile the expression. - */ - - envPtr->excRangeArrayPtr[range].codeOffset = TclCurrCodeOffset(); - numChars = (last - first + 1); - savedChar = first[numChars]; - first[numChars] = '\0'; - result = TclCompileExpr(interp, first, first + numChars, - flags, envPtr); - first[numChars] = savedChar; - - envPtr->excRangeArrayPtr[range].numCodeBytes = - TclCurrCodeOffset() - envPtr->excRangeArrayPtr[range].codeOffset; - - if ((result != TCL_OK) || (envPtr->exprIsJustVarRef) - || (envPtr->exprIsComparison)) { - /* - * We must call the expr command at runtime. Either there - * was a compilation error or the inline code might fail to - * give the correct 2 level substitution semantics. - * - * The latter can happen if the expression consisted of just - * a single variable reference or if the top-level operator - * in the expr is a comparison (which might operate on - * strings). In the latter case, the expression's code might - * execute (apparently) successfully but produce the wrong - * result. We depend on its execution failing if a second - * level of substitutions is required. This causes the - * "catch" code we generate around the inline code to back - * off to a call on the expr command at runtime, and this - * always gives the right 2 level substitution semantics. - * - * We delete the inline code by backing up the code pc and - * catch index. Note that if there was a compilation error, - * we can't report the error yet since the expression might - * be valid after the second round of substitutions. - */ - - envPtr->codeNext = (envPtr->codeStart + startCodeOffset); - envPtr->excRangeArrayNext = startRangeNext; - inlineCode = 0; - } else { - TclEmitOpcode(INST_END_CATCH, envPtr); - TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); - envPtr->excRangeArrayPtr[range].catchOffset = TclCurrCodeOffset(); - } - } - - /* - * Arrange to call expr at runtime with the (already substituted - * once) expression word on the stack. - */ - - envPtr->pushSimpleWords = 1; - result = CompileWord(interp, first, lastChar, flags, envPtr); - src += envPtr->termOffset; - maxDepth = envPtr->maxStackDepth; - if (result == TCL_OK) { - TclEmitOpcode(INST_EXPR_STK, envPtr); - } - - /* - * If emitting inline code for this non-{}'d expression, update - * the target of the jump after that inline code. - */ - - if (inlineCode) { - int jumpDist = (TclCurrCodeOffset() - jumpFixup.codeOffset); - if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) { - /* - * Update the inline expression code's catch ExceptionRange - * target since it, being after the jump, also moved down. - */ - - envPtr->excRangeArrayPtr[range].catchOffset += 3; - } - } - } /* if expression isn't in {}s */ - - done: - envPtr->termOffset = (src - string); - envPtr->maxStackDepth = maxDepth; - envPtr->pushSimpleWords = savePushSimpleWords; - envPtr->exprIsJustVarRef = saveExprIsJustVarRef; - envPtr->exprIsComparison = saveExprIsComparison; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CompileCmdWordInline -- - * - * Procedure that compiles a Tcl command word inline. If the word is - * enclosed in quotes or braces, we call TclCompileString to compile it - * after stripping them off. Otherwise, we normally push the word's - * value and call eval at runtime, but if the word is just a sequence - * of alphanumeric characters, we emit an invoke instruction - * directly. This procedure assumes that string points to the start of - * the word to compile. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK unless - * there was an error while compiling string. If an error occurs then - * the interpreter's result contains a standard error message. - * - * envPtr->termOffset is filled in with the offset of the character in - * "string" just after the last one successfully processed. - * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * - * Side effects: - * Instructions are added to envPtr to execute the command word - * at runtime. - * - *---------------------------------------------------------------------- - */ - -static int -CompileCmdWordInline(interp, string, lastChar, flags, envPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source string to compile. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ +LogCompilationInfo(interp, script, command, length) + Tcl_Interp *interp; /* Interpreter in which to log the + * information. */ + char *script; /* First character in script containing + * command (must be <= command). */ + 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). */ +{ + char buffer[200]; + register char *p; + char *ellipsis = ""; Interp *iPtr = (Interp *) interp; - register char *src = string;/* Points to current source char. */ - register int type; /* Current char's CHAR_TYPE type. */ - int maxDepth = 0; /* Maximum number of stack elements needed - * to execute cmd. */ - char *termPtr; /* Points to char that terminated braced - * string. */ - char savedChar; /* Holds the character termporarily replaced - * by a null character during compilation - * of the command. */ - int savePushSimpleWords = envPtr->pushSimpleWords; - int objIndex; - int result = TCL_OK; - register char c; - - type = CHAR_TYPE(src, lastChar); - if (type & (TCL_QUOTE | TCL_OPEN_BRACE)) { - src++; - envPtr->pushSimpleWords = 0; - if (type == TCL_QUOTE) { - result = TclCompileQuotes(interp, src, lastChar, - '"', flags, envPtr); - } else { - result = CompileBraces(interp, src, lastChar, flags, envPtr); - } - if (result != TCL_OK) { - goto done; - } - - /* - * Make sure the terminating character is the end of word. - */ - - termPtr = (src + envPtr->termOffset); - c = *termPtr; - if ((c == '\\') && (*(termPtr+1) == '\n')) { - /* - * Line is continued on next line; the backslash-newline turns - * into space, which terminates the word. - */ - } else { - type = CHAR_TYPE(termPtr, lastChar); - if ((type != TCL_SPACE) && (type != TCL_COMMAND_END)) { - Tcl_ResetResult(interp); - if (*(src-1) == '"') { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "extra characters after close-quote", -1); - } else { - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "extra characters after close-brace", -1); - } - result = TCL_ERROR; - goto done; - } - } - - if (envPtr->wordIsSimple) { - /* - * A simple word enclosed in "" or {}s. Call TclCompileString to - * compile it inline. Add a null character after the end of the - * quoted or braced string: i.e., at the " or }. Turn the - * flag bit TCL_BRACKET_TERM off since the recursively - * compiled subcommand is now terminated by a null character. - */ - char *closeCharPos = (termPtr - 1); - - savedChar = *closeCharPos; - *closeCharPos = '\0'; - result = TclCompileString(interp, src, closeCharPos, - (flags & ~TCL_BRACKET_TERM), envPtr); - *closeCharPos = savedChar; - if (result != TCL_OK) { - goto done; - } - } else { - /* - * The braced string contained a backslash-newline. Call eval - * at runtime. - */ - TclEmitOpcode(INST_EVAL_STK, envPtr); - } - src = termPtr; - maxDepth = envPtr->maxStackDepth; - } else { - /* - * Not a braced or quoted string. We normally push the word's - * value and call eval at runtime. However, if the word is just - * a sequence of alphanumeric characters, we call its compile - * procedure, if any, or otherwise just emit an invoke instruction. - */ - - char *p = src; - c = *p; - while (isalnum(UCHAR(c)) || (c == '_')) { - p++; - c = *p; - } - type = CHAR_TYPE(p, lastChar); - if ((p > src) && (type == TCL_COMMAND_END)) { - /* - * Look for a compile procedure and call it. Otherwise emit an - * invoke instruction to call the command at runtime. - */ - - Tcl_Command cmd; - Command *cmdPtr = NULL; - int wasCompiled = 0; - - savedChar = *p; - *p = '\0'; - - cmd = Tcl_FindCommand(interp, src, (Tcl_Namespace *) NULL, - /*flags*/ 0); - if (cmd != (Tcl_Command) NULL) { - cmdPtr = (Command *) cmd; - } - if (cmdPtr != NULL && cmdPtr->compileProc != NULL) { - *p = savedChar; - src = p; - iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS - | ERROR_CODE_SET); - result = (*(cmdPtr->compileProc))(interp, src, lastChar, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - wasCompiled = 1; - src += envPtr->termOffset; - maxDepth = envPtr->maxStackDepth; - } - if (!wasCompiled) { - objIndex = TclObjIndexForString(src, p-src, - /*allocStrRep*/ 1, /*inHeap*/ 0, envPtr); - *p = savedChar; - TclEmitPush(objIndex, envPtr); - TclEmitInstUInt1(INST_INVOKE_STK1, 1, envPtr); - src = p; - maxDepth = 1; - } - } else { - /* - * Push the word and call eval at runtime. - */ - - envPtr->pushSimpleWords = 1; - result = CompileWord(interp, src, lastChar, flags, envPtr); - if (result != TCL_OK) { - goto done; - } - TclEmitOpcode(INST_EVAL_STK, envPtr); - src += envPtr->termOffset; - maxDepth = envPtr->maxStackDepth; - } - } - - done: - envPtr->termOffset = (src - string); - envPtr->maxStackDepth = maxDepth; - envPtr->pushSimpleWords = savePushSimpleWords; - return result; -} - -/* - *---------------------------------------------------------------------- - * - * LookupCompiledLocal -- + + if (iPtr->flags & ERR_ALREADY_LOGGED) { + /* + * Someone else has already logged error information for this + * command; we shouldn't add anything more. + */ + + return; + } + + /* + * Compute the line number where the error occurred. + */ + + iPtr->errorLine = 1; + for (p = script; p != command; p++) { + if (*p == '\n') { + iPtr->errorLine++; + } + } + + /* + * Create an error message to add to errorInfo, including up to a + * maximum number of characters of the command. + */ + + if (length < 0) { + length = strlen(command); + } + if (length > 150) { + length = 150; + ellipsis = "..."; + } + sprintf(buffer, "\n while compiling\n\"%.*s%s\"", + length, command, ellipsis); + Tcl_AddObjErrorInfo(interp, buffer, -1); +} + +/* + *---------------------------------------------------------------------- + * + * 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 createIfNew is 0 (false) 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 createIfNew is 1 and name is non-NULL, the index of a - * new entry is returned. + * 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 createIfNew is 1 and + * Creates and registers a new local variable if create is 1 and * the variable is unknown, or if the name is NULL. * *---------------------------------------------------------------------- */ -static int -LookupCompiledLocal(name, nameChars, createIfNew, flagsIfCreated, procPtr) +int +TclFindCompiledLocal(name, nameBytes, create, flags, procPtr) register char *name; /* Points to first character of the name of * a scalar or array variable. If NULL, a * temporary var should be created. */ - int nameChars; /* The length of the name excluding the - * terminating null character. */ - int createIfNew; /* 1 to allocate a local frame entry for the - * variable if it is new. */ - int flagsIfCreated; /* Flag bits for the compiled local if + int nameBytes; /* Number of bytes in the name. */ + int create; /* If 1, allocate a local frame entry for + * the variable if it is new. */ + int flags; /* Flag bits for the compiled local if * created. Only VAR_SCALAR, VAR_ARRAY, and * VAR_LINK make sense. */ register Proc *procPtr; /* Points to structure describing procedure * containing the variable reference. */ { register CompiledLocal *localPtr; - int localIndex = -1; + int localVar = -1; register int i; /* * If not creating a temporary, does a local variable of the specified * name already exist? @@ -6556,15 +1767,15 @@ if (name != NULL) { int localCt = procPtr->numCompiledLocals; localPtr = procPtr->firstLocalPtr; for (i = 0; i < localCt; i++) { - if (!localPtr->isTemp) { + if (!TclIsVarTemporary(localPtr)) { char *localName = localPtr->name; if ((name[0] == localName[0]) - && (nameChars == localPtr->nameLength) - && (strncmp(name, localName, (unsigned) nameChars) == 0)) { + && (nameBytes == localPtr->nameLength) + && (strncmp(name, localName, (unsigned) nameBytes) == 0)) { return i; } } localPtr = localPtr->nextPtr; } @@ -6572,306 +1783,152 @@ /* * Create a new variable if appropriate. */ - if (createIfNew || (name == NULL)) { - localIndex = procPtr->numCompiledLocals; + if (create || (name == NULL)) { + localVar = procPtr->numCompiledLocals; localPtr = (CompiledLocal *) ckalloc((unsigned) (sizeof(CompiledLocal) - sizeof(localPtr->name) - + nameChars+1)); + + nameBytes+1)); if (procPtr->firstLocalPtr == NULL) { procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr; } else { procPtr->lastLocalPtr->nextPtr = localPtr; procPtr->lastLocalPtr = localPtr; } localPtr->nextPtr = NULL; - localPtr->nameLength = nameChars; - localPtr->frameIndex = localIndex; - localPtr->isArg = 0; - localPtr->isTemp = (name == NULL); - localPtr->flags = flagsIfCreated; + localPtr->nameLength = nameBytes; + localPtr->frameIndex = localVar; + localPtr->flags = flags; + if (name == NULL) { + localPtr->flags |= VAR_TEMPORARY; + } localPtr->defValuePtr = NULL; + localPtr->resolveInfo = NULL; + if (name != NULL) { - memcpy((VOID *) localPtr->name, (VOID *) name, (size_t) nameChars); + memcpy((VOID *) localPtr->name, (VOID *) name, + (size_t) nameBytes); } - localPtr->name[nameChars] = '\0'; + localPtr->name[nameBytes] = '\0'; procPtr->numCompiledLocals++; } - return localIndex; -} - -/* - *---------------------------------------------------------------------- - * - * AdvanceToNextWord -- - * - * This procedure is called to skip over any leading white space at the - * start of a word. Note that a backslash-newline is treated as a - * space. - * - * Results: - * None. - * - * Side effects: - * Updates envPtr->termOffset with the offset of the first - * character in "string" that was not white space or a - * backslash-newline. This might be the offset of the character that - * ends the command: a newline, null, semicolon, or close-bracket. - * - *---------------------------------------------------------------------- - */ - -static void -AdvanceToNextWord(string, envPtr) - char *string; /* The source string to compile. */ - CompileEnv *envPtr; /* Holds resulting instructions. */ -{ - register char *src; /* Points to current source char. */ - register int type; /* Current char's CHAR_TYPE type. */ - - src = string; - type = CHAR_TYPE(src, src+1); - while (type & (TCL_SPACE | TCL_BACKSLASH)) { - if (type == TCL_BACKSLASH) { - if (src[1] == '\n') { - src += 2; - } else { - break; /* exit loop; no longer white space */ - } - } else { - src++; - } - type = CHAR_TYPE(src, src+1); - } - envPtr->termOffset = (src - string); -} - -/* - *---------------------------------------------------------------------- - * - * 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(src, readPtr) - 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. */ -{ - CONST char *p = src + 1; - char result; - int count; - - 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': - if (isxdigit(UCHAR(p[1]))) { - char *end; - - result = (char) strtoul(p+1, &end, 16); - count = end - src; - } else { - count = 2; - result = 'x'; - } - break; - case '\n': - do { - p++; - } while ((*p == ' ') || (*p == '\t')); - result = ' '; - count = p - src; - break; - case 0: - result = '\\'; - count = 1; - break; - default: - if (isdigit(UCHAR(*p))) { - result = (char)(*p - '0'); - p++; - if (!isdigit(UCHAR(*p))) { - break; - } - count = 3; - result = (char)((result << 3) + (*p - '0')); - p++; - if (!isdigit(UCHAR(*p))) { - break; - } - count = 4; - result = (char)((result << 3) + (*p - '0')); - break; - } - result = *p; - count = 2; - break; - } - - if (readPtr != NULL) { - *readPtr = count; - } - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclObjIndexForString -- - * - * Procedure to find, or if necessary create, an object in a - * CompileEnv's object array that has a string representation - * matching the argument string. - * - * Results: - * The index in the CompileEnv's object array of an object with a - * string representation matching the argument "string". The object is - * created if necessary. If inHeap is 1, then string is heap allocated - * and ownership of the string is passed to TclObjIndexForString; - * otherwise, the string is owned by the caller and must not be - * modified or freed by TclObjIndexForString. Typically, a caller sets - * inHeap 1 if string is an already heap-allocated buffer holding the - * result of backslash substitutions. - * - * Side effects: - * A new Tcl object will be created if no existing object matches the - * input string. If allocStrRep is 1 then if a new object is created, - * its string representation is allocated in the heap, else it is left - * NULL. If inHeap is 1, this procedure is given ownership of the - * string: if an object is created and allocStrRep is 1 then its - * string representation is set directly from string, otherwise - * the string is freed. - * - *---------------------------------------------------------------------- - */ - -int -TclObjIndexForString(string, length, allocStrRep, inHeap, envPtr) - register char *string; /* Points to string for which an object is - * found or created in CompileEnv's object - * array. */ - int length; /* Length of string. */ - int allocStrRep; /* If 1 then the object's string rep should - * be allocated in the heap. */ - int inHeap; /* If 1 then string is heap allocated and - * its ownership is passed to - * TclObjIndexForString. */ - CompileEnv *envPtr; /* Points to the CompileEnv in whose object - * array an object is found or created. */ -{ - register Tcl_Obj *objPtr; /* Points to the object created for - * the string, if one was created. */ - int objIndex; /* Index of matching object. */ - Tcl_HashEntry *hPtr; - int strLength, new; - - /* - * Look up the string in the code's object hashtable. If found, just - * return the associated object array index. Note that if the string - * has embedded nulls, we don't create a hash table entry. This - * should be fixed, but we need to update hash tables, first. - */ - - strLength = strlen(string); - if (length == -1) { - length = strLength; - } - if (strLength != length) { - hPtr = NULL; - } else { - hPtr = Tcl_CreateHashEntry(&envPtr->objTable, string, &new); - if (!new) { /* already in object table and array */ - objIndex = (int) Tcl_GetHashValue(hPtr); - if (inHeap) { - ckfree(string); - } - return objIndex; - } - } - - /* - * Create a new object holding the string, add it to the object array, - * and register its index in the object hashtable. - */ - - objPtr = Tcl_NewObj(); - if (allocStrRep) { - if (inHeap) { /* use input string for obj's string rep */ - objPtr->bytes = string; - } else { - if (length > 0) { - objPtr->bytes = ckalloc((unsigned) length + 1); - memcpy((VOID *) objPtr->bytes, (VOID *) string, - (size_t) length); - objPtr->bytes[length] = '\0'; - } - } - objPtr->length = length; - } else { /* leave the string rep NULL */ - if (inHeap) { - ckfree(string); - } - } - - if (envPtr->objArrayNext >= envPtr->objArrayEnd) { - ExpandObjectArray(envPtr); - } - objIndex = envPtr->objArrayNext; - envPtr->objArrayPtr[objIndex] = objPtr; - Tcl_IncrRefCount(objPtr); - envPtr->objArrayNext++; - - if (hPtr) { - Tcl_SetHashValue(hPtr, objIndex); - } - return objIndex; + return localVar; +} + +/* + *---------------------------------------------------------------------- + * + * TclInitCompiledLocals -- + * + * 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. + * + *---------------------------------------------------------------------- + */ + +void +TclInitCompiledLocals(interp, framePtr, nsPtr) + Tcl_Interp *interp; /* Current interpreter. */ + CallFrame *framePtr; /* Call frame to initialize. */ + Namespace *nsPtr; /* Pointer to current namespace. */ +{ + register CompiledLocal *localPtr; + Interp *iPtr = (Interp*) interp; + Tcl_ResolvedVarInfo *vinfo, *resVarInfo; + Var *varPtr = framePtr->compiledLocals; + Var *resolvedVarPtr; + ResolverScheme *resPtr; + int result; + + /* + * 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. + */ + + for (localPtr = framePtr->procPtr->firstLocalPtr; + localPtr != NULL; + localPtr = localPtr->nextPtr) { + + /* + * Check to see if this local is affected by namespace or + * interp resolvers. The resolver to use is cached for the + * next invocation of the procedure. + */ + + if (!(localPtr->flags & (VAR_ARGUMENT|VAR_TEMPORARY|VAR_RESOLVED)) + && (nsPtr->compiledVarResProc || iPtr->resolverPtr)) { + resPtr = iPtr->resolverPtr; + + 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; + } + } + + /* + * Now invoke the resolvers to determine the exact variables that + * should be used. + */ + + resVarInfo = localPtr->resolveInfo; + resolvedVarPtr = NULL; + + if (resVarInfo && resVarInfo->fetchProc) { + resolvedVarPtr = (Var*) (*resVarInfo->fetchProc)(interp, + resVarInfo); + } + + if (resolvedVarPtr) { + varPtr->name = localPtr->name; /* will be just '\0' if temp var */ + varPtr->nsPtr = NULL; + varPtr->hPtr = NULL; + varPtr->refCount = 0; + varPtr->tracePtr = NULL; + varPtr->searchPtr = NULL; + varPtr->flags = 0; + TclSetVarLink(varPtr); + varPtr->value.linkPtr = resolvedVarPtr; + resolvedVarPtr->refCount++; + } else { + varPtr->value.objPtr = NULL; + varPtr->name = localPtr->name; /* will be just '\0' if temp var */ + varPtr->nsPtr = NULL; + varPtr->hPtr = NULL; + varPtr->refCount = 0; + varPtr->tracePtr = NULL; + varPtr->searchPtr = NULL; + varPtr->flags = (localPtr->flags | VAR_UNDEFINED); + } + varPtr++; + } } /* *---------------------------------------------------------------------- * @@ -6901,11 +1958,11 @@ * 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 = TclCurrCodeOffset(); + size_t currBytes = (envPtr->codeNext - envPtr->codeStart); size_t newBytes = 2*(envPtr->codeEnd - envPtr->codeStart); unsigned char *newPtr = (unsigned char *) ckalloc((unsigned) newBytes); /* * Copy from old code array to new, free old code array if needed, and @@ -6919,61 +1976,10 @@ envPtr->codeStart = newPtr; envPtr->codeNext = (newPtr + currBytes); envPtr->codeEnd = (newPtr + newBytes); envPtr->mallocedCodeArray = 1; } - -/* - *---------------------------------------------------------------------- - * - * ExpandObjectArray -- - * - * Procedure that uses malloc to allocate more storage for a - * CompileEnv's object array. - * - * Results: - * None. - * - * Side effects: - * The object array in *envPtr is reallocated to a new array of - * double the size, and if envPtr->mallocedObjArray is non-zero the - * old array is freed. Tcl_Obj pointers are copied from the old array - * to the new one. - * - *---------------------------------------------------------------------- - */ - -static void -ExpandObjectArray(envPtr) - CompileEnv *envPtr; /* Points to the CompileEnv whose object - * array must be enlarged. */ -{ - /* - * envPtr->objArrayNext is equal to envPtr->objArrayEnd. The currently - * allocated Tcl_Obj pointers are stored between elements - * 0 and (envPtr->objArrayNext - 1) [inclusive] in the object array - * pointed to by objArrayPtr. - */ - - size_t currBytes = envPtr->objArrayNext * sizeof(Tcl_Obj *); - int newElems = 2*envPtr->objArrayEnd; - size_t newBytes = newElems * sizeof(Tcl_Obj *); - Tcl_Obj **newPtr = (Tcl_Obj **) ckalloc((unsigned) newBytes); - - /* - * Copy from old object array to new, free old object array if needed, - * and mark new object array as malloced. - */ - - memcpy((VOID *) newPtr, (VOID *) envPtr->objArrayPtr, currBytes); - if (envPtr->mallocedObjArray) { - ckfree((char *) envPtr->objArrayPtr); - } - envPtr->objArrayPtr = (Tcl_Obj **) newPtr; - envPtr->objArrayEnd = newElems; - envPtr->mallocedObjArray = 1; -} /* *---------------------------------------------------------------------- * * EnterCmdStartData -- @@ -7036,18 +2042,18 @@ envPtr->mallocedCmdMap = 1; } if (cmdIndex > 0) { if (codeOffset < envPtr->cmdMapPtr[cmdIndex-1].codeOffset) { - panic("EnterCmdStartData: cmd map table not sorted by code offset"); + panic("EnterCmdStartData: cmd map not sorted by code offset"); } } cmdLocPtr = &(envPtr->cmdMapPtr[cmdIndex]); cmdLocPtr->codeOffset = codeOffset; cmdLocPtr->srcOffset = srcOffset; - cmdLocPtr->numSrcChars = -1; + cmdLocPtr->numSrcBytes = -1; cmdLocPtr->numCodeBytes = -1; } /* *---------------------------------------------------------------------- @@ -7069,290 +2075,75 @@ * *---------------------------------------------------------------------- */ static void -EnterCmdExtentData(envPtr, cmdIndex, numSrcChars, numCodeBytes) +EnterCmdExtentData(envPtr, cmdIndex, numSrcBytes, numCodeBytes) 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 numSrcChars; /* Number of command source chars. */ + int numSrcBytes; /* Number of command source chars. */ int numCodeBytes; /* Offset of last byte of command code. */ { CmdLocation *cmdLocPtr; if ((cmdIndex < 0) || (cmdIndex >= envPtr->numCommands)) { - panic("EnterCmdStartData: bad command index %d\n", cmdIndex); + panic("EnterCmdExtentData: bad command index %d\n", cmdIndex); } if (cmdIndex > envPtr->cmdMapEnd) { - panic("EnterCmdStartData: no start data registered for command with index %d\n", cmdIndex); + panic("EnterCmdExtentData: missing start data for command %d\n", + cmdIndex); } cmdLocPtr = &(envPtr->cmdMapPtr[cmdIndex]); - cmdLocPtr->numSrcChars = numSrcChars; + cmdLocPtr->numSrcBytes = numSrcBytes; cmdLocPtr->numCodeBytes = numCodeBytes; } /* *---------------------------------------------------------------------- * - * InitArgInfo -- - * - * Initializes a ArgInfo structure to hold information about - * some number of argument words in a command. - * - * Results: - * None. - * - * Side effects: - * The ArgInfo structure is initialized. - * - *---------------------------------------------------------------------- - */ - -static void -InitArgInfo(argInfoPtr) - register ArgInfo *argInfoPtr; /* Points to the ArgInfo structure - * to initialize. */ -{ - argInfoPtr->numArgs = 0; - argInfoPtr->startArray = argInfoPtr->staticStartSpace; - argInfoPtr->endArray = argInfoPtr->staticEndSpace; - argInfoPtr->allocArgs = ARGINFO_INIT_ENTRIES; - argInfoPtr->mallocedArrays = 0; -} - -/* - *---------------------------------------------------------------------- - * - * CollectArgInfo -- - * - * Procedure to scan the argument words of a command and record the - * start and finish of each argument word in a ArgInfo structure. - * - * Results: - * The return value is a standard Tcl result, which is TCL_OK unless - * there was an error while scanning string. If an error occurs then - * the interpreter's result contains a standard error message. - * - * Side effects: - * If necessary, the argument start and end arrays in *argInfoPtr - * are grown and reallocated to a new arrays of double the size, and - * if argInfoPtr->mallocedArray is non-zero the old arrays are freed. - * - *---------------------------------------------------------------------- - */ - -static int -CollectArgInfo(interp, string, lastChar, flags, argInfoPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* The source command string to scan. */ - char *lastChar; /* Pointer to terminating character of - * string. */ - int flags; /* Flags to control compilation (same as - * passed to Tcl_Eval). */ - register ArgInfo *argInfoPtr; - /* Points to the ArgInfo structure in which - * to record the arg word information. */ -{ - register char *src = string;/* Points to current source char. */ - register int type; /* Current char's CHAR_TYPE type. */ - int nestedCmd = (flags & TCL_BRACKET_TERM); - /* 1 if string being scanned is a nested - * command and is terminated by a ']'; - * otherwise 0. */ - int scanningArgs; /* 1 if still scanning argument words to - * determine their start and end. */ - char *wordStart, *wordEnd; /* Points to the first and last significant - * characters of each word. */ - CompileEnv tempCompEnv; /* Only used to hold the termOffset field - * updated by AdvanceToNextWord. */ - char *prev; - - argInfoPtr->numArgs = 0; - scanningArgs = 1; - while (scanningArgs) { - AdvanceToNextWord(src, &tempCompEnv); - src += tempCompEnv.termOffset; - type = CHAR_TYPE(src, lastChar); - - if ((type == TCL_COMMAND_END) && ((*src != ']') || nestedCmd)) { - break; /* done collecting argument words */ - } else if (*src == '"') { - wordStart = src; - src = TclWordEnd(src, lastChar, nestedCmd, NULL); - if (src == lastChar) { - badStringTermination: - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "quoted string doesn't terminate properly", -1); - return TCL_ERROR; - } - prev = (src-1); - if (*src == '"') { - wordEnd = src; - src++; - } else if ((*src == ';') && (*prev == '"')) { - scanningArgs = 0; - wordEnd = prev; - } else { - goto badStringTermination; - } - } else if (*src == '{') { - wordStart = src; - src = TclWordEnd(src, lastChar, nestedCmd, NULL); - if (src == lastChar) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "missing close-brace", -1); - return TCL_ERROR; - } - prev = (src-1); - if (*src == '}') { - wordEnd = src; - src++; - } else if ((*src == ';') && (*prev == '}')) { - scanningArgs = 0; - wordEnd = prev; - } else { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "argument word in braces doesn't terminate properly", -1); - return TCL_ERROR; - } - } else { - wordStart = src; - src = TclWordEnd(src, lastChar, nestedCmd, NULL); - prev = (src-1); - if (src == lastChar) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "missing close-bracket or close-brace", -1); - return TCL_ERROR; - } else if (*src == ';') { - scanningArgs = 0; - wordEnd = prev; - } else { - wordEnd = src; - src++; - if ((src == lastChar) || (*src == '\n') - || ((*src == ']') && nestedCmd)) { - scanningArgs = 0; - } - } - } /* end of test on each kind of word */ - - if (argInfoPtr->numArgs == argInfoPtr->allocArgs) { - int newArgs = 2*argInfoPtr->numArgs; - size_t currBytes = argInfoPtr->numArgs * sizeof(char *); - size_t newBytes = newArgs * sizeof(char *); - char **newStartArrayPtr = - (char **) ckalloc((unsigned) newBytes); - char **newEndArrayPtr = - (char **) ckalloc((unsigned) newBytes); - - /* - * Copy from the old arrays to the new, free the old arrays if - * needed, and mark the new arrays as malloc'ed. - */ - - memcpy((VOID *) newStartArrayPtr, - (VOID *) argInfoPtr->startArray, currBytes); - memcpy((VOID *) newEndArrayPtr, - (VOID *) argInfoPtr->endArray, currBytes); - if (argInfoPtr->mallocedArrays) { - ckfree((char *) argInfoPtr->startArray); - ckfree((char *) argInfoPtr->endArray); - } - argInfoPtr->startArray = newStartArrayPtr; - argInfoPtr->endArray = newEndArrayPtr; - argInfoPtr->allocArgs = newArgs; - argInfoPtr->mallocedArrays = 1; - } - argInfoPtr->startArray[argInfoPtr->numArgs] = wordStart; - argInfoPtr->endArray[argInfoPtr->numArgs] = wordEnd; - argInfoPtr->numArgs++; - } - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * FreeArgInfo -- - * - * Free any storage allocated in a ArgInfo structure. - * - * Results: - * None. - * - * Side effects: - * Allocated storage in the ArgInfo structure is freed. - * - *---------------------------------------------------------------------- - */ - -static void -FreeArgInfo(argInfoPtr) - register ArgInfo *argInfoPtr; /* Points to the ArgInfo structure - * to free. */ -{ - if (argInfoPtr->mallocedArrays) { - ckfree((char *) argInfoPtr->startArray); - ckfree((char *) argInfoPtr->endArray); - } -} - -/* - *---------------------------------------------------------------------- - * - * CreateLoopExceptionRange -- + * TclCreateExceptRange -- * * Procedure that allocates and initializes a new ExceptionRange - * structure of the specified kind in a CompileEnv's ExceptionRange - * array. + * 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->mallocedExcRangeArray is non-zero the old + * 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. * *---------------------------------------------------------------------- */ -static int -CreateExceptionRange(type, envPtr) +int +TclCreateExceptRange(type, envPtr) ExceptionRangeType type; /* The kind of ExceptionRange desired. */ - register CompileEnv *envPtr;/* Points to the CompileEnv for which a new - * loop ExceptionRange structure is to be - * allocated. */ + register CompileEnv *envPtr;/* Points to CompileEnv for which to + * create a new ExceptionRange structure. */ { - int index; /* Index for the newly-allocated - * ExceptionRange structure. */ register ExceptionRange *rangePtr; - /* Points to the new ExceptionRange - * structure */ + int index = envPtr->exceptArrayNext; - index = envPtr->excRangeArrayNext; - if (index >= envPtr->excRangeArrayEnd) { + if (index >= envPtr->exceptArrayEnd) { /* * Expand the ExceptionRange array. The currently allocated entries - * are stored between elements 0 and (envPtr->excRangeArrayNext - 1) + * are stored between elements 0 and (envPtr->exceptArrayNext - 1) * [inclusive]. */ size_t currBytes = - envPtr->excRangeArrayNext * sizeof(ExceptionRange); - int newElems = 2*envPtr->excRangeArrayEnd; + envPtr->exceptArrayNext * sizeof(ExceptionRange); + int newElems = 2*envPtr->exceptArrayEnd; size_t newBytes = newElems * sizeof(ExceptionRange); ExceptionRange *newPtr = (ExceptionRange *) ckalloc((unsigned) newBytes); /* @@ -7359,24 +2150,24 @@ * Copy from old ExceptionRange array to new, free old * ExceptionRange array if needed, and mark the new ExceptionRange * array as malloced. */ - memcpy((VOID *) newPtr, (VOID *) envPtr->excRangeArrayPtr, + memcpy((VOID *) newPtr, (VOID *) envPtr->exceptArrayPtr, currBytes); - if (envPtr->mallocedExcRangeArray) { - ckfree((char *) envPtr->excRangeArrayPtr); - } - envPtr->excRangeArrayPtr = (ExceptionRange *) newPtr; - envPtr->excRangeArrayEnd = newElems; - envPtr->mallocedExcRangeArray = 1; - } - envPtr->excRangeArrayNext++; - - rangePtr = &(envPtr->excRangeArrayPtr[index]); + if (envPtr->mallocedExceptArray) { + ckfree((char *) envPtr->exceptArrayPtr); + } + envPtr->exceptArrayPtr = (ExceptionRange *) newPtr; + envPtr->exceptArrayEnd = newElems; + envPtr->mallocedExceptArray = 1; + } + envPtr->exceptArrayNext++; + + rangePtr = &(envPtr->exceptArrayPtr[index]); rangePtr->type = type; - rangePtr->nestingLevel = envPtr->excRangeDepth; + rangePtr->nestingLevel = envPtr->exceptDepth; rangePtr->codeOffset = -1; rangePtr->numCodeBytes = -1; rangePtr->breakOffset = -1; rangePtr->continueOffset = -1; rangePtr->catchOffset = -1; @@ -7405,19 +2196,14 @@ * *---------------------------------------------------------------------- */ int -TclCreateAuxData(clientData, dupProc, freeProc, envPtr) +TclCreateAuxData(clientData, typePtr, envPtr) ClientData clientData; /* The compilation auxiliary data to store * in the new aux data record. */ - AuxDataDupProc *dupProc; /* Procedure to call to duplicate the - * compilation aux data when the containing - * ByteCode structure is duplicated. */ - AuxDataFreeProc *freeProc; /* Procedure to call to free the - * compilation aux data when the containing - * ByteCode structure is freed. */ + 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; @@ -7452,12 +2238,11 @@ } envPtr->auxDataArrayNext++; auxDataPtr = &(envPtr->auxDataArrayPtr[index]); auxDataPtr->clientData = clientData; - auxDataPtr->dupProc = dupProc; - auxDataPtr->freeProc = freeProc; + auxDataPtr->type = typePtr; return index; } /* *---------------------------------------------------------------------- @@ -7600,28 +2385,28 @@ { /* * Initialize the JumpFixup structure: * - codeOffset is offset of first byte of jump below * - cmdIndex is index of the command after the current one - * - excRangeIndex is the index of the first ExceptionRange after + * - exceptIndex is the index of the first ExceptionRange after * the current one. */ jumpFixupPtr->jumpType = jumpType; - jumpFixupPtr->codeOffset = TclCurrCodeOffset(); + jumpFixupPtr->codeOffset = (envPtr->codeNext - envPtr->codeStart); jumpFixupPtr->cmdIndex = envPtr->numCommands; - jumpFixupPtr->excRangeIndex = envPtr->excRangeArrayNext; + jumpFixupPtr->exceptIndex = envPtr->exceptArrayNext; switch (jumpType) { case TCL_UNCONDITIONAL_JUMP: - TclEmitInstInt1(INST_JUMP1, /*offset*/ 0, envPtr); + TclEmitInstInt1(INST_JUMP1, 0, envPtr); break; case TCL_TRUE_JUMP: - TclEmitInstInt1(INST_JUMP_TRUE1, /*offset*/ 0, envPtr); + TclEmitInstInt1(INST_JUMP_TRUE1, 0, envPtr); break; default: - TclEmitInstInt1(INST_JUMP_FALSE1, /*offset*/ 0, envPtr); + TclEmitInstInt1(INST_JUMP_FALSE1, 0, envPtr); break; } } /* @@ -7682,13 +2467,18 @@ 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. */ - TclEnsureCodeSpace(3, envPtr); /* NB: might change code addresses! */ + if ((envPtr->codeNext + 3) > envPtr->codeEnd) { + TclExpandCodeArray(envPtr); + } jumpPc = (envPtr->codeStart + jumpFixupPtr->codeOffset); for (numBytes = envPtr->codeNext-jumpPc-2, p = jumpPc+2+numBytes-1; numBytes > 0; numBytes--, p--) { p[3] = p[0]; } @@ -7717,14 +2507,14 @@ for (k = firstCmd; k <= lastCmd; k++) { (envPtr->cmdMapPtr[k]).codeOffset += 3; } } - firstRange = jumpFixupPtr->excRangeIndex; - lastRange = (envPtr->excRangeArrayNext - 1); + firstRange = jumpFixupPtr->exceptIndex; + lastRange = (envPtr->exceptArrayNext - 1); for (k = firstRange; k <= lastRange; k++) { - ExceptionRange *rangePtr = &(envPtr->excRangeArrayPtr[k]); + ExceptionRange *rangePtr = &(envPtr->exceptArrayPtr[k]); rangePtr->codeOffset += 3; switch (rangePtr->type) { case LOOP_EXCEPTION_RANGE: rangePtr->breakOffset += 3; @@ -7734,12 +2524,929 @@ break; case CATCH_EXCEPTION_RANGE: rangePtr->catchOffset += 3; break; default: - panic("TclFixupForwardJump: unrecognized ExceptionRange type %d\n", rangePtr->type); + panic("TclFixupForwardJump: bad ExceptionRange type %d\n", + rangePtr->type); } } return 1; /* the jump was grown */ } + +/* + *---------------------------------------------------------------------- + * + * 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 (&instructionTable[0]). + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +InstructionDesc * +TclGetInstructionTable() +{ + return &instructionTable[0]; +} + +/* + *-------------------------------------------------------------- + * + * TclRegisterAuxDataType -- + * + * This procedure is called to register a new AuxData type + * in the table of all AuxData types supported by Tcl. + * + * Results: + * None. + * + * Side effects: + * The type is registered in the AuxData type table. If there was already + * a type with the same name as in typePtr, it is replaced with the + * new type. + * + *-------------------------------------------------------------- + */ + +void +TclRegisterAuxDataType(typePtr) + AuxDataType *typePtr; /* Information about object type; + * storage must be statically + * allocated (must live forever). */ +{ + register Tcl_HashEntry *hPtr; + int new; + + Tcl_MutexLock(&tableMutex); + if (!auxDataTypeTableInitialized) { + TclInitAuxDataTypeTable(); + } + + /* + * If there's already a type with the given name, remove it. + */ + + hPtr = Tcl_FindHashEntry(&auxDataTypeTable, typePtr->name); + if (hPtr != (Tcl_HashEntry *) NULL) { + Tcl_DeleteHashEntry(hPtr); + } + + /* + * Now insert the new object type. + */ + + hPtr = Tcl_CreateHashEntry(&auxDataTypeTable, typePtr->name, &new); + if (new) { + Tcl_SetHashValue(hPtr, typePtr); + } + Tcl_MutexUnlock(&tableMutex); +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + *---------------------------------------------------------------------- + */ + +AuxDataType * +TclGetAuxDataType(typeName) + char *typeName; /* Name of AuxData type to look up. */ +{ + register Tcl_HashEntry *hPtr; + AuxDataType *typePtr = NULL; + + Tcl_MutexLock(&tableMutex); + if (!auxDataTypeTableInitialized) { + TclInitAuxDataTypeTable(); + } + + hPtr = Tcl_FindHashEntry(&auxDataTypeTable, typeName); + if (hPtr != (Tcl_HashEntry *) NULL) { + typePtr = (AuxDataType *) Tcl_GetHashValue(hPtr); + } + Tcl_MutexUnlock(&tableMutex); + + return typePtr; +} + +/* + *-------------------------------------------------------------- + * + * TclInitAuxDataTypeTable -- + * + * This procedure is invoked to perform once-only initialization of + * the AuxData type table. It also registers the AuxData types defined in + * this file. + * + * Results: + * None. + * + * Side effects: + * Initializes the table of defined AuxData types "auxDataTypeTable" with + * builtin AuxData types defined in this file. + * + *-------------------------------------------------------------- + */ + +void +TclInitAuxDataTypeTable() +{ + /* + * The table mutex must already be held before this routine is invoked. + */ + + auxDataTypeTableInitialized = 1; + Tcl_InitHashTable(&auxDataTypeTable, TCL_STRING_KEYS); + + /* + * There is only one AuxData type at this time, so register it here. + */ + + TclRegisterAuxDataType(&tclForeachInfoType); +} + +/* + *---------------------------------------------------------------------- + * + * TclFinalizeAuxDataTypeTable -- + * + * This procedure is called by Tcl_Finalize after all exit handlers + * have been run to free up storage associated with the table of AuxData + * types. This procedure is called by TclFinalizeExecution() which + * is called by Tcl_Finalize(). + * + * Results: + * None. + * + * Side effects: + * Deletes all entries in the hash table of AuxData types. + * + *---------------------------------------------------------------------- + */ + +void +TclFinalizeAuxDataTypeTable() +{ + Tcl_MutexLock(&tableMutex); + if (auxDataTypeTableInitialized) { + Tcl_DeleteHashTable(&auxDataTypeTable); + auxDataTypeTableInitialized = 0; + } + Tcl_MutexUnlock(&tableMutex); +} + +/* + *---------------------------------------------------------------------- + * + * 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(envPtr) + 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) { + 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) { + 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)) { + srcDeltaNext++; + } else { + srcDeltaNext += 5; /* 1 byte for 0xFF, 4 for delta */ + } + prevSrcOffset = mapPtr[i].srcOffset; + + srcLen = mapPtr[i].numSrcBytes; + if (srcLen < 0) { + 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(envPtr, codePtr, startPtr) + 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) { + 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) { + 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)) { + 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) { + 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_DEBUG +/* + *---------------------------------------------------------------------- + * + * TclPrintByteCodeObj -- + * + * This procedure prints ("disassembles") the instructions of a + * bytecode object to stdout. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TclPrintByteCodeObj(interp, objPtr) + Tcl_Interp *interp; /* Used only for Tcl_GetStringFromObj. */ + Tcl_Obj *objPtr; /* The bytecode object to disassemble. */ +{ + ByteCode* codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; + unsigned char *codeStart, *codeLimit, *pc; + unsigned char *codeDeltaNext, *codeLengthNext; + unsigned char *srcDeltaNext, *srcLengthNext; + int codeOffset, codeLen, srcOffset, srcLen, numCmds, delta, i; + Interp *iPtr = (Interp *) *codePtr->interpHandle; + + if (codePtr->refCount <= 0) { + return; /* already freed */ + } + + codeStart = codePtr->codeStart; + codeLimit = (codeStart + codePtr->numCodeBytes); + numCmds = codePtr->numCommands; + + /* + * Print header lines describing the ByteCode. + */ + + fprintf(stdout, "\nByteCode 0x%x, refCt %u, epoch %u, interp 0x%x (epoch %u)\n", + (unsigned int) codePtr, codePtr->refCount, + codePtr->compileEpoch, (unsigned int) iPtr, + iPtr->compileEpoch); + fprintf(stdout, " Source "); + TclPrintSource(stdout, codePtr->source, + TclMin(codePtr->numSrcBytes, 55)); + fprintf(stdout, "\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? + ((float)codePtr->structureSize)/((float)codePtr->numSrcBytes) : 0.0)); +#else + 0.0); +#endif +#ifdef TCL_COMPILE_STATS + fprintf(stdout, + " Code %d = header %d+inst %d+litObj %d+exc %d+aux %d+cmdMap %d\n", + codePtr->structureSize, + (sizeof(ByteCode) - (sizeof(size_t) + sizeof(Tcl_Time))), + codePtr->numCodeBytes, + (codePtr->numLitObjects * sizeof(Tcl_Obj *)), + (codePtr->numExceptRanges * sizeof(ExceptionRange)), + (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; + fprintf(stdout, + " Proc 0x%x, refCt %d, args %d, compiled locals %d\n", + (unsigned int) procPtr, procPtr->refCount, procPtr->numArgs, + numCompiledLocals); + if (numCompiledLocals > 0) { + CompiledLocal *localPtr = procPtr->firstLocalPtr; + for (i = 0; i < numCompiledLocals; i++) { + fprintf(stdout, " slot %d%s%s%s%s%s%s", i, + ((localPtr->flags & VAR_SCALAR)? ", 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)) { + fprintf(stdout, "\n"); + } else { + fprintf(stdout, ", \"%s\"\n", localPtr->name); + } + localPtr = localPtr->nextPtr; + } + } + } + + /* + * Print the ExceptionRange array. + */ + + if (codePtr->numExceptRanges > 0) { + fprintf(stdout, " Exception ranges %d, depth %d:\n", + codePtr->numExceptRanges, codePtr->maxExceptDepth); + for (i = 0; i < codePtr->numExceptRanges; i++) { + ExceptionRange *rangePtr = &(codePtr->exceptArrayPtr[i]); + fprintf(stdout, " %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: + fprintf(stdout, "continue %d, break %d\n", + rangePtr->continueOffset, rangePtr->breakOffset); + break; + case CATCH_EXCEPTION_RANGE: + fprintf(stdout, "catch %d\n", rangePtr->catchOffset); + break; + default: + panic("TclPrintByteCodeObj: bad ExceptionRange type %d\n", + 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) { + fprintf(stdout, " "); + pc += TclPrintInstruction(codePtr, pc); + } + return; + } + + /* + * Print table showing the code offset, source offset, and source + * length for each command. These are encoded as a sequence of bytes. + */ + + fprintf(stdout, " 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 int) (*codeDeltaNext) == (unsigned int) 0xFF) { + codeDeltaNext++; + delta = TclGetInt4AtPtr(codeDeltaNext); + codeDeltaNext += 4; + } else { + delta = TclGetInt1AtPtr(codeDeltaNext); + codeDeltaNext++; + } + codeOffset += delta; + + if ((unsigned int) (*codeLengthNext) == (unsigned int) 0xFF) { + codeLengthNext++; + codeLen = TclGetInt4AtPtr(codeLengthNext); + codeLengthNext += 4; + } else { + codeLen = TclGetInt1AtPtr(codeLengthNext); + codeLengthNext++; + } + + if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) { + srcDeltaNext++; + delta = TclGetInt4AtPtr(srcDeltaNext); + srcDeltaNext += 4; + } else { + delta = TclGetInt1AtPtr(srcDeltaNext); + srcDeltaNext++; + } + srcOffset += delta; + + if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) { + srcLengthNext++; + srcLen = TclGetInt4AtPtr(srcLengthNext); + srcLengthNext += 4; + } else { + srcLen = TclGetInt1AtPtr(srcLengthNext); + srcLengthNext++; + } + + fprintf(stdout, "%s%4d: pc %d-%d, src %d-%d", + ((i % 2)? " " : "\n "), + (i+1), codeOffset, (codeOffset + codeLen - 1), + srcOffset, (srcOffset + srcLen - 1)); + } + if (numCmds > 0) { + fprintf(stdout, "\n"); + } + + /* + * 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 int) (*codeDeltaNext) == (unsigned int) 0xFF) { + codeDeltaNext++; + delta = TclGetInt4AtPtr(codeDeltaNext); + codeDeltaNext += 4; + } else { + delta = TclGetInt1AtPtr(codeDeltaNext); + codeDeltaNext++; + } + codeOffset += delta; + + if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) { + srcDeltaNext++; + delta = TclGetInt4AtPtr(srcDeltaNext); + srcDeltaNext += 4; + } else { + delta = TclGetInt1AtPtr(srcDeltaNext); + srcDeltaNext++; + } + srcOffset += delta; + + if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) { + srcLengthNext++; + srcLen = TclGetInt4AtPtr(srcLengthNext); + srcLengthNext += 4; + } else { + srcLen = TclGetInt1AtPtr(srcLengthNext); + srcLengthNext++; + } + + /* + * Print instructions before command i. + */ + + while ((pc-codeStart) < codeOffset) { + fprintf(stdout, " "); + pc += TclPrintInstruction(codePtr, pc); + } + + fprintf(stdout, " Command %d: ", (i+1)); + TclPrintSource(stdout, (codePtr->source + srcOffset), + TclMin(srcLen, 55)); + fprintf(stdout, "\n"); + } + if (pc < codeLimit) { + /* + * Print instructions after the last command. + */ + + while (pc < codeLimit) { + fprintf(stdout, " "); + pc += TclPrintInstruction(codePtr, pc); + } + } +} +#endif /* TCL_COMPILE_DEBUG */ + +/* + *---------------------------------------------------------------------- + * + * 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(codePtr, pc) + ByteCode* codePtr; /* Bytecode containing the instruction. */ + unsigned char *pc; /* Points to first byte of instruction. */ +{ + Proc *procPtr = codePtr->procPtr; + unsigned char opCode = *pc; + register InstructionDesc *instDesc = &instructionTable[opCode]; + unsigned char *codeStart = codePtr->codeStart; + unsigned int pcOffset = (pc - codeStart); + int opnd, i, j; + + fprintf(stdout, "(%u) %s ", pcOffset, instDesc->name); + for (i = 0; i < instDesc->numOperands; i++) { + switch (instDesc->opTypes[i]) { + case OPERAND_INT1: + opnd = TclGetInt1AtPtr(pc+1+i); + if ((i == 0) && ((opCode == INST_JUMP1) + || (opCode == INST_JUMP_TRUE1) + || (opCode == INST_JUMP_FALSE1))) { + fprintf(stdout, "%d # pc %u", opnd, (pcOffset + opnd)); + } else { + fprintf(stdout, "%d", opnd); + } + break; + case OPERAND_INT4: + opnd = TclGetInt4AtPtr(pc+1+i); + if ((i == 0) && ((opCode == INST_JUMP4) + || (opCode == INST_JUMP_TRUE4) + || (opCode == INST_JUMP_FALSE4))) { + fprintf(stdout, "%d # pc %u", opnd, (pcOffset + opnd)); + } else { + fprintf(stdout, "%d", opnd); + } + break; + case OPERAND_UINT1: + opnd = TclGetUInt1AtPtr(pc+1+i); + if ((i == 0) && (opCode == INST_PUSH1)) { + fprintf(stdout, "%u # ", (unsigned int) opnd); + TclPrintObject(stdout, codePtr->objArrayPtr[opnd], 40); + } else if ((i == 0) && ((opCode == INST_LOAD_SCALAR1) + || (opCode == INST_LOAD_ARRAY1) + || (opCode == INST_STORE_SCALAR1) + || (opCode == INST_STORE_ARRAY1))) { + int localCt = procPtr->numCompiledLocals; + CompiledLocal *localPtr = procPtr->firstLocalPtr; + if (opnd >= localCt) { + panic("TclPrintInstruction: bad local var index %u (%u locals)\n", + (unsigned int) opnd, localCt); + return instDesc->numBytes; + } + for (j = 0; j < opnd; j++) { + localPtr = localPtr->nextPtr; + } + if (TclIsVarTemporary(localPtr)) { + fprintf(stdout, "%u # temp var %u", + (unsigned int) opnd, (unsigned int) opnd); + } else { + fprintf(stdout, "%u # var ", (unsigned int) opnd); + TclPrintSource(stdout, localPtr->name, 40); + } + } else { + fprintf(stdout, "%u ", (unsigned int) opnd); + } + break; + case OPERAND_UINT4: + opnd = TclGetUInt4AtPtr(pc+1+i); + if (opCode == INST_PUSH4) { + fprintf(stdout, "%u # ", opnd); + TclPrintObject(stdout, codePtr->objArrayPtr[opnd], 40); + } else if ((i == 0) && ((opCode == INST_LOAD_SCALAR4) + || (opCode == INST_LOAD_ARRAY4) + || (opCode == INST_STORE_SCALAR4) + || (opCode == INST_STORE_ARRAY4))) { + int localCt = procPtr->numCompiledLocals; + CompiledLocal *localPtr = procPtr->firstLocalPtr; + if (opnd >= localCt) { + panic("TclPrintInstruction: bad local var index %u (%u locals)\n", + (unsigned int) opnd, localCt); + return instDesc->numBytes; + } + for (j = 0; j < opnd; j++) { + localPtr = localPtr->nextPtr; + } + if (TclIsVarTemporary(localPtr)) { + fprintf(stdout, "%u # temp var %u", + (unsigned int) opnd, (unsigned int) opnd); + } else { + fprintf(stdout, "%u # var ", (unsigned int) opnd); + TclPrintSource(stdout, localPtr->name, 40); + } + } else { + fprintf(stdout, "%u ", (unsigned int) opnd); + } + break; + case OPERAND_NONE: + default: + break; + } + } + fprintf(stdout, "\n"); + return instDesc->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(outFile, objPtr, maxChars) + 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(outFile, string, maxChars) + FILE *outFile; /* The file to print the source to. */ + char *string; /* The string to print. */ + int maxChars; /* Maximum number of chars to print. */ +{ + register char *p; + register int i = 0; + + if (string == NULL) { + fprintf(outFile, "\"\""); + return; + } + + fprintf(outFile, "\""); + p = string; + for (; (*p != '\0') && (i < maxChars); p++, i++) { + switch (*p) { + case '"': + fprintf(outFile, "\\\""); + continue; + case '\f': + fprintf(outFile, "\\f"); + continue; + case '\n': + fprintf(outFile, "\\n"); + continue; + case '\r': + fprintf(outFile, "\\r"); + continue; + case '\t': + fprintf(outFile, "\\t"); + continue; + case '\v': + fprintf(outFile, "\\v"); + continue; + default: + fprintf(outFile, "%c", *p); + continue; + } + } + fprintf(outFile, "\""); +} + +#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(codePtr) + ByteCode *codePtr; /* Points to ByteCode structure with info + * to add to accumulated statistics. */ +{ + Interp *iPtr = (Interp *) *codePtr->interpHandle; + register ByteCodeStats *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(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 */ Index: generic/tclCompile.h ================================================================== --- generic/tclCompile.h +++ generic/tclCompile.h @@ -1,22 +1,27 @@ /* * tclCompile.h -- * - * Copyright (c) 1996-1997 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclCompile.h 1.37 97/08/07 19:11:50 + * RCS: @(#) $Id: tclCompile.h,v 1.1.2.5 1999/03/10 22:51:14 redman Exp $ */ #ifndef _TCLCOMPILATION #define _TCLCOMPILATION 1 #ifndef _TCLINT #include "tclInt.h" #endif /* _TCLINT */ + +#ifdef BUILD_tcl +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT +#endif /* *------------------------------------------------------------------------ * Variables related to compilation. These are used in tclCompile.c, * tclExecute.c, tclBasic.c, and their clients. @@ -52,36 +57,10 @@ * This variable is linked to the Tcl variable "tcl_traceExec". */ extern int tclTraceExec; -/* - * The number of bytecode compilations and various other compilation-related - * statistics. The tclByteCodeCount and tclSourceCount arrays are used to - * hold the count of ByteCodes and sources whose sizes fall into various - * binary decades; e.g., tclByteCodeCount[5] is a count of the ByteCodes - * with size larger than 2**4 and less than or equal to 2**5. - */ - -#ifdef TCL_COMPILE_STATS -extern long tclNumCompilations; -extern double tclTotalSourceBytes; -extern double tclTotalCodeBytes; - -extern double tclTotalInstBytes; -extern double tclTotalObjBytes; -extern double tclTotalExceptBytes; -extern double tclTotalAuxBytes; -extern double tclTotalCmdMapBytes; - -extern double tclCurrentSourceBytes; -extern double tclCurrentCodeBytes; - -extern int tclSourceCount[32]; -extern int tclByteCodeCount[32]; -#endif /* TCL_COMPILE_STATS */ - /* *------------------------------------------------------------------------ * Data structures related to compilation. *------------------------------------------------------------------------ */ @@ -101,16 +80,16 @@ * since a break there terminates the for command. This means a for command * actually generates two LoopInfo structures. */ typedef enum { - LOOP_EXCEPTION_RANGE, /* Code range is part of a loop command. - * break and continue "exceptions" cause + LOOP_EXCEPTION_RANGE, /* Exception's range is part of a loop. + * Break and continue "exceptions" cause * jumps to appropriate PC offsets. */ - CATCH_EXCEPTION_RANGE /* Code range is controlled by a catch - * command. Errors in the range cause a - * jump to a particular PC offset. */ + 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. @@ -117,20 +96,18 @@ * 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 a LOOP_EXCEPTION_RANGE, the target - * PC offset for a break command in the - * range. */ - int continueOffset; /* If a 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 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 an "exception" in range. */ + * offset for any "exception" in range. */ } ExceptionRange; /* * Structure used to map between instruction pc and source locations. It * defines for each compiled Tcl command its code's starting offset and @@ -141,11 +118,11 @@ 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 numSrcChars; /* Number of command source chars. */ + int numSrcBytes; /* Number of command source chars. */ } CmdLocation; /* * CompileProcs need the ability to record information during compilation * that can be used by bytecode instructions during execution. The AuxData @@ -163,37 +140,51 @@ */ typedef ClientData (AuxDataDupProc) _ANSI_ARGS_((ClientData clientData)); typedef void (AuxDataFreeProc) _ANSI_ARGS_((ClientData clientData)); +/* + * 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 { + 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. */ +} AuxDataType; + /* * The definition of the AuxData structure that holds information created * during compilation by CompileProcs and used by instructions during * execution. */ typedef struct AuxData { + AuxDataType *type; /* pointer to the AuxData type associated with + * this ClientData. */ ClientData clientData; /* The compilation data itself. */ - 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. */ } 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 40 +#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 { @@ -204,40 +195,29 @@ * interpreter. */ 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 excRangeDepth; /* Current exception range nesting level; + int exceptDepth; /* Current exception range nesting level; * -1 if not in any range currently. */ - int maxExcRangeDepth; /* Max nesting level of exception ranges; + 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. */ - Tcl_HashTable objTable; /* Contains all Tcl objects referenced by - * the compiled code. Indexed by the string - * representations of the objects. Used to + 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. */ - int pushSimpleWords; /* Set 1 by callers of compilation routines - * if they should emit instructions to push - * "simple" command words (those that are - * just a sequence of characters). If 0, the - * callers are responsible for compiling - * simple words. */ - int wordIsSimple; /* Set 1 by compilation procedures before - * returning if the previous command word - * was just a sequence of characters, - * otherwise 0. Used to help determine the - * command being compiled. */ - int numSimpleWordChars; /* If wordIsSimple is 1 then the number of - * characters in the simple word, else 0. */ int exprIsJustVarRef; /* Set 1 if the expression last compiled by * TclCompileExpr consisted of just a * variable reference as in the expression * of "if $b then...". Otherwise 0. Used * to implement expr's 2 level substitution @@ -246,35 +226,33 @@ * expression last compiled is a comparison. * Otherwise 0. If 1, since the operands * might be strings, the expr is compiled * out-of-line to implement expr's 2 level * substitution semantics properly. */ - int termOffset; /* Offset of character just after the last - * one compiled. Set by compilation - * procedures before returning. */ 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.*/ - Tcl_Obj **objArrayPtr; /* Points to start of object array. */ - int objArrayNext; /* Index of next free object array entry. */ - int objArrayEnd; /* Index just after last obj array entry. */ - int mallocedObjArray; /* 1 if object array was expanded and + 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 *excRangeArrayPtr; + ExceptionRange *exceptArrayPtr; /* Points to start of the ExceptionRange * array. */ - int excRangeArrayNext; /* Next free ExceptionRange array index. - * excRangeArrayNext is the number of ranges - * and (excRangeArrayNext-1) is the index of + 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 excRangeArrayEnd; /* Index after the last ExceptionRange + int exceptArrayEnd; /* Index after the last ExceptionRange * array entry. */ - int mallocedExcRangeArray; /* 1 if ExceptionRange array was expanded - * and excRangeArrayPtr points in heap, + int mallocedExceptArray; /* 1 if ExceptionRange array was expanded + * and exceptArrayPtr points in heap, * else 0. */ 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. */ @@ -289,13 +267,13 @@ 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. */ - Tcl_Obj *staticObjArraySpace[COMPILEENV_INIT_NUM_OBJECTS]; - /* Initial storage for object array. */ - ExceptionRange staticExcRangeArraySpace[COMPILEENV_INIT_EXCEPT_RANGES]; + LiteralEntry staticLiteralSpace[COMPILEENV_INIT_NUM_OBJECTS]; + /* Initial storage of LiteralEntry array. */ + ExceptionRange staticExceptArraySpace[COMPILEENV_INIT_EXCEPT_RANGES]; /* Initial ExceptionRange 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. */ @@ -303,59 +281,77 @@ /* * 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 object array, the ExceptionRange array, the - * CmdLocation map, and the compilation AuxData array. + * 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 typedef struct ByteCode { - 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 + 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 */ 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. Used for - * debugging. */ - size_t totalSize; /* Total number of bytes required for this - * ByteCode structure including the storage - * for Tcl objects in its object array. */ + * 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 numSrcChars; /* Number of source chars compiled. */ + int numSrcBytes; /* Number of source bytes compiled. */ int numCodeBytes; /* Number of code bytes. */ - int numObjects; /* Number of Tcl objects in object array. */ - int numExcRanges; /* Number of ExceptionRange array elems. */ + 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 maxExcRangeDepth; /* Maximum nesting level of ExceptionRanges; + 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 object array. - * This is just after the last code byte. */ - ExceptionRange *excRangeArrayPtr; + 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 @@ -392,110 +388,115 @@ * 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. */ +#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 opcodes must correspond - * to the entries in the table of instruction descriptions 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 for the Tcl bytecode instructions. These must correspond to the + * entries in the table of instruction descriptions, instructionTable, 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 (INST_DONE + 1) -#define INST_PUSH4 (INST_DONE + 2) -#define INST_POP (INST_DONE + 3) -#define INST_DUP (INST_DONE + 4) -#define INST_CONCAT1 (INST_DONE + 5) -#define INST_INVOKE_STK1 (INST_DONE + 6) -#define INST_INVOKE_STK4 (INST_DONE + 7) -#define INST_EVAL_STK (INST_DONE + 8) -#define INST_EXPR_STK (INST_DONE + 9) +#define INST_PUSH1 1 +#define INST_PUSH4 2 +#define INST_POP 3 +#define INST_DUP 4 +#define INST_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 (INST_EXPR_STK + 1) -#define INST_LOAD_SCALAR4 (INST_LOAD_SCALAR1 + 1) -#define INST_LOAD_SCALAR_STK (INST_LOAD_SCALAR1 + 2) -#define INST_LOAD_ARRAY1 (INST_LOAD_SCALAR1 + 3) -#define INST_LOAD_ARRAY4 (INST_LOAD_SCALAR1 + 4) -#define INST_LOAD_ARRAY_STK (INST_LOAD_SCALAR1 + 5) -#define INST_LOAD_STK (INST_LOAD_SCALAR1 + 6) -#define INST_STORE_SCALAR1 (INST_LOAD_SCALAR1 + 7) -#define INST_STORE_SCALAR4 (INST_LOAD_SCALAR1 + 8) -#define INST_STORE_SCALAR_STK (INST_LOAD_SCALAR1 + 9) -#define INST_STORE_ARRAY1 (INST_LOAD_SCALAR1 + 10) -#define INST_STORE_ARRAY4 (INST_LOAD_SCALAR1 + 11) -#define INST_STORE_ARRAY_STK (INST_LOAD_SCALAR1 + 12) -#define INST_STORE_STK (INST_LOAD_SCALAR1 + 13) +#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 (INST_STORE_STK + 1) -#define INST_INCR_SCALAR_STK (INST_INCR_SCALAR1 + 1) -#define INST_INCR_ARRAY1 (INST_INCR_SCALAR1 + 2) -#define INST_INCR_ARRAY_STK (INST_INCR_SCALAR1 + 3) -#define INST_INCR_STK (INST_INCR_SCALAR1 + 4) -#define INST_INCR_SCALAR1_IMM (INST_INCR_SCALAR1 + 5) -#define INST_INCR_SCALAR_STK_IMM (INST_INCR_SCALAR1 + 6) -#define INST_INCR_ARRAY1_IMM (INST_INCR_SCALAR1 + 7) -#define INST_INCR_ARRAY_STK_IMM (INST_INCR_SCALAR1 + 8) -#define INST_INCR_STK_IMM (INST_INCR_SCALAR1 + 9) +#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 (INST_INCR_STK_IMM + 1) -#define INST_JUMP4 (INST_JUMP1 + 1) -#define INST_JUMP_TRUE1 (INST_JUMP1 + 2) -#define INST_JUMP_TRUE4 (INST_JUMP1 + 3) -#define INST_JUMP_FALSE1 (INST_JUMP1 + 4) -#define INST_JUMP_FALSE4 (INST_JUMP1 + 5) +#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 (INST_JUMP_FALSE4 + 1) -#define INST_LAND (INST_LOR + 1) -#define INST_BITOR (INST_LOR + 2) -#define INST_BITXOR (INST_LOR + 3) -#define INST_BITAND (INST_LOR + 4) -#define INST_EQ (INST_LOR + 5) -#define INST_NEQ (INST_LOR + 6) -#define INST_LT (INST_LOR + 7) -#define INST_GT (INST_LOR + 8) -#define INST_LE (INST_LOR + 9) -#define INST_GE (INST_LOR + 10) -#define INST_LSHIFT (INST_LOR + 11) -#define INST_RSHIFT (INST_LOR + 12) -#define INST_ADD (INST_LOR + 13) -#define INST_SUB (INST_LOR + 14) -#define INST_MULT (INST_LOR + 15) -#define INST_DIV (INST_LOR + 16) -#define INST_MOD (INST_LOR + 17) -#define INST_UPLUS (INST_LOR + 18) -#define INST_UMINUS (INST_LOR + 19) -#define INST_BITNOT (INST_LOR + 20) -#define INST_LNOT (INST_LOR + 21) -#define INST_CALL_BUILTIN_FUNC1 (INST_LOR + 22) -#define INST_CALL_FUNC1 (INST_LOR + 23) -#define INST_TRY_CVT_TO_NUMERIC (INST_LOR + 24) +#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 (INST_TRY_CVT_TO_NUMERIC + 1) -#define INST_CONTINUE (INST_BREAK + 1) +#define INST_BREAK 65 +#define INST_CONTINUE 66 /* Opcodes 67 to 68 */ -#define INST_FOREACH_START4 (INST_CONTINUE + 1) -#define INST_FOREACH_STEP4 (INST_FOREACH_START4 + 1) +#define INST_FOREACH_START4 67 +#define INST_FOREACH_STEP4 68 /* Opcodes 69 to 72 */ -#define INST_BEGIN_CATCH4 (INST_FOREACH_STEP4 + 1) -#define INST_END_CATCH (INST_BEGIN_CATCH4 + 1) -#define INST_PUSH_RESULT (INST_BEGIN_CATCH4 + 2) -#define INST_PUSH_RETURN_CODE (INST_BEGIN_CATCH4 + 3) +#define INST_BEGIN_CATCH4 69 +#define INST_END_CATCH 70 +#define INST_PUSH_RESULT 71 +#define INST_PUSH_RETURN_CODE 72 /* The last opcode */ -#define LAST_INST_OPCODE INST_PUSH_RETURN_CODE +#define LAST_INST_OPCODE 72 /* * 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. @@ -556,11 +557,11 @@ #define BUILTIN_FUNC_INT 21 #define BUILTIN_FUNC_RAND 22 #define BUILTIN_FUNC_ROUND 23 #define BUILTIN_FUNC_SRAND 24 -#define LAST_BUILTIN_FUNC BUILTIN_FUNC_SRAND +#define LAST_BUILTIN_FUNC 24 /* * 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. @@ -579,34 +580,10 @@ * function when invoking it. */ } BuiltinFunc; extern BuiltinFunc builtinFuncTable[]; -/* - * The structure used to hold information about the start and end of each - * argument word in a command. - */ - -#define ARGINFO_INIT_ENTRIES 5 - -typedef struct ArgInfo { - int numArgs; /* Number of argument words in command. */ - char **startArray; /* Array of pointers to the first character - * of each argument word. */ - char **endArray; /* Array of pointers to the last character - * of each argument word. */ - int allocArgs; /* Number of array entries currently - * allocated. */ - int mallocedArrays; /* 1 if the arrays were expanded and - * wordStartArray/wordEndArray point into - * the heap, else 0. */ - char *staticStartSpace[ARGINFO_INIT_ENTRIES]; - /* Initial storage for word start array. */ - char *staticEndSpace[ARGINFO_INIT_ENTRIES]; - /* Initial storage for word end array. */ -} ArgInfo; - /* * 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 @@ -631,11 +608,11 @@ 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 excRangeIndex; /* Index of the first range entry in the + 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. */ @@ -678,22 +655,24 @@ */ typedef struct ForeachInfo { int numLists; /* The number of both the variable and value * lists of the foreach command. */ - int firstListTmp; /* The slot number of the first temporary - * variable holding the lists themselves. */ - int loopIterNumTmp; /* The slot number of the temp var holding - * the count of times the loop body has been - * executed. This is used to determine which - * list element to assign each loop var. */ + 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; + +extern AuxDataType tclForeachInfoType; /* * 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 @@ -734,143 +713,153 @@ * modules but not used outside: *---------------------------------------------------------------- */ EXTERN void TclCleanupByteCode _ANSI_ARGS_((ByteCode *codePtr)); -EXTERN int TclCompileExpr _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int flags, - CompileEnv *envPtr)); -EXTERN int TclCompileQuotes _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int termChar, - int flags, CompileEnv *envPtr)); -EXTERN int TclCompileString _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int flags, - CompileEnv *envPtr)); -EXTERN int TclCompileDollarVar _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int flags, - CompileEnv *envPtr)); -EXTERN int TclCreateAuxData _ANSI_ARGS_(( - ClientData clientData, AuxDataDupProc *dupProc, - AuxDataFreeProc *freeProc, CompileEnv *envPtr)); +EXTERN int TclCompileCmdWord _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Token *tokenPtr, int count, + CompileEnv *envPtr)); +EXTERN int TclCompileExpr _ANSI_ARGS_((Tcl_Interp *interp, + char *script, int numBytes, + CompileEnv *envPtr)); +EXTERN int TclCompileExprWords _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Token *tokenPtr, int numWords, + CompileEnv *envPtr)); +EXTERN int TclCompileScript _ANSI_ARGS_((Tcl_Interp *interp, + char *script, int numBytes, int nested, + CompileEnv *envPtr)); +EXTERN int TclCompileTokens _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Token *tokenPtr, int count, + CompileEnv *envPtr)); +EXTERN int TclCreateAuxData _ANSI_ARGS_((ClientData clientData, + AuxDataType *typePtr, CompileEnv *envPtr)); +EXTERN int TclCreateExceptRange _ANSI_ARGS_(( + ExceptionRangeType type, CompileEnv *envPtr)); EXTERN ExecEnv * TclCreateExecEnv _ANSI_ARGS_((Tcl_Interp *interp)); EXTERN void TclDeleteExecEnv _ANSI_ARGS_((ExecEnv *eePtr)); +EXTERN void TclDeleteLiteralTable _ANSI_ARGS_(( + Tcl_Interp *interp, LiteralTable *tablePtr)); EXTERN void TclEmitForwardJump _ANSI_ARGS_((CompileEnv *envPtr, TclJumpType jumpType, JumpFixup *jumpFixupPtr)); +EXTERN AuxDataType *TclGetAuxDataType _ANSI_ARGS_((char *typeName)); EXTERN ExceptionRange * TclGetExceptionRangeForPc _ANSI_ARGS_(( unsigned char *pc, int catchOnly, ByteCode* codePtr)); +EXTERN InstructionDesc * TclGetInstructionTable _ANSI_ARGS_(()); EXTERN int TclExecuteByteCode _ANSI_ARGS_((Tcl_Interp *interp, ByteCode *codePtr)); EXTERN void TclExpandCodeArray _ANSI_ARGS_(( - CompileEnv *envPtr)); + CompileEnv *envPtr)); EXTERN void TclExpandJumpFixupArray _ANSI_ARGS_(( JumpFixupArray *fixupArrayPtr)); +EXTERN void TclFinalizeAuxDataTypeTable _ANSI_ARGS_((void)); +EXTERN int TclFindCompiledLocal _ANSI_ARGS_((char *name, + int nameChars, int create, int flags, + Proc *procPtr)); +EXTERN LiteralEntry * TclLookupLiteralEntry _ANSI_ARGS_(( + Tcl_Interp *interp, Tcl_Obj *objPtr)); EXTERN int TclFixupForwardJump _ANSI_ARGS_(( CompileEnv *envPtr, JumpFixup *jumpFixupPtr, int jumpDist, int distThreshold)); EXTERN void TclFreeCompileEnv _ANSI_ARGS_((CompileEnv *envPtr)); EXTERN void TclFreeJumpFixupArray _ANSI_ARGS_(( JumpFixupArray *fixupArrayPtr)); +EXTERN void TclInitAuxDataTypeTable _ANSI_ARGS_((void)); EXTERN void TclInitByteCodeObj _ANSI_ARGS_((Tcl_Obj *objPtr, CompileEnv *envPtr)); +EXTERN void TclInitCompilation _ANSI_ARGS_((void)); EXTERN void TclInitCompileEnv _ANSI_ARGS_((Tcl_Interp *interp, - CompileEnv *envPtr, char *string)); + CompileEnv *envPtr, char *string, + int numBytes)); EXTERN void TclInitJumpFixupArray _ANSI_ARGS_(( JumpFixupArray *fixupArrayPtr)); +EXTERN void TclInitLiteralTable _ANSI_ARGS_(( + LiteralTable *tablePtr)); #ifdef TCL_COMPILE_STATS +EXTERN char * TclLiteralStats _ANSI_ARGS_(( + LiteralTable *tablePtr)); EXTERN int TclLog2 _ANSI_ARGS_((int value)); -#endif /*TCL_COMPILE_STATS*/ -EXTERN int TclObjIndexForString _ANSI_ARGS_((char *start, - int length, int allocStrRep, int inHeap, - CompileEnv *envPtr)); +#endif +#ifdef TCL_COMPILE_DEBUG +EXTERN void TclPrintByteCodeObj _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *objPtr)); +#endif EXTERN int TclPrintInstruction _ANSI_ARGS_((ByteCode* codePtr, unsigned char *pc)); +EXTERN void TclPrintObject _ANSI_ARGS_((FILE *outFile, + Tcl_Obj *objPtr, int maxChars)); EXTERN void TclPrintSource _ANSI_ARGS_((FILE *outFile, char *string, int maxChars)); +EXTERN void TclRegisterAuxDataType _ANSI_ARGS_((AuxDataType *typePtr)); +EXTERN int TclRegisterLiteral _ANSI_ARGS_((CompileEnv *envPtr, + char *bytes, int length, int onHeap)); +EXTERN void TclReleaseLiteral _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *objPtr)); +EXTERN void TclSetCmdNameObj _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *objPtr, Command *cmdPtr)); +#ifdef TCL_COMPILE_DEBUG +EXTERN void TclVerifyGlobalLiteralTable _ANSI_ARGS_(( + Interp *iPtr)); +EXTERN void TclVerifyLocalLiteralTable _ANSI_ARGS_(( + CompileEnv *envPtr)); +#endif /* *---------------------------------------------------------------- * Macros used by Tcl bytecode compilation and execution modules * inside the Tcl core but not used outside. *---------------------------------------------------------------- */ -/* - * Macros to ensure there is enough room in a CompileEnv's code array. - * The ANSI C "prototypes" for these macros are: - * - * EXTERN void TclEnsureCodeSpace1 _ANSI_ARGS_((CompileEnv *envPtr)); - * EXTERN void TclEnsureCodeSpace _ANSI_ARGS_((int nBytes, - * CompileEnv *envPtr)); - */ - -#define TclEnsureCodeSpace1(envPtr) \ - if ((envPtr)->codeNext == (envPtr)->codeEnd) \ - TclExpandCodeArray(envPtr) - -#define TclEnsureCodeSpace(nBytes, envPtr) \ - if (((envPtr)->codeNext + nBytes) > (envPtr)->codeEnd) \ - TclExpandCodeArray(envPtr) - /* * Macro to emit an opcode byte into a CompileEnv's code array. * The ANSI C "prototype" for this macro is: * * EXTERN void TclEmitOpcode _ANSI_ARGS_((unsigned char op, * CompileEnv *envPtr)); */ #define TclEmitOpcode(op, envPtr) \ - TclEnsureCodeSpace1(envPtr); \ + if ((envPtr)->codeNext == (envPtr)->codeEnd) \ + TclExpandCodeArray(envPtr); \ *(envPtr)->codeNext++ = (unsigned char) (op) /* - * Macros to emit a (signed or unsigned) int operand. The two variants - * depend on the number of bytes needed for the int. 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: + * Macro to emit an integer operand. + * The ANSI C "prototype" for this macro is: * * EXTERN void TclEmitInt1 _ANSI_ARGS_((int i, CompileEnv *envPtr)); - * EXTERN void TclEmitInt4 _ANSI_ARGS_((int i, CompileEnv *envPtr)); */ #define TclEmitInt1(i, envPtr) \ - TclEnsureCodeSpace(1, (envPtr)); \ + if ((envPtr)->codeNext == (envPtr)->codeEnd) \ + TclExpandCodeArray(envPtr); \ *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i)) -#define TclEmitInt4(i, envPtr) \ - TclEnsureCodeSpace(4, (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) ) - /* - * Macros to emit an instruction with signed or unsigned int operands. + * 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: * * EXTERN void TclEmitInstInt1 _ANSI_ARGS_((unsigned char op, int i, * CompileEnv *envPtr)); * EXTERN void TclEmitInstInt4 _ANSI_ARGS_((unsigned char op, int i, * CompileEnv *envPtr)); - * EXTERN void TclEmitInstUInt1 _ANSI_ARGS_((unsigned char op, - * unsigned int i, CompileEnv *envPtr)); - * EXTERN void TclEmitInstUInt4 _ANSI_ARGS_((unsigned char op, - * unsigned int i, CompileEnv *envPtr)); */ #define TclEmitInstInt1(op, i, envPtr) \ - TclEnsureCodeSpace(2, (envPtr)); \ + if (((envPtr)->codeNext + 2) > (envPtr)->codeEnd) { \ + TclExpandCodeArray(envPtr); \ + } \ *(envPtr)->codeNext++ = (unsigned char) (op); \ *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i)) #define TclEmitInstInt4(op, i, envPtr) \ - TclEnsureCodeSpace(5, (envPtr)); \ + 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); \ @@ -877,16 +866,10 @@ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) >> 8); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) ) -#define TclEmitInstUInt1(op, i, envPtr) \ - TclEmitInstInt1((op), (i), (envPtr)) - -#define TclEmitInstUInt4(op, i, envPtr) \ - TclEmitInstInt4((op), (i), (envPtr)) - /* * 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: @@ -894,13 +877,13 @@ * EXTERN void TclEmitPush _ANSI_ARGS_((int objIndex, CompileEnv *envPtr)); */ #define TclEmitPush(objIndex, envPtr) \ if ((objIndex) <= 255) { \ - TclEmitInstUInt1(INST_PUSH1, (objIndex), (envPtr)); \ + TclEmitInstInt1(INST_PUSH1, (objIndex), (envPtr)); \ } else { \ - TclEmitInstUInt4(INST_PUSH4, (objIndex), (envPtr)); \ + TclEmitInstInt4(INST_PUSH4, (objIndex), (envPtr)); \ } /* * 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" @@ -990,23 +973,9 @@ */ #define TclMin(i, j) ((((int) i) < ((int) j))? (i) : (j)) #define TclMax(i, j) ((((int) i) > ((int) j))? (i) : (j)) -/* - * Macro used to compute the offset of the current instruction in the - * bytecode instruction stream. The ANSI C "prototypes" for this macro is: - * - * EXTERN int TclCurrCodeOffset _ANSI_ARGS_((void)); - */ - -#define TclCurrCodeOffset() ((envPtr)->codeNext - (envPtr)->codeStart) - -/* - * Upper bound for legal jump distances. Checked during compilation if - * debugging. - */ - -#define MAX_JUMP_DIST 5000 +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT #endif /* _TCLCOMPILATION */ - Index: generic/tclDate.c ================================================================== --- generic/tclDate.c +++ generic/tclDate.c @@ -8,11 +8,11 @@ * 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. * - * @(#) tclDate.c 1.32 97/02/03 14:54:37 + * RCS: @(#) $Id: tclDate.c,v 1.1.2.3 1999/03/10 06:49:15 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" @@ -439,11 +439,11 @@ Julian += TclDateTimezone * 60L; if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0) return -1; Julian += tod; if (DSTmode == DSTon - || (DSTmode == DSTmaybe && TclpGetDate(&Julian, 0)->tm_isdst)) + || (DSTmode == DSTmaybe && TclpGetDate((TclpTime_t)&Julian, 0)->tm_isdst)) Julian -= 60 * 60; *TimePtr = Julian; return 0; } @@ -454,12 +454,12 @@ time_t Future; { time_t StartDay; time_t FutureDay; - StartDay = (TclpGetDate(&Start, 0)->tm_hour + 1) % 24; - FutureDay = (TclpGetDate(&Future, 0)->tm_hour + 1) % 24; + StartDay = (TclpGetDate((TclpTime_t)&Start, 0)->tm_hour + 1) % 24; + FutureDay = (TclpGetDate((TclpTime_t)&Future, 0)->tm_hour + 1) % 24; return (Future - Start) + (StartDay - FutureDay) * 60L * 60L; } static time_t @@ -470,11 +470,11 @@ { struct tm *tm; time_t now; now = Start; - tm = TclpGetDate(&now, 0); + tm = TclpGetDate((TclpTime_t)&now, 0); now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7); now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1); return DSTcorrect(Start, now); } @@ -493,11 +493,11 @@ if (RelMonth == 0) { *TimePtr = 0; return 0; } - tm = TclpGetDate(&Start, 0); + tm = TclpGetDate((TclpTime_t)&Start, 0); Month = 12 * (tm->tm_year + TM_YEAR_BASE) + tm->tm_mon + RelMonth; Year = Month / 12; Month = Month % 12 + 1; result = Convert(Month, (time_t) tm->tm_mday, Year, (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec, @@ -535,15 +535,12 @@ int abbrev; /* * Make it lowercase. */ - for (p = buff; *p; p++) { - if (isupper(UCHAR(*p))) { - *p = (char) tolower(UCHAR(*p)); - } - } + + Tcl_UtfToLower(buff); if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) { TclDatelval.Meridian = MERam; return tMERIDIAN; } @@ -612,11 +609,12 @@ } /* * Military timezones. */ - if (buff[1] == '\0' && isalpha(UCHAR(*buff))) { + if (buff[1] == '\0' && !(*buff & 0x80) + && isalpha(UCHAR(*buff))) { /* INTL: ISO only */ for (tp = MilitaryTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { TclDatelval.Number = tp->value; return tp->type; } @@ -658,33 +656,35 @@ for ( ; ; ) { while (isspace((unsigned char) (*TclDateInput))) { TclDateInput++; } - if (isdigit(c = *TclDateInput) || c == '-' || c == '+') { + if (isdigit(c = *TclDateInput) || c == '-' || c == '+') { /* INTL: digit */ if (c == '-' || c == '+') { sign = c == '-' ? -1 : 1; - if (!isdigit(*++TclDateInput)) { + if (!isdigit(*++TclDateInput)) { /* INTL: digit */ /* * skip the '-' sign */ continue; } } else { sign = 0; } - for (TclDatelval.Number = 0; isdigit(c = *TclDateInput++); ) { + for (TclDatelval.Number = 0; + isdigit(c = *TclDateInput++); ) { /* INTL: digit */ TclDatelval.Number = 10 * TclDatelval.Number + c - '0'; } TclDateInput--; if (sign < 0) { TclDatelval.Number = -TclDatelval.Number; } return sign ? tSNUMBER : tUNUMBER; } - if (isalpha(UCHAR(c))) { - for (p = buff; isalpha(c = *TclDateInput++) || c == '.'; ) { + if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */ + for (p = buff; isalpha(c = *TclDateInput++) /* INTL: ISO only. */ + || c == '.'; ) { if (p < &buff[sizeof buff - 1]) { *p++ = c; } } *p = '\0'; @@ -724,11 +724,11 @@ time_t Time; time_t tod; int thisyear; TclDateInput = p; - tm = TclpGetDate((time_t *) &now, 0); + tm = TclpGetDate((TclpTime_t) &now, 0); thisyear = tm->tm_year + TM_YEAR_BASE; TclDateYear = thisyear; TclDateMonth = tm->tm_mon + 1; TclDateDay = tm->tm_mday; TclDateTimezone = zone; ADDED generic/tclDecls.h Index: generic/tclDecls.h ================================================================== --- /dev/null +++ generic/tclDecls.h @@ -0,0 +1,2995 @@ +/* + * 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. + * + * RCS: @(#) $Id: tclDecls.h,v 1.3.2.16 1999/04/06 03:13:13 redman Exp $ + */ + +#ifndef _TCLDECLS +#define _TCLDECLS + +/* + * 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. */ + +/* + * Exported function declarations: + */ + +/* 0 */ +EXTERN int Tcl_PkgProvideEx _ANSI_ARGS_((Tcl_Interp * interp, + char * name, char * version, + ClientData clientData)); +/* 1 */ +EXTERN char * Tcl_PkgRequireEx _ANSI_ARGS_((Tcl_Interp * interp, + char * name, char * version, int exact, + ClientData * clientDataPtr)); +/* 2 */ +EXTERN void Tcl_Panic _ANSI_ARGS_(TCL_VARARGS(char *,format)); +/* 3 */ +EXTERN char * Tcl_Alloc _ANSI_ARGS_((unsigned int size)); +/* 4 */ +EXTERN void Tcl_Free _ANSI_ARGS_((char * ptr)); +/* 5 */ +EXTERN char * Tcl_Realloc _ANSI_ARGS_((char * ptr, + unsigned int size)); +/* 6 */ +EXTERN char * Tcl_DbCkalloc _ANSI_ARGS_((unsigned int size, + char * file, int line)); +/* 7 */ +EXTERN int Tcl_DbCkfree _ANSI_ARGS_((char * ptr, char * file, + int line)); +/* 8 */ +EXTERN char * Tcl_DbCkrealloc _ANSI_ARGS_((char * ptr, + unsigned int size, char * file, int line)); +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 9 */ +EXTERN void Tcl_CreateFileHandler _ANSI_ARGS_((int fd, int mask, + Tcl_FileProc * proc, ClientData clientData)); +#endif /* UNIX */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 10 */ +EXTERN void Tcl_DeleteFileHandler _ANSI_ARGS_((int fd)); +#endif /* UNIX */ +/* 11 */ +EXTERN void Tcl_SetTimer _ANSI_ARGS_((Tcl_Time * timePtr)); +/* 12 */ +EXTERN void Tcl_Sleep _ANSI_ARGS_((int ms)); +/* 13 */ +EXTERN int Tcl_WaitForEvent _ANSI_ARGS_((Tcl_Time * timePtr)); +/* 14 */ +EXTERN int Tcl_AppendAllObjTypes _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr)); +/* 15 */ +EXTERN void Tcl_AppendStringsToObj _ANSI_ARGS_(TCL_VARARGS(Tcl_Obj *,objPtr)); +/* 16 */ +EXTERN void Tcl_AppendToObj _ANSI_ARGS_((Tcl_Obj * objPtr, + char * bytes, int length)); +/* 17 */ +EXTERN Tcl_Obj * Tcl_ConcatObj _ANSI_ARGS_((int objc, + Tcl_Obj *CONST objv[])); +/* 18 */ +EXTERN int Tcl_ConvertToType _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, Tcl_ObjType * typePtr)); +/* 19 */ +EXTERN void Tcl_DbDecrRefCount _ANSI_ARGS_((Tcl_Obj * objPtr, + char * file, int line)); +/* 20 */ +EXTERN void Tcl_DbIncrRefCount _ANSI_ARGS_((Tcl_Obj * objPtr, + char * file, int line)); +/* 21 */ +EXTERN int Tcl_DbIsShared _ANSI_ARGS_((Tcl_Obj * objPtr, + char * file, int line)); +/* 22 */ +EXTERN Tcl_Obj * Tcl_DbNewBooleanObj _ANSI_ARGS_((int boolValue, + char * file, int line)); +/* 23 */ +EXTERN Tcl_Obj * Tcl_DbNewByteArrayObj _ANSI_ARGS_(( + unsigned char * bytes, int length, + char * file, int line)); +/* 24 */ +EXTERN Tcl_Obj * Tcl_DbNewDoubleObj _ANSI_ARGS_((double doubleValue, + char * file, int line)); +/* 25 */ +EXTERN Tcl_Obj * Tcl_DbNewListObj _ANSI_ARGS_((int objc, + Tcl_Obj *CONST objv[], char * file, int line)); +/* 26 */ +EXTERN Tcl_Obj * Tcl_DbNewLongObj _ANSI_ARGS_((long longValue, + char * file, int line)); +/* 27 */ +EXTERN Tcl_Obj * Tcl_DbNewObj _ANSI_ARGS_((char * file, int line)); +/* 28 */ +EXTERN Tcl_Obj * Tcl_DbNewStringObj _ANSI_ARGS_((CONST char * bytes, + int length, char * file, int line)); +/* 29 */ +EXTERN Tcl_Obj * Tcl_DuplicateObj _ANSI_ARGS_((Tcl_Obj * objPtr)); +/* 30 */ +EXTERN void TclFreeObj _ANSI_ARGS_((Tcl_Obj * objPtr)); +/* 31 */ +EXTERN int Tcl_GetBoolean _ANSI_ARGS_((Tcl_Interp * interp, + char * str, int * boolPtr)); +/* 32 */ +EXTERN int Tcl_GetBooleanFromObj _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr, + int * boolPtr)); +/* 33 */ +EXTERN unsigned char * Tcl_GetByteArrayFromObj _ANSI_ARGS_(( + Tcl_Obj * objPtr, int * lengthPtr)); +/* 34 */ +EXTERN int Tcl_GetDouble _ANSI_ARGS_((Tcl_Interp * interp, + char * str, double * doublePtr)); +/* 35 */ +EXTERN int Tcl_GetDoubleFromObj _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr, + double * doublePtr)); +/* 36 */ +EXTERN int Tcl_GetIndexFromObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, char ** tablePtr, + char * msg, int flags, int * indexPtr)); +/* 37 */ +EXTERN int Tcl_GetInt _ANSI_ARGS_((Tcl_Interp * interp, + char * str, int * intPtr)); +/* 38 */ +EXTERN int Tcl_GetIntFromObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, int * intPtr)); +/* 39 */ +EXTERN int Tcl_GetLongFromObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, long * longPtr)); +/* 40 */ +EXTERN Tcl_ObjType * Tcl_GetObjType _ANSI_ARGS_((char * typeName)); +/* 41 */ +EXTERN char * Tcl_GetStringFromObj _ANSI_ARGS_((Tcl_Obj * objPtr, + int * lengthPtr)); +/* 42 */ +EXTERN void Tcl_InvalidateStringRep _ANSI_ARGS_(( + Tcl_Obj * objPtr)); +/* 43 */ +EXTERN int Tcl_ListObjAppendList _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * listPtr, + Tcl_Obj * elemListPtr)); +/* 44 */ +EXTERN int Tcl_ListObjAppendElement _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * listPtr, + Tcl_Obj * objPtr)); +/* 45 */ +EXTERN int Tcl_ListObjGetElements _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * listPtr, + int * objcPtr, Tcl_Obj *** objvPtr)); +/* 46 */ +EXTERN int Tcl_ListObjIndex _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * listPtr, int index, + Tcl_Obj ** objPtrPtr)); +/* 47 */ +EXTERN int Tcl_ListObjLength _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * listPtr, int * intPtr)); +/* 48 */ +EXTERN int Tcl_ListObjReplace _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * listPtr, int first, int count, + int objc, Tcl_Obj *CONST objv[])); +/* 49 */ +EXTERN Tcl_Obj * Tcl_NewBooleanObj _ANSI_ARGS_((int boolValue)); +/* 50 */ +EXTERN Tcl_Obj * Tcl_NewByteArrayObj _ANSI_ARGS_(( + unsigned char * bytes, int length)); +/* 51 */ +EXTERN Tcl_Obj * Tcl_NewDoubleObj _ANSI_ARGS_((double doubleValue)); +/* 52 */ +EXTERN Tcl_Obj * Tcl_NewIntObj _ANSI_ARGS_((int intValue)); +/* 53 */ +EXTERN Tcl_Obj * Tcl_NewListObj _ANSI_ARGS_((int objc, + Tcl_Obj *CONST objv[])); +/* 54 */ +EXTERN Tcl_Obj * Tcl_NewLongObj _ANSI_ARGS_((long longValue)); +/* 55 */ +EXTERN Tcl_Obj * Tcl_NewObj _ANSI_ARGS_((void)); +/* 56 */ +EXTERN Tcl_Obj * Tcl_NewStringObj _ANSI_ARGS_((CONST char * bytes, + int length)); +/* 57 */ +EXTERN void Tcl_SetBooleanObj _ANSI_ARGS_((Tcl_Obj * objPtr, + int boolValue)); +/* 58 */ +EXTERN unsigned char * Tcl_SetByteArrayLength _ANSI_ARGS_((Tcl_Obj * objPtr, + int length)); +/* 59 */ +EXTERN void Tcl_SetByteArrayObj _ANSI_ARGS_((Tcl_Obj * objPtr, + unsigned char * bytes, int length)); +/* 60 */ +EXTERN void Tcl_SetDoubleObj _ANSI_ARGS_((Tcl_Obj * objPtr, + double doubleValue)); +/* 61 */ +EXTERN void Tcl_SetIntObj _ANSI_ARGS_((Tcl_Obj * objPtr, + int intValue)); +/* 62 */ +EXTERN void Tcl_SetListObj _ANSI_ARGS_((Tcl_Obj * objPtr, + int objc, Tcl_Obj *CONST objv[])); +/* 63 */ +EXTERN void Tcl_SetLongObj _ANSI_ARGS_((Tcl_Obj * objPtr, + long longValue)); +/* 64 */ +EXTERN void Tcl_SetObjLength _ANSI_ARGS_((Tcl_Obj * objPtr, + int length)); +/* 65 */ +EXTERN void Tcl_SetStringObj _ANSI_ARGS_((Tcl_Obj * objPtr, + char * bytes, int length)); +/* 66 */ +EXTERN void Tcl_AddErrorInfo _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * message)); +/* 67 */ +EXTERN void Tcl_AddObjErrorInfo _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * message, int length)); +/* 68 */ +EXTERN void Tcl_AllowExceptions _ANSI_ARGS_((Tcl_Interp * interp)); +/* 69 */ +EXTERN void Tcl_AppendElement _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * string)); +/* 70 */ +EXTERN void Tcl_AppendResult _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); +/* 71 */ +EXTERN Tcl_AsyncHandler Tcl_AsyncCreate _ANSI_ARGS_((Tcl_AsyncProc * proc, + ClientData clientData)); +/* 72 */ +EXTERN void Tcl_AsyncDelete _ANSI_ARGS_((Tcl_AsyncHandler async)); +/* 73 */ +EXTERN int Tcl_AsyncInvoke _ANSI_ARGS_((Tcl_Interp * interp, + int code)); +/* 74 */ +EXTERN void Tcl_AsyncMark _ANSI_ARGS_((Tcl_AsyncHandler async)); +/* 75 */ +EXTERN int Tcl_AsyncReady _ANSI_ARGS_((void)); +/* 76 */ +EXTERN void Tcl_BackgroundError _ANSI_ARGS_((Tcl_Interp * interp)); +/* 77 */ +EXTERN char Tcl_Backslash _ANSI_ARGS_((CONST char * src, + int * readPtr)); +/* 78 */ +EXTERN int Tcl_BadChannelOption _ANSI_ARGS_(( + Tcl_Interp * interp, char * optionName, + char * optionList)); +/* 79 */ +EXTERN void Tcl_CallWhenDeleted _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_InterpDeleteProc * proc, + ClientData clientData)); +/* 80 */ +EXTERN void Tcl_CancelIdleCall _ANSI_ARGS_(( + Tcl_IdleProc * idleProc, + ClientData clientData)); +/* 81 */ +EXTERN int Tcl_Close _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Channel chan)); +/* 82 */ +EXTERN int Tcl_CommandComplete _ANSI_ARGS_((char * cmd)); +/* 83 */ +EXTERN char * Tcl_Concat _ANSI_ARGS_((int argc, char ** argv)); +/* 84 */ +EXTERN int Tcl_ConvertElement _ANSI_ARGS_((CONST char * src, + char * dst, int flags)); +/* 85 */ +EXTERN int Tcl_ConvertCountedElement _ANSI_ARGS_(( + CONST char * src, int length, char * dst, + int flags)); +/* 86 */ +EXTERN int Tcl_CreateAlias _ANSI_ARGS_((Tcl_Interp * slave, + char * slaveCmd, Tcl_Interp * target, + char * targetCmd, int argc, char ** argv)); +/* 87 */ +EXTERN int Tcl_CreateAliasObj _ANSI_ARGS_((Tcl_Interp * slave, + char * slaveCmd, Tcl_Interp * target, + char * targetCmd, int objc, + Tcl_Obj *CONST objv[])); +/* 88 */ +EXTERN Tcl_Channel Tcl_CreateChannel _ANSI_ARGS_(( + Tcl_ChannelType * typePtr, char * chanName, + ClientData instanceData, int mask)); +/* 89 */ +EXTERN void Tcl_CreateChannelHandler _ANSI_ARGS_(( + Tcl_Channel chan, int mask, + Tcl_ChannelProc * proc, + ClientData clientData)); +/* 90 */ +EXTERN void Tcl_CreateCloseHandler _ANSI_ARGS_((Tcl_Channel chan, + Tcl_CloseProc * proc, ClientData clientData)); +/* 91 */ +EXTERN Tcl_Command Tcl_CreateCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * cmdName, Tcl_CmdProc * proc, + ClientData clientData, + Tcl_CmdDeleteProc * deleteProc)); +/* 92 */ +EXTERN void Tcl_CreateEventSource _ANSI_ARGS_(( + Tcl_EventSetupProc * setupProc, + Tcl_EventCheckProc * checkProc, + ClientData clientData)); +/* 93 */ +EXTERN void Tcl_CreateExitHandler _ANSI_ARGS_(( + Tcl_ExitProc * proc, ClientData clientData)); +/* 94 */ +EXTERN Tcl_Interp * Tcl_CreateInterp _ANSI_ARGS_((void)); +/* 95 */ +EXTERN void Tcl_CreateMathFunc _ANSI_ARGS_((Tcl_Interp * interp, + char * name, int numArgs, + Tcl_ValueType * argTypes, + Tcl_MathProc * proc, ClientData clientData)); +/* 96 */ +EXTERN Tcl_Command Tcl_CreateObjCommand _ANSI_ARGS_(( + Tcl_Interp * interp, char * cmdName, + Tcl_ObjCmdProc * proc, ClientData clientData, + Tcl_CmdDeleteProc * deleteProc)); +/* 97 */ +EXTERN Tcl_Interp * Tcl_CreateSlave _ANSI_ARGS_((Tcl_Interp * interp, + char * slaveName, int isSafe)); +/* 98 */ +EXTERN Tcl_TimerToken Tcl_CreateTimerHandler _ANSI_ARGS_((int milliseconds, + Tcl_TimerProc * proc, ClientData clientData)); +/* 99 */ +EXTERN Tcl_Trace Tcl_CreateTrace _ANSI_ARGS_((Tcl_Interp * interp, + int level, Tcl_CmdTraceProc * proc, + ClientData clientData)); +/* 100 */ +EXTERN void Tcl_DeleteAssocData _ANSI_ARGS_((Tcl_Interp * interp, + char * name)); +/* 101 */ +EXTERN void Tcl_DeleteChannelHandler _ANSI_ARGS_(( + Tcl_Channel chan, Tcl_ChannelProc * proc, + ClientData clientData)); +/* 102 */ +EXTERN void Tcl_DeleteCloseHandler _ANSI_ARGS_((Tcl_Channel chan, + Tcl_CloseProc * proc, ClientData clientData)); +/* 103 */ +EXTERN int Tcl_DeleteCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * cmdName)); +/* 104 */ +EXTERN int Tcl_DeleteCommandFromToken _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Command command)); +/* 105 */ +EXTERN void Tcl_DeleteEvents _ANSI_ARGS_(( + Tcl_EventDeleteProc * proc, + ClientData clientData)); +/* 106 */ +EXTERN void Tcl_DeleteEventSource _ANSI_ARGS_(( + Tcl_EventSetupProc * setupProc, + Tcl_EventCheckProc * checkProc, + ClientData clientData)); +/* 107 */ +EXTERN void Tcl_DeleteExitHandler _ANSI_ARGS_(( + Tcl_ExitProc * proc, ClientData clientData)); +/* 108 */ +EXTERN void Tcl_DeleteHashEntry _ANSI_ARGS_(( + Tcl_HashEntry * entryPtr)); +/* 109 */ +EXTERN void Tcl_DeleteHashTable _ANSI_ARGS_(( + Tcl_HashTable * tablePtr)); +/* 110 */ +EXTERN void Tcl_DeleteInterp _ANSI_ARGS_((Tcl_Interp * interp)); +/* 111 */ +EXTERN void Tcl_DetachPids _ANSI_ARGS_((int numPids, + Tcl_Pid * pidPtr)); +/* 112 */ +EXTERN void Tcl_DeleteTimerHandler _ANSI_ARGS_(( + Tcl_TimerToken token)); +/* 113 */ +EXTERN void Tcl_DeleteTrace _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Trace trace)); +/* 114 */ +EXTERN void Tcl_DontCallWhenDeleted _ANSI_ARGS_(( + Tcl_Interp * interp, + Tcl_InterpDeleteProc * proc, + ClientData clientData)); +/* 115 */ +EXTERN int Tcl_DoOneEvent _ANSI_ARGS_((int flags)); +/* 116 */ +EXTERN void Tcl_DoWhenIdle _ANSI_ARGS_((Tcl_IdleProc * proc, + ClientData clientData)); +/* 117 */ +EXTERN char * Tcl_DStringAppend _ANSI_ARGS_((Tcl_DString * dsPtr, + CONST char * str, int length)); +/* 118 */ +EXTERN char * Tcl_DStringAppendElement _ANSI_ARGS_(( + Tcl_DString * dsPtr, CONST char * string)); +/* 119 */ +EXTERN void Tcl_DStringEndSublist _ANSI_ARGS_(( + Tcl_DString * dsPtr)); +/* 120 */ +EXTERN void Tcl_DStringFree _ANSI_ARGS_((Tcl_DString * dsPtr)); +/* 121 */ +EXTERN void Tcl_DStringGetResult _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_DString * dsPtr)); +/* 122 */ +EXTERN void Tcl_DStringInit _ANSI_ARGS_((Tcl_DString * dsPtr)); +/* 123 */ +EXTERN void Tcl_DStringResult _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_DString * dsPtr)); +/* 124 */ +EXTERN void Tcl_DStringSetLength _ANSI_ARGS_(( + Tcl_DString * dsPtr, int length)); +/* 125 */ +EXTERN void Tcl_DStringStartSublist _ANSI_ARGS_(( + Tcl_DString * dsPtr)); +/* 126 */ +EXTERN int Tcl_Eof _ANSI_ARGS_((Tcl_Channel chan)); +/* 127 */ +EXTERN char * Tcl_ErrnoId _ANSI_ARGS_((void)); +/* 128 */ +EXTERN char * Tcl_ErrnoMsg _ANSI_ARGS_((int err)); +/* 129 */ +EXTERN int Tcl_Eval _ANSI_ARGS_((Tcl_Interp * interp, + char * string)); +/* 130 */ +EXTERN int Tcl_EvalFile _ANSI_ARGS_((Tcl_Interp * interp, + char * fileName)); +/* 131 */ +EXTERN int Tcl_EvalObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr)); +/* 132 */ +EXTERN void Tcl_EventuallyFree _ANSI_ARGS_(( + ClientData clientData, + Tcl_FreeProc * freeProc)); +/* 133 */ +EXTERN void Tcl_Exit _ANSI_ARGS_((int status)); +/* 134 */ +EXTERN int Tcl_ExposeCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * hiddenCmdToken, char * cmdName)); +/* 135 */ +EXTERN int Tcl_ExprBoolean _ANSI_ARGS_((Tcl_Interp * interp, + char * str, int * ptr)); +/* 136 */ +EXTERN int Tcl_ExprBooleanObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, int * ptr)); +/* 137 */ +EXTERN int Tcl_ExprDouble _ANSI_ARGS_((Tcl_Interp * interp, + char * str, double * ptr)); +/* 138 */ +EXTERN int Tcl_ExprDoubleObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, double * ptr)); +/* 139 */ +EXTERN int Tcl_ExprLong _ANSI_ARGS_((Tcl_Interp * interp, + char * str, long * ptr)); +/* 140 */ +EXTERN int Tcl_ExprLongObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, long * ptr)); +/* 141 */ +EXTERN int Tcl_ExprObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, Tcl_Obj ** resultPtrPtr)); +/* 142 */ +EXTERN int Tcl_ExprString _ANSI_ARGS_((Tcl_Interp * interp, + char * string)); +/* 143 */ +EXTERN void Tcl_Finalize _ANSI_ARGS_((void)); +/* 144 */ +EXTERN void Tcl_FindExecutable _ANSI_ARGS_((CONST char * argv0)); +/* 145 */ +EXTERN Tcl_HashEntry * Tcl_FirstHashEntry _ANSI_ARGS_(( + Tcl_HashTable * tablePtr, + Tcl_HashSearch * searchPtr)); +/* 146 */ +EXTERN int Tcl_Flush _ANSI_ARGS_((Tcl_Channel chan)); +/* 147 */ +EXTERN void Tcl_FreeResult _ANSI_ARGS_((Tcl_Interp * interp)); +/* 148 */ +EXTERN int Tcl_GetAlias _ANSI_ARGS_((Tcl_Interp * interp, + char * slaveCmd, + Tcl_Interp ** targetInterpPtr, + char ** targetCmdPtr, int * argcPtr, + char *** argvPtr)); +/* 149 */ +EXTERN int Tcl_GetAliasObj _ANSI_ARGS_((Tcl_Interp * interp, + char * slaveCmd, + Tcl_Interp ** targetInterpPtr, + char ** targetCmdPtr, int * objcPtr, + Tcl_Obj *** objv)); +/* 150 */ +EXTERN ClientData Tcl_GetAssocData _ANSI_ARGS_((Tcl_Interp * interp, + char * name, Tcl_InterpDeleteProc ** procPtr)); +/* 151 */ +EXTERN Tcl_Channel Tcl_GetChannel _ANSI_ARGS_((Tcl_Interp * interp, + char * chanName, int * modePtr)); +/* 152 */ +EXTERN int Tcl_GetChannelBufferSize _ANSI_ARGS_(( + Tcl_Channel chan)); +/* 153 */ +EXTERN int Tcl_GetChannelHandle _ANSI_ARGS_((Tcl_Channel chan, + int direction, ClientData * handlePtr)); +/* 154 */ +EXTERN ClientData Tcl_GetChannelInstanceData _ANSI_ARGS_(( + Tcl_Channel chan)); +/* 155 */ +EXTERN int Tcl_GetChannelMode _ANSI_ARGS_((Tcl_Channel chan)); +/* 156 */ +EXTERN char * Tcl_GetChannelName _ANSI_ARGS_((Tcl_Channel chan)); +/* 157 */ +EXTERN int Tcl_GetChannelOption _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Channel chan, + char * optionName, Tcl_DString * dsPtr)); +/* 158 */ +EXTERN Tcl_ChannelType * Tcl_GetChannelType _ANSI_ARGS_((Tcl_Channel chan)); +/* 159 */ +EXTERN int Tcl_GetCommandInfo _ANSI_ARGS_((Tcl_Interp * interp, + char * cmdName, Tcl_CmdInfo * infoPtr)); +/* 160 */ +EXTERN char * Tcl_GetCommandName _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Command command)); +/* 161 */ +EXTERN int Tcl_GetErrno _ANSI_ARGS_((void)); +/* 162 */ +EXTERN char * Tcl_GetHostName _ANSI_ARGS_((void)); +/* 163 */ +EXTERN int Tcl_GetInterpPath _ANSI_ARGS_(( + Tcl_Interp * askInterp, + Tcl_Interp * slaveInterp)); +/* 164 */ +EXTERN Tcl_Interp * Tcl_GetMaster _ANSI_ARGS_((Tcl_Interp * interp)); +/* 165 */ +EXTERN CONST char * Tcl_GetNameOfExecutable _ANSI_ARGS_((void)); +/* 166 */ +EXTERN Tcl_Obj * Tcl_GetObjResult _ANSI_ARGS_((Tcl_Interp * interp)); +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 167 */ +EXTERN int Tcl_GetOpenFile _ANSI_ARGS_((Tcl_Interp * interp, + char * str, int write, int checkUsage, + ClientData * filePtr)); +#endif /* UNIX */ +/* 168 */ +EXTERN Tcl_PathType Tcl_GetPathType _ANSI_ARGS_((char * path)); +/* 169 */ +EXTERN int Tcl_Gets _ANSI_ARGS_((Tcl_Channel chan, + Tcl_DString * dsPtr)); +/* 170 */ +EXTERN int Tcl_GetsObj _ANSI_ARGS_((Tcl_Channel chan, + Tcl_Obj * objPtr)); +/* 171 */ +EXTERN int Tcl_GetServiceMode _ANSI_ARGS_((void)); +/* 172 */ +EXTERN Tcl_Interp * Tcl_GetSlave _ANSI_ARGS_((Tcl_Interp * interp, + char * slaveName)); +/* 173 */ +EXTERN Tcl_Channel Tcl_GetStdChannel _ANSI_ARGS_((int type)); +/* 174 */ +EXTERN char * Tcl_GetStringResult _ANSI_ARGS_((Tcl_Interp * interp)); +/* 175 */ +EXTERN char * Tcl_GetVar _ANSI_ARGS_((Tcl_Interp * interp, + char * varName, int flags)); +/* 176 */ +EXTERN char * Tcl_GetVar2 _ANSI_ARGS_((Tcl_Interp * interp, + char * part1, char * part2, int flags)); +/* 177 */ +EXTERN int Tcl_GlobalEval _ANSI_ARGS_((Tcl_Interp * interp, + char * command)); +/* 178 */ +EXTERN int Tcl_GlobalEvalObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr)); +/* 179 */ +EXTERN int Tcl_HideCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * cmdName, char * hiddenCmdToken)); +/* 180 */ +EXTERN int Tcl_Init _ANSI_ARGS_((Tcl_Interp * interp)); +/* 181 */ +EXTERN void Tcl_InitHashTable _ANSI_ARGS_(( + Tcl_HashTable * tablePtr, int keyType)); +/* 182 */ +EXTERN int Tcl_InputBlocked _ANSI_ARGS_((Tcl_Channel chan)); +/* 183 */ +EXTERN int Tcl_InputBuffered _ANSI_ARGS_((Tcl_Channel chan)); +/* 184 */ +EXTERN int Tcl_InterpDeleted _ANSI_ARGS_((Tcl_Interp * interp)); +/* 185 */ +EXTERN int Tcl_IsSafe _ANSI_ARGS_((Tcl_Interp * interp)); +/* 186 */ +EXTERN char * Tcl_JoinPath _ANSI_ARGS_((int argc, char ** argv, + Tcl_DString * resultPtr)); +/* 187 */ +EXTERN int Tcl_LinkVar _ANSI_ARGS_((Tcl_Interp * interp, + char * varName, char * addr, int type)); +/* Slot 188 is reserved */ +/* 189 */ +EXTERN Tcl_Channel Tcl_MakeFileChannel _ANSI_ARGS_((ClientData handle, + int mode)); +/* 190 */ +EXTERN int Tcl_MakeSafe _ANSI_ARGS_((Tcl_Interp * interp)); +/* 191 */ +EXTERN Tcl_Channel Tcl_MakeTcpClientChannel _ANSI_ARGS_(( + ClientData tcpSocket)); +/* 192 */ +EXTERN char * Tcl_Merge _ANSI_ARGS_((int argc, char ** argv)); +/* 193 */ +EXTERN Tcl_HashEntry * Tcl_NextHashEntry _ANSI_ARGS_(( + Tcl_HashSearch * searchPtr)); +/* 194 */ +EXTERN void Tcl_NotifyChannel _ANSI_ARGS_((Tcl_Channel channel, + int mask)); +/* 195 */ +EXTERN Tcl_Obj * Tcl_ObjGetVar2 _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, + int flags)); +/* 196 */ +EXTERN Tcl_Obj * Tcl_ObjSetVar2 _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, + Tcl_Obj * newValuePtr, int flags)); +/* 197 */ +EXTERN Tcl_Channel Tcl_OpenCommandChannel _ANSI_ARGS_(( + Tcl_Interp * interp, int argc, char ** argv, + int flags)); +/* 198 */ +EXTERN Tcl_Channel Tcl_OpenFileChannel _ANSI_ARGS_((Tcl_Interp * interp, + char * fileName, char * modeString, + int permissions)); +/* 199 */ +EXTERN Tcl_Channel Tcl_OpenTcpClient _ANSI_ARGS_((Tcl_Interp * interp, + int port, char * address, char * myaddr, + int myport, int async)); +/* 200 */ +EXTERN Tcl_Channel Tcl_OpenTcpServer _ANSI_ARGS_((Tcl_Interp * interp, + int port, char * host, + Tcl_TcpAcceptProc * acceptProc, + ClientData callbackData)); +/* 201 */ +EXTERN void Tcl_Preserve _ANSI_ARGS_((ClientData data)); +/* 202 */ +EXTERN void Tcl_PrintDouble _ANSI_ARGS_((Tcl_Interp * interp, + double value, char * dst)); +/* 203 */ +EXTERN int Tcl_PutEnv _ANSI_ARGS_((CONST char * string)); +/* 204 */ +EXTERN char * Tcl_PosixError _ANSI_ARGS_((Tcl_Interp * interp)); +/* 205 */ +EXTERN void Tcl_QueueEvent _ANSI_ARGS_((Tcl_Event * evPtr, + Tcl_QueuePosition position)); +/* 206 */ +EXTERN int Tcl_Read _ANSI_ARGS_((Tcl_Channel chan, + char * bufPtr, int toRead)); +/* 207 */ +EXTERN void Tcl_ReapDetachedProcs _ANSI_ARGS_((void)); +/* 208 */ +EXTERN int Tcl_RecordAndEval _ANSI_ARGS_((Tcl_Interp * interp, + char * cmd, int flags)); +/* 209 */ +EXTERN int Tcl_RecordAndEvalObj _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * cmdPtr, + int flags)); +/* 210 */ +EXTERN void Tcl_RegisterChannel _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Channel chan)); +/* 211 */ +EXTERN void Tcl_RegisterObjType _ANSI_ARGS_(( + Tcl_ObjType * typePtr)); +/* 212 */ +EXTERN Tcl_RegExp Tcl_RegExpCompile _ANSI_ARGS_((Tcl_Interp * interp, + char * string)); +/* 213 */ +EXTERN int Tcl_RegExpExec _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_RegExp regexp, CONST char * str, + CONST char * start)); +/* 214 */ +EXTERN int Tcl_RegExpMatch _ANSI_ARGS_((Tcl_Interp * interp, + char * str, char * pattern)); +/* 215 */ +EXTERN void Tcl_RegExpRange _ANSI_ARGS_((Tcl_RegExp regexp, + int index, char ** startPtr, char ** endPtr)); +/* 216 */ +EXTERN void Tcl_Release _ANSI_ARGS_((ClientData clientData)); +/* 217 */ +EXTERN void Tcl_ResetResult _ANSI_ARGS_((Tcl_Interp * interp)); +/* 218 */ +EXTERN int Tcl_ScanElement _ANSI_ARGS_((CONST char * str, + int * flagPtr)); +/* 219 */ +EXTERN int Tcl_ScanCountedElement _ANSI_ARGS_((CONST char * str, + int length, int * flagPtr)); +/* 220 */ +EXTERN int Tcl_Seek _ANSI_ARGS_((Tcl_Channel chan, int offset, + int mode)); +/* 221 */ +EXTERN int Tcl_ServiceAll _ANSI_ARGS_((void)); +/* 222 */ +EXTERN int Tcl_ServiceEvent _ANSI_ARGS_((int flags)); +/* 223 */ +EXTERN void Tcl_SetAssocData _ANSI_ARGS_((Tcl_Interp * interp, + char * name, Tcl_InterpDeleteProc * proc, + ClientData clientData)); +/* 224 */ +EXTERN void Tcl_SetChannelBufferSize _ANSI_ARGS_(( + Tcl_Channel chan, int sz)); +/* 225 */ +EXTERN int Tcl_SetChannelOption _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Channel chan, + char * optionName, char * newValue)); +/* 226 */ +EXTERN int Tcl_SetCommandInfo _ANSI_ARGS_((Tcl_Interp * interp, + char * cmdName, Tcl_CmdInfo * infoPtr)); +/* 227 */ +EXTERN void Tcl_SetErrno _ANSI_ARGS_((int err)); +/* 228 */ +EXTERN void Tcl_SetErrorCode _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); +/* 229 */ +EXTERN void Tcl_SetMaxBlockTime _ANSI_ARGS_((Tcl_Time * timePtr)); +/* 230 */ +EXTERN void Tcl_SetPanicProc _ANSI_ARGS_(( + Tcl_PanicProc * panicProc)); +/* 231 */ +EXTERN int Tcl_SetRecursionLimit _ANSI_ARGS_(( + Tcl_Interp * interp, int depth)); +/* 232 */ +EXTERN void Tcl_SetResult _ANSI_ARGS_((Tcl_Interp * interp, + char * str, Tcl_FreeProc * freeProc)); +/* 233 */ +EXTERN int Tcl_SetServiceMode _ANSI_ARGS_((int mode)); +/* 234 */ +EXTERN void Tcl_SetObjErrorCode _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * errorObjPtr)); +/* 235 */ +EXTERN void Tcl_SetObjResult _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * resultObjPtr)); +/* 236 */ +EXTERN void Tcl_SetStdChannel _ANSI_ARGS_((Tcl_Channel channel, + int type)); +/* 237 */ +EXTERN char * Tcl_SetVar _ANSI_ARGS_((Tcl_Interp * interp, + char * varName, char * newValue, int flags)); +/* 238 */ +EXTERN char * Tcl_SetVar2 _ANSI_ARGS_((Tcl_Interp * interp, + char * part1, char * part2, char * newValue, + int flags)); +/* 239 */ +EXTERN char * Tcl_SignalId _ANSI_ARGS_((int sig)); +/* 240 */ +EXTERN char * Tcl_SignalMsg _ANSI_ARGS_((int sig)); +/* 241 */ +EXTERN void Tcl_SourceRCFile _ANSI_ARGS_((Tcl_Interp * interp)); +/* 242 */ +EXTERN int Tcl_SplitList _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * listStr, int * argcPtr, + char *** argvPtr)); +/* 243 */ +EXTERN void Tcl_SplitPath _ANSI_ARGS_((CONST char * path, + int * argcPtr, char *** argvPtr)); +/* 244 */ +EXTERN void Tcl_StaticPackage _ANSI_ARGS_((Tcl_Interp * interp, + char * pkgName, + Tcl_PackageInitProc * initProc, + Tcl_PackageInitProc * safeInitProc)); +/* 245 */ +EXTERN int Tcl_StringMatch _ANSI_ARGS_((CONST char * str, + CONST char * pattern)); +/* 246 */ +EXTERN int Tcl_Tell _ANSI_ARGS_((Tcl_Channel chan)); +/* 247 */ +EXTERN int Tcl_TraceVar _ANSI_ARGS_((Tcl_Interp * interp, + char * varName, int flags, + Tcl_VarTraceProc * proc, + ClientData clientData)); +/* 248 */ +EXTERN int Tcl_TraceVar2 _ANSI_ARGS_((Tcl_Interp * interp, + char * part1, char * part2, int flags, + Tcl_VarTraceProc * proc, + ClientData clientData)); +/* 249 */ +EXTERN char * Tcl_TranslateFileName _ANSI_ARGS_(( + Tcl_Interp * interp, char * name, + Tcl_DString * bufferPtr)); +/* 250 */ +EXTERN int Tcl_Ungets _ANSI_ARGS_((Tcl_Channel chan, char * str, + int len, int atHead)); +/* 251 */ +EXTERN void Tcl_UnlinkVar _ANSI_ARGS_((Tcl_Interp * interp, + char * varName)); +/* 252 */ +EXTERN int Tcl_UnregisterChannel _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Channel chan)); +/* 253 */ +EXTERN int Tcl_UnsetVar _ANSI_ARGS_((Tcl_Interp * interp, + char * varName, int flags)); +/* 254 */ +EXTERN int Tcl_UnsetVar2 _ANSI_ARGS_((Tcl_Interp * interp, + char * part1, char * part2, int flags)); +/* 255 */ +EXTERN void Tcl_UntraceVar _ANSI_ARGS_((Tcl_Interp * interp, + char * varName, int flags, + Tcl_VarTraceProc * proc, + ClientData clientData)); +/* 256 */ +EXTERN void Tcl_UntraceVar2 _ANSI_ARGS_((Tcl_Interp * interp, + char * part1, char * part2, int flags, + Tcl_VarTraceProc * proc, + ClientData clientData)); +/* 257 */ +EXTERN void Tcl_UpdateLinkedVar _ANSI_ARGS_((Tcl_Interp * interp, + char * varName)); +/* 258 */ +EXTERN int Tcl_UpVar _ANSI_ARGS_((Tcl_Interp * interp, + char * frameName, char * varName, + char * localName, int flags)); +/* 259 */ +EXTERN int Tcl_UpVar2 _ANSI_ARGS_((Tcl_Interp * interp, + char * frameName, char * part1, char * part2, + char * localName, int flags)); +/* 260 */ +EXTERN int Tcl_VarEval _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); +/* 261 */ +EXTERN ClientData Tcl_VarTraceInfo _ANSI_ARGS_((Tcl_Interp * interp, + char * varName, int flags, + Tcl_VarTraceProc * procPtr, + ClientData prevClientData)); +/* 262 */ +EXTERN ClientData Tcl_VarTraceInfo2 _ANSI_ARGS_((Tcl_Interp * interp, + char * part1, char * part2, int flags, + Tcl_VarTraceProc * procPtr, + ClientData prevClientData)); +/* 263 */ +EXTERN int Tcl_Write _ANSI_ARGS_((Tcl_Channel chan, char * s, + int slen)); +/* 264 */ +EXTERN void Tcl_WrongNumArgs _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], + char * message)); +/* 265 */ +EXTERN int Tcl_DumpActiveMemory _ANSI_ARGS_((char * fileName)); +/* 266 */ +EXTERN void Tcl_ValidateAllMemory _ANSI_ARGS_((char * file, + int line)); +/* 267 */ +EXTERN void Tcl_AppendResultVA _ANSI_ARGS_((Tcl_Interp * interp, + va_list argList)); +/* 268 */ +EXTERN void Tcl_AppendStringsToObjVA _ANSI_ARGS_(( + Tcl_Obj * objPtr, va_list argList)); +/* 269 */ +EXTERN char * Tcl_HashStats _ANSI_ARGS_((Tcl_HashTable * tablePtr)); +/* 270 */ +EXTERN char * Tcl_ParseVar _ANSI_ARGS_((Tcl_Interp * interp, + char * str, char ** termPtr)); +/* 271 */ +EXTERN char * Tcl_PkgPresent _ANSI_ARGS_((Tcl_Interp * interp, + char * name, char * version, int exact)); +/* 272 */ +EXTERN char * Tcl_PkgPresentEx _ANSI_ARGS_((Tcl_Interp * interp, + char * name, char * version, int exact, + ClientData * clientDataPtr)); +/* 273 */ +EXTERN int Tcl_PkgProvide _ANSI_ARGS_((Tcl_Interp * interp, + char * name, char * version)); +/* 274 */ +EXTERN char * Tcl_PkgRequire _ANSI_ARGS_((Tcl_Interp * interp, + char * name, char * version, int exact)); +/* 275 */ +EXTERN void Tcl_SetErrorCodeVA _ANSI_ARGS_((Tcl_Interp * interp, + va_list argList)); +/* 276 */ +EXTERN int Tcl_VarEvalVA _ANSI_ARGS_((Tcl_Interp * interp, + va_list argList)); +/* 277 */ +EXTERN Tcl_Pid Tcl_WaitPid _ANSI_ARGS_((Tcl_Pid pid, int * statPtr, + int options)); +/* 278 */ +EXTERN void Tcl_PanicVA _ANSI_ARGS_((char * format, + va_list argList)); +/* 279 */ +EXTERN void Tcl_GetVersion _ANSI_ARGS_((int * major, int * minor, + int * patchLevel, int * type)); +/* 280 */ +EXTERN void Tcl_InitMemory _ANSI_ARGS_((Tcl_Interp * interp)); +/* Slot 281 is reserved */ +/* Slot 282 is reserved */ +/* Slot 283 is reserved */ +/* Slot 284 is reserved */ +/* Slot 285 is reserved */ +/* 286 */ +EXTERN void Tcl_AppendObjToObj _ANSI_ARGS_((Tcl_Obj * objPtr, + Tcl_Obj * appendObjPtr)); +/* 287 */ +EXTERN Tcl_Encoding Tcl_CreateEncoding _ANSI_ARGS_(( + Tcl_EncodingType * typePtr)); +/* 288 */ +EXTERN void Tcl_CreateThreadExitHandler _ANSI_ARGS_(( + Tcl_ExitProc * proc, ClientData clientData)); +/* 289 */ +EXTERN void Tcl_DeleteThreadExitHandler _ANSI_ARGS_(( + Tcl_ExitProc * proc, ClientData clientData)); +/* 290 */ +EXTERN void Tcl_DiscardResult _ANSI_ARGS_(( + Tcl_SavedResult * statePtr)); +/* 291 */ +EXTERN int Tcl_EvalEx _ANSI_ARGS_((Tcl_Interp * interp, + char * script, int numBytes, int flags)); +/* 292 */ +EXTERN int Tcl_EvalObjv _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +/* 293 */ +EXTERN int Tcl_EvalObjEx _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, int flags)); +/* 294 */ +EXTERN void Tcl_ExitThread _ANSI_ARGS_((int status)); +/* 295 */ +EXTERN int Tcl_ExternalToUtf _ANSI_ARGS_((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 _ANSI_ARGS_(( + Tcl_Encoding encoding, CONST char * src, + int srcLen, Tcl_DString * dsPtr)); +/* 297 */ +EXTERN void Tcl_FinalizeThread _ANSI_ARGS_((void)); +/* 298 */ +EXTERN void Tcl_FinalizeNotifier _ANSI_ARGS_(( + ClientData clientData)); +/* 299 */ +EXTERN void Tcl_FreeEncoding _ANSI_ARGS_((Tcl_Encoding encoding)); +/* 300 */ +EXTERN Tcl_ThreadId Tcl_GetCurrentThread _ANSI_ARGS_((void)); +/* 301 */ +EXTERN Tcl_Encoding Tcl_GetEncoding _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * name)); +/* 302 */ +EXTERN char * Tcl_GetEncodingName _ANSI_ARGS_(( + Tcl_Encoding encoding)); +/* 303 */ +EXTERN void Tcl_GetEncodingNames _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 304 */ +EXTERN int Tcl_GetIndexFromObjStruct _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr, + char ** tablePtr, int offset, char * msg, + int flags, int * indexPtr)); +/* 305 */ +EXTERN VOID * Tcl_GetThreadData _ANSI_ARGS_(( + Tcl_ThreadDataKey * keyPtr, int size)); +/* 306 */ +EXTERN Tcl_Obj * Tcl_GetVar2Ex _ANSI_ARGS_((Tcl_Interp * interp, + char * part1, char * part2, int flags)); +/* 307 */ +EXTERN ClientData Tcl_InitNotifier _ANSI_ARGS_((void)); +/* 308 */ +EXTERN void Tcl_MutexLock _ANSI_ARGS_((Tcl_Mutex * mutexPtr)); +/* 309 */ +EXTERN void Tcl_MutexUnlock _ANSI_ARGS_((Tcl_Mutex * mutexPtr)); +/* 310 */ +EXTERN void Tcl_ConditionNotify _ANSI_ARGS_(( + Tcl_Condition * condPtr)); +/* 311 */ +EXTERN void Tcl_ConditionWait _ANSI_ARGS_(( + Tcl_Condition * condPtr, + Tcl_Mutex * mutexPtr, Tcl_Time * timePtr)); +/* 312 */ +EXTERN int Tcl_NumUtfChars _ANSI_ARGS_((CONST char * src, + int len)); +/* 313 */ +EXTERN int Tcl_ReadChars _ANSI_ARGS_((Tcl_Channel channel, + Tcl_Obj * objPtr, int charsToRead, + int appendFlag)); +/* 314 */ +EXTERN void Tcl_RestoreResult _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_SavedResult * statePtr)); +/* 315 */ +EXTERN void Tcl_SaveResult _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_SavedResult * statePtr)); +/* 316 */ +EXTERN int Tcl_SetSystemEncoding _ANSI_ARGS_(( + Tcl_Interp * interp, CONST char * name)); +/* 317 */ +EXTERN Tcl_Obj * Tcl_SetVar2Ex _ANSI_ARGS_((Tcl_Interp * interp, + char * part1, char * part2, + Tcl_Obj * newValuePtr, int flags)); +/* 318 */ +EXTERN void Tcl_ThreadAlert _ANSI_ARGS_((Tcl_ThreadId threadId)); +/* 319 */ +EXTERN void Tcl_ThreadQueueEvent _ANSI_ARGS_(( + Tcl_ThreadId threadId, Tcl_Event* evPtr, + Tcl_QueuePosition position)); +/* 320 */ +EXTERN Tcl_UniChar Tcl_UniCharAtIndex _ANSI_ARGS_((CONST char * src, + int index)); +/* 321 */ +EXTERN Tcl_UniChar Tcl_UniCharToLower _ANSI_ARGS_((int ch)); +/* 322 */ +EXTERN Tcl_UniChar Tcl_UniCharToTitle _ANSI_ARGS_((int ch)); +/* 323 */ +EXTERN Tcl_UniChar Tcl_UniCharToUpper _ANSI_ARGS_((int ch)); +/* 324 */ +EXTERN int Tcl_UniCharToUtf _ANSI_ARGS_((int ch, char * buf)); +/* 325 */ +EXTERN char * Tcl_UtfAtIndex _ANSI_ARGS_((CONST char * src, + int index)); +/* 326 */ +EXTERN int Tcl_UtfCharComplete _ANSI_ARGS_((CONST char * src, + int len)); +/* 327 */ +EXTERN int Tcl_UtfBackslash _ANSI_ARGS_((CONST char * src, + int * readPtr, char * dst)); +/* 328 */ +EXTERN char * Tcl_UtfFindFirst _ANSI_ARGS_((CONST char * src, + int ch)); +/* 329 */ +EXTERN char * Tcl_UtfFindLast _ANSI_ARGS_((CONST char * src, + int ch)); +/* 330 */ +EXTERN char * Tcl_UtfNext _ANSI_ARGS_((CONST char * src)); +/* 331 */ +EXTERN char * Tcl_UtfPrev _ANSI_ARGS_((CONST char * src, + CONST char * start)); +/* 332 */ +EXTERN int Tcl_UtfToExternal _ANSI_ARGS_((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 _ANSI_ARGS_(( + Tcl_Encoding encoding, CONST char * src, + int srcLen, Tcl_DString * dsPtr)); +/* 334 */ +EXTERN int Tcl_UtfToLower _ANSI_ARGS_((char * src)); +/* 335 */ +EXTERN int Tcl_UtfToTitle _ANSI_ARGS_((char * src)); +/* 336 */ +EXTERN int Tcl_UtfToUniChar _ANSI_ARGS_((CONST char * src, + Tcl_UniChar * chPtr)); +/* 337 */ +EXTERN int Tcl_UtfToUpper _ANSI_ARGS_((char * src)); +/* 338 */ +EXTERN int Tcl_WriteChars _ANSI_ARGS_((Tcl_Channel chan, + CONST char * src, int srcLen)); +/* 339 */ +EXTERN int Tcl_WriteObj _ANSI_ARGS_((Tcl_Channel chan, + Tcl_Obj * objPtr)); +/* 340 */ +EXTERN char * Tcl_GetString _ANSI_ARGS_((Tcl_Obj * objPtr)); +/* 341 */ +EXTERN char * Tcl_GetDefaultEncodingDir _ANSI_ARGS_((void)); +/* 342 */ +EXTERN void Tcl_SetDefaultEncodingDir _ANSI_ARGS_((char * path)); +/* 343 */ +EXTERN void Tcl_AlertNotifier _ANSI_ARGS_((ClientData clientData)); +/* 344 */ +EXTERN void Tcl_ServiceModeHook _ANSI_ARGS_((int mode)); +/* 345 */ +EXTERN int Tcl_UniCharIsAlnum _ANSI_ARGS_((int ch)); +/* 346 */ +EXTERN int Tcl_UniCharIsAlpha _ANSI_ARGS_((int ch)); +/* 347 */ +EXTERN int Tcl_UniCharIsDigit _ANSI_ARGS_((int ch)); +/* 348 */ +EXTERN int Tcl_UniCharIsLower _ANSI_ARGS_((int ch)); +/* 349 */ +EXTERN int Tcl_UniCharIsSpace _ANSI_ARGS_((int ch)); +/* 350 */ +EXTERN int Tcl_UniCharIsUpper _ANSI_ARGS_((int ch)); +/* 351 */ +EXTERN int Tcl_UniCharIsWordChar _ANSI_ARGS_((int ch)); +/* 352 */ +EXTERN int Tcl_UniCharLen _ANSI_ARGS_((Tcl_UniChar * str)); +/* 353 */ +EXTERN int Tcl_UniCharNcmp _ANSI_ARGS_((const Tcl_UniChar * cs, + const Tcl_UniChar * ct, size_t n)); +/* 354 */ +EXTERN char * Tcl_UniCharToUtfDString _ANSI_ARGS_(( + CONST Tcl_UniChar * string, int numChars, + Tcl_DString * dsPtr)); +/* 355 */ +EXTERN Tcl_UniChar * Tcl_UtfToUniCharDString _ANSI_ARGS_(( + CONST char * string, int length, + Tcl_DString * dsPtr)); +/* 356 */ +EXTERN Tcl_RegExp Tcl_GetRegExpFromObj _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * patObj, + int flags)); +/* 357 */ +EXTERN Tcl_Obj * Tcl_EvalTokens _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Token * tokenPtr, int count)); +/* 358 */ +EXTERN void Tcl_FreeParse _ANSI_ARGS_((Tcl_Parse * parsePtr)); +/* 359 */ +EXTERN void Tcl_LogCommandInfo _ANSI_ARGS_((Tcl_Interp * interp, + char * script, char * command, int length)); +/* 360 */ +EXTERN int Tcl_ParseBraces _ANSI_ARGS_((Tcl_Interp * interp, + char * string, int numBytes, + Tcl_Parse * parsePtr, int append, + char ** termPtr)); +/* 361 */ +EXTERN int Tcl_ParseCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * string, int numBytes, int nested, + Tcl_Parse * parsePtr)); +/* 362 */ +EXTERN int Tcl_ParseExpr _ANSI_ARGS_((Tcl_Interp * interp, + char * string, int numBytes, + Tcl_Parse * parsePtr)); +/* 363 */ +EXTERN int Tcl_ParseQuotedString _ANSI_ARGS_(( + Tcl_Interp * interp, char * string, + int numBytes, Tcl_Parse * parsePtr, + int append, char ** termPtr)); +/* 364 */ +EXTERN int Tcl_ParseVarName _ANSI_ARGS_((Tcl_Interp * interp, + char * string, int numBytes, + Tcl_Parse * parsePtr, int append)); +/* 365 */ +EXTERN char * Tcl_GetCwd _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_DString * cwdPtr)); +/* 366 */ +EXTERN int Tcl_Chdir _ANSI_ARGS_((CONST char * dirName)); + +typedef struct TclStubHooks { + struct TclPlatStubs *tclPlatStubs; + struct TclIntStubs *tclIntStubs; + struct TclIntPlatStubs *tclIntPlatStubs; +} TclStubHooks; + +typedef struct TclStubs { + int magic; + struct TclStubHooks *hooks; + + int (*tcl_PkgProvideEx) _ANSI_ARGS_((Tcl_Interp * interp, char * name, char * version, ClientData clientData)); /* 0 */ + char * (*tcl_PkgRequireEx) _ANSI_ARGS_((Tcl_Interp * interp, char * name, char * version, int exact, ClientData * clientDataPtr)); /* 1 */ + void (*tcl_Panic) _ANSI_ARGS_(TCL_VARARGS(char *,format)); /* 2 */ + char * (*tcl_Alloc) _ANSI_ARGS_((unsigned int size)); /* 3 */ + void (*tcl_Free) _ANSI_ARGS_((char * ptr)); /* 4 */ + char * (*tcl_Realloc) _ANSI_ARGS_((char * ptr, unsigned int size)); /* 5 */ + char * (*tcl_DbCkalloc) _ANSI_ARGS_((unsigned int size, char * file, int line)); /* 6 */ + int (*tcl_DbCkfree) _ANSI_ARGS_((char * ptr, char * file, int line)); /* 7 */ + char * (*tcl_DbCkrealloc) _ANSI_ARGS_((char * ptr, unsigned int size, char * file, int line)); /* 8 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void (*tcl_CreateFileHandler) _ANSI_ARGS_((int fd, int mask, Tcl_FileProc * proc, ClientData clientData)); /* 9 */ +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved9; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved9; +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void (*tcl_DeleteFileHandler) _ANSI_ARGS_((int fd)); /* 10 */ +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved10; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved10; +#endif /* MAC_TCL */ + void (*tcl_SetTimer) _ANSI_ARGS_((Tcl_Time * timePtr)); /* 11 */ + void (*tcl_Sleep) _ANSI_ARGS_((int ms)); /* 12 */ + int (*tcl_WaitForEvent) _ANSI_ARGS_((Tcl_Time * timePtr)); /* 13 */ + int (*tcl_AppendAllObjTypes) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 14 */ + void (*tcl_AppendStringsToObj) _ANSI_ARGS_(TCL_VARARGS(Tcl_Obj *,objPtr)); /* 15 */ + void (*tcl_AppendToObj) _ANSI_ARGS_((Tcl_Obj * objPtr, char * bytes, int length)); /* 16 */ + Tcl_Obj * (*tcl_ConcatObj) _ANSI_ARGS_((int objc, Tcl_Obj *CONST objv[])); /* 17 */ + int (*tcl_ConvertToType) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, Tcl_ObjType * typePtr)); /* 18 */ + void (*tcl_DbDecrRefCount) _ANSI_ARGS_((Tcl_Obj * objPtr, char * file, int line)); /* 19 */ + void (*tcl_DbIncrRefCount) _ANSI_ARGS_((Tcl_Obj * objPtr, char * file, int line)); /* 20 */ + int (*tcl_DbIsShared) _ANSI_ARGS_((Tcl_Obj * objPtr, char * file, int line)); /* 21 */ + Tcl_Obj * (*tcl_DbNewBooleanObj) _ANSI_ARGS_((int boolValue, char * file, int line)); /* 22 */ + Tcl_Obj * (*tcl_DbNewByteArrayObj) _ANSI_ARGS_((unsigned char * bytes, int length, char * file, int line)); /* 23 */ + Tcl_Obj * (*tcl_DbNewDoubleObj) _ANSI_ARGS_((double doubleValue, char * file, int line)); /* 24 */ + Tcl_Obj * (*tcl_DbNewListObj) _ANSI_ARGS_((int objc, Tcl_Obj *CONST objv[], char * file, int line)); /* 25 */ + Tcl_Obj * (*tcl_DbNewLongObj) _ANSI_ARGS_((long longValue, char * file, int line)); /* 26 */ + Tcl_Obj * (*tcl_DbNewObj) _ANSI_ARGS_((char * file, int line)); /* 27 */ + Tcl_Obj * (*tcl_DbNewStringObj) _ANSI_ARGS_((CONST char * bytes, int length, char * file, int line)); /* 28 */ + Tcl_Obj * (*tcl_DuplicateObj) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 29 */ + void (*tclFreeObj) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 30 */ + int (*tcl_GetBoolean) _ANSI_ARGS_((Tcl_Interp * interp, char * str, int * boolPtr)); /* 31 */ + int (*tcl_GetBooleanFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int * boolPtr)); /* 32 */ + unsigned char * (*tcl_GetByteArrayFromObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int * lengthPtr)); /* 33 */ + int (*tcl_GetDouble) _ANSI_ARGS_((Tcl_Interp * interp, char * str, double * doublePtr)); /* 34 */ + int (*tcl_GetDoubleFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, double * doublePtr)); /* 35 */ + int (*tcl_GetIndexFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, char ** tablePtr, char * msg, int flags, int * indexPtr)); /* 36 */ + int (*tcl_GetInt) _ANSI_ARGS_((Tcl_Interp * interp, char * str, int * intPtr)); /* 37 */ + int (*tcl_GetIntFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int * intPtr)); /* 38 */ + int (*tcl_GetLongFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, long * longPtr)); /* 39 */ + Tcl_ObjType * (*tcl_GetObjType) _ANSI_ARGS_((char * typeName)); /* 40 */ + char * (*tcl_GetStringFromObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int * lengthPtr)); /* 41 */ + void (*tcl_InvalidateStringRep) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 42 */ + int (*tcl_ListObjAppendList) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, Tcl_Obj * elemListPtr)); /* 43 */ + int (*tcl_ListObjAppendElement) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, Tcl_Obj * objPtr)); /* 44 */ + int (*tcl_ListObjGetElements) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, int * objcPtr, Tcl_Obj *** objvPtr)); /* 45 */ + int (*tcl_ListObjIndex) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, int index, Tcl_Obj ** objPtrPtr)); /* 46 */ + int (*tcl_ListObjLength) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, int * intPtr)); /* 47 */ + int (*tcl_ListObjReplace) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, int first, int count, int objc, Tcl_Obj *CONST objv[])); /* 48 */ + Tcl_Obj * (*tcl_NewBooleanObj) _ANSI_ARGS_((int boolValue)); /* 49 */ + Tcl_Obj * (*tcl_NewByteArrayObj) _ANSI_ARGS_((unsigned char * bytes, int length)); /* 50 */ + Tcl_Obj * (*tcl_NewDoubleObj) _ANSI_ARGS_((double doubleValue)); /* 51 */ + Tcl_Obj * (*tcl_NewIntObj) _ANSI_ARGS_((int intValue)); /* 52 */ + Tcl_Obj * (*tcl_NewListObj) _ANSI_ARGS_((int objc, Tcl_Obj *CONST objv[])); /* 53 */ + Tcl_Obj * (*tcl_NewLongObj) _ANSI_ARGS_((long longValue)); /* 54 */ + Tcl_Obj * (*tcl_NewObj) _ANSI_ARGS_((void)); /* 55 */ + Tcl_Obj * (*tcl_NewStringObj) _ANSI_ARGS_((CONST char * bytes, int length)); /* 56 */ + void (*tcl_SetBooleanObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int boolValue)); /* 57 */ + unsigned char * (*tcl_SetByteArrayLength) _ANSI_ARGS_((Tcl_Obj * objPtr, int length)); /* 58 */ + void (*tcl_SetByteArrayObj) _ANSI_ARGS_((Tcl_Obj * objPtr, unsigned char * bytes, int length)); /* 59 */ + void (*tcl_SetDoubleObj) _ANSI_ARGS_((Tcl_Obj * objPtr, double doubleValue)); /* 60 */ + void (*tcl_SetIntObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int intValue)); /* 61 */ + void (*tcl_SetListObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int objc, Tcl_Obj *CONST objv[])); /* 62 */ + void (*tcl_SetLongObj) _ANSI_ARGS_((Tcl_Obj * objPtr, long longValue)); /* 63 */ + void (*tcl_SetObjLength) _ANSI_ARGS_((Tcl_Obj * objPtr, int length)); /* 64 */ + void (*tcl_SetStringObj) _ANSI_ARGS_((Tcl_Obj * objPtr, char * bytes, int length)); /* 65 */ + void (*tcl_AddErrorInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * message)); /* 66 */ + void (*tcl_AddObjErrorInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * message, int length)); /* 67 */ + void (*tcl_AllowExceptions) _ANSI_ARGS_((Tcl_Interp * interp)); /* 68 */ + void (*tcl_AppendElement) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string)); /* 69 */ + void (*tcl_AppendResult) _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); /* 70 */ + Tcl_AsyncHandler (*tcl_AsyncCreate) _ANSI_ARGS_((Tcl_AsyncProc * proc, ClientData clientData)); /* 71 */ + void (*tcl_AsyncDelete) _ANSI_ARGS_((Tcl_AsyncHandler async)); /* 72 */ + int (*tcl_AsyncInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int code)); /* 73 */ + void (*tcl_AsyncMark) _ANSI_ARGS_((Tcl_AsyncHandler async)); /* 74 */ + int (*tcl_AsyncReady) _ANSI_ARGS_((void)); /* 75 */ + void (*tcl_BackgroundError) _ANSI_ARGS_((Tcl_Interp * interp)); /* 76 */ + char (*tcl_Backslash) _ANSI_ARGS_((CONST char * src, int * readPtr)); /* 77 */ + int (*tcl_BadChannelOption) _ANSI_ARGS_((Tcl_Interp * interp, char * optionName, char * optionList)); /* 78 */ + void (*tcl_CallWhenDeleted) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_InterpDeleteProc * proc, ClientData clientData)); /* 79 */ + void (*tcl_CancelIdleCall) _ANSI_ARGS_((Tcl_IdleProc * idleProc, ClientData clientData)); /* 80 */ + int (*tcl_Close) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 81 */ + int (*tcl_CommandComplete) _ANSI_ARGS_((char * cmd)); /* 82 */ + char * (*tcl_Concat) _ANSI_ARGS_((int argc, char ** argv)); /* 83 */ + int (*tcl_ConvertElement) _ANSI_ARGS_((CONST char * src, char * dst, int flags)); /* 84 */ + int (*tcl_ConvertCountedElement) _ANSI_ARGS_((CONST char * src, int length, char * dst, int flags)); /* 85 */ + int (*tcl_CreateAlias) _ANSI_ARGS_((Tcl_Interp * slave, char * slaveCmd, Tcl_Interp * target, char * targetCmd, int argc, char ** argv)); /* 86 */ + int (*tcl_CreateAliasObj) _ANSI_ARGS_((Tcl_Interp * slave, char * slaveCmd, Tcl_Interp * target, char * targetCmd, int objc, Tcl_Obj *CONST objv[])); /* 87 */ + Tcl_Channel (*tcl_CreateChannel) _ANSI_ARGS_((Tcl_ChannelType * typePtr, char * chanName, ClientData instanceData, int mask)); /* 88 */ + void (*tcl_CreateChannelHandler) _ANSI_ARGS_((Tcl_Channel chan, int mask, Tcl_ChannelProc * proc, ClientData clientData)); /* 89 */ + void (*tcl_CreateCloseHandler) _ANSI_ARGS_((Tcl_Channel chan, Tcl_CloseProc * proc, ClientData clientData)); /* 90 */ + Tcl_Command (*tcl_CreateCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * cmdName, Tcl_CmdProc * proc, ClientData clientData, Tcl_CmdDeleteProc * deleteProc)); /* 91 */ + void (*tcl_CreateEventSource) _ANSI_ARGS_((Tcl_EventSetupProc * setupProc, Tcl_EventCheckProc * checkProc, ClientData clientData)); /* 92 */ + void (*tcl_CreateExitHandler) _ANSI_ARGS_((Tcl_ExitProc * proc, ClientData clientData)); /* 93 */ + Tcl_Interp * (*tcl_CreateInterp) _ANSI_ARGS_((void)); /* 94 */ + void (*tcl_CreateMathFunc) _ANSI_ARGS_((Tcl_Interp * interp, char * name, int numArgs, Tcl_ValueType * argTypes, Tcl_MathProc * proc, ClientData clientData)); /* 95 */ + Tcl_Command (*tcl_CreateObjCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * cmdName, Tcl_ObjCmdProc * proc, ClientData clientData, Tcl_CmdDeleteProc * deleteProc)); /* 96 */ + Tcl_Interp * (*tcl_CreateSlave) _ANSI_ARGS_((Tcl_Interp * interp, char * slaveName, int isSafe)); /* 97 */ + Tcl_TimerToken (*tcl_CreateTimerHandler) _ANSI_ARGS_((int milliseconds, Tcl_TimerProc * proc, ClientData clientData)); /* 98 */ + Tcl_Trace (*tcl_CreateTrace) _ANSI_ARGS_((Tcl_Interp * interp, int level, Tcl_CmdTraceProc * proc, ClientData clientData)); /* 99 */ + void (*tcl_DeleteAssocData) _ANSI_ARGS_((Tcl_Interp * interp, char * name)); /* 100 */ + void (*tcl_DeleteChannelHandler) _ANSI_ARGS_((Tcl_Channel chan, Tcl_ChannelProc * proc, ClientData clientData)); /* 101 */ + void (*tcl_DeleteCloseHandler) _ANSI_ARGS_((Tcl_Channel chan, Tcl_CloseProc * proc, ClientData clientData)); /* 102 */ + int (*tcl_DeleteCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * cmdName)); /* 103 */ + int (*tcl_DeleteCommandFromToken) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command command)); /* 104 */ + void (*tcl_DeleteEvents) _ANSI_ARGS_((Tcl_EventDeleteProc * proc, ClientData clientData)); /* 105 */ + void (*tcl_DeleteEventSource) _ANSI_ARGS_((Tcl_EventSetupProc * setupProc, Tcl_EventCheckProc * checkProc, ClientData clientData)); /* 106 */ + void (*tcl_DeleteExitHandler) _ANSI_ARGS_((Tcl_ExitProc * proc, ClientData clientData)); /* 107 */ + void (*tcl_DeleteHashEntry) _ANSI_ARGS_((Tcl_HashEntry * entryPtr)); /* 108 */ + void (*tcl_DeleteHashTable) _ANSI_ARGS_((Tcl_HashTable * tablePtr)); /* 109 */ + void (*tcl_DeleteInterp) _ANSI_ARGS_((Tcl_Interp * interp)); /* 110 */ + void (*tcl_DetachPids) _ANSI_ARGS_((int numPids, Tcl_Pid * pidPtr)); /* 111 */ + void (*tcl_DeleteTimerHandler) _ANSI_ARGS_((Tcl_TimerToken token)); /* 112 */ + void (*tcl_DeleteTrace) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Trace trace)); /* 113 */ + void (*tcl_DontCallWhenDeleted) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_InterpDeleteProc * proc, ClientData clientData)); /* 114 */ + int (*tcl_DoOneEvent) _ANSI_ARGS_((int flags)); /* 115 */ + void (*tcl_DoWhenIdle) _ANSI_ARGS_((Tcl_IdleProc * proc, ClientData clientData)); /* 116 */ + char * (*tcl_DStringAppend) _ANSI_ARGS_((Tcl_DString * dsPtr, CONST char * str, int length)); /* 117 */ + char * (*tcl_DStringAppendElement) _ANSI_ARGS_((Tcl_DString * dsPtr, CONST char * string)); /* 118 */ + void (*tcl_DStringEndSublist) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 119 */ + void (*tcl_DStringFree) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 120 */ + void (*tcl_DStringGetResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * dsPtr)); /* 121 */ + void (*tcl_DStringInit) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 122 */ + void (*tcl_DStringResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * dsPtr)); /* 123 */ + void (*tcl_DStringSetLength) _ANSI_ARGS_((Tcl_DString * dsPtr, int length)); /* 124 */ + void (*tcl_DStringStartSublist) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 125 */ + int (*tcl_Eof) _ANSI_ARGS_((Tcl_Channel chan)); /* 126 */ + char * (*tcl_ErrnoId) _ANSI_ARGS_((void)); /* 127 */ + char * (*tcl_ErrnoMsg) _ANSI_ARGS_((int err)); /* 128 */ + int (*tcl_Eval) _ANSI_ARGS_((Tcl_Interp * interp, char * string)); /* 129 */ + int (*tcl_EvalFile) _ANSI_ARGS_((Tcl_Interp * interp, char * fileName)); /* 130 */ + int (*tcl_EvalObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 131 */ + void (*tcl_EventuallyFree) _ANSI_ARGS_((ClientData clientData, Tcl_FreeProc * freeProc)); /* 132 */ + void (*tcl_Exit) _ANSI_ARGS_((int status)); /* 133 */ + int (*tcl_ExposeCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * hiddenCmdToken, char * cmdName)); /* 134 */ + int (*tcl_ExprBoolean) _ANSI_ARGS_((Tcl_Interp * interp, char * str, int * ptr)); /* 135 */ + int (*tcl_ExprBooleanObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int * ptr)); /* 136 */ + int (*tcl_ExprDouble) _ANSI_ARGS_((Tcl_Interp * interp, char * str, double * ptr)); /* 137 */ + int (*tcl_ExprDoubleObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, double * ptr)); /* 138 */ + int (*tcl_ExprLong) _ANSI_ARGS_((Tcl_Interp * interp, char * str, long * ptr)); /* 139 */ + int (*tcl_ExprLongObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, long * ptr)); /* 140 */ + int (*tcl_ExprObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, Tcl_Obj ** resultPtrPtr)); /* 141 */ + int (*tcl_ExprString) _ANSI_ARGS_((Tcl_Interp * interp, char * string)); /* 142 */ + void (*tcl_Finalize) _ANSI_ARGS_((void)); /* 143 */ + void (*tcl_FindExecutable) _ANSI_ARGS_((CONST char * argv0)); /* 144 */ + Tcl_HashEntry * (*tcl_FirstHashEntry) _ANSI_ARGS_((Tcl_HashTable * tablePtr, Tcl_HashSearch * searchPtr)); /* 145 */ + int (*tcl_Flush) _ANSI_ARGS_((Tcl_Channel chan)); /* 146 */ + void (*tcl_FreeResult) _ANSI_ARGS_((Tcl_Interp * interp)); /* 147 */ + int (*tcl_GetAlias) _ANSI_ARGS_((Tcl_Interp * interp, char * slaveCmd, Tcl_Interp ** targetInterpPtr, char ** targetCmdPtr, int * argcPtr, char *** argvPtr)); /* 148 */ + int (*tcl_GetAliasObj) _ANSI_ARGS_((Tcl_Interp * interp, char * slaveCmd, Tcl_Interp ** targetInterpPtr, char ** targetCmdPtr, int * objcPtr, Tcl_Obj *** objv)); /* 149 */ + ClientData (*tcl_GetAssocData) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_InterpDeleteProc ** procPtr)); /* 150 */ + Tcl_Channel (*tcl_GetChannel) _ANSI_ARGS_((Tcl_Interp * interp, char * chanName, int * modePtr)); /* 151 */ + int (*tcl_GetChannelBufferSize) _ANSI_ARGS_((Tcl_Channel chan)); /* 152 */ + int (*tcl_GetChannelHandle) _ANSI_ARGS_((Tcl_Channel chan, int direction, ClientData * handlePtr)); /* 153 */ + ClientData (*tcl_GetChannelInstanceData) _ANSI_ARGS_((Tcl_Channel chan)); /* 154 */ + int (*tcl_GetChannelMode) _ANSI_ARGS_((Tcl_Channel chan)); /* 155 */ + char * (*tcl_GetChannelName) _ANSI_ARGS_((Tcl_Channel chan)); /* 156 */ + int (*tcl_GetChannelOption) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan, char * optionName, Tcl_DString * dsPtr)); /* 157 */ + Tcl_ChannelType * (*tcl_GetChannelType) _ANSI_ARGS_((Tcl_Channel chan)); /* 158 */ + int (*tcl_GetCommandInfo) _ANSI_ARGS_((Tcl_Interp * interp, char * cmdName, Tcl_CmdInfo * infoPtr)); /* 159 */ + char * (*tcl_GetCommandName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command command)); /* 160 */ + int (*tcl_GetErrno) _ANSI_ARGS_((void)); /* 161 */ + char * (*tcl_GetHostName) _ANSI_ARGS_((void)); /* 162 */ + int (*tcl_GetInterpPath) _ANSI_ARGS_((Tcl_Interp * askInterp, Tcl_Interp * slaveInterp)); /* 163 */ + Tcl_Interp * (*tcl_GetMaster) _ANSI_ARGS_((Tcl_Interp * interp)); /* 164 */ + CONST char * (*tcl_GetNameOfExecutable) _ANSI_ARGS_((void)); /* 165 */ + Tcl_Obj * (*tcl_GetObjResult) _ANSI_ARGS_((Tcl_Interp * interp)); /* 166 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + int (*tcl_GetOpenFile) _ANSI_ARGS_((Tcl_Interp * interp, char * str, int write, int checkUsage, ClientData * filePtr)); /* 167 */ +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved167; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved167; +#endif /* MAC_TCL */ + Tcl_PathType (*tcl_GetPathType) _ANSI_ARGS_((char * path)); /* 168 */ + int (*tcl_Gets) _ANSI_ARGS_((Tcl_Channel chan, Tcl_DString * dsPtr)); /* 169 */ + int (*tcl_GetsObj) _ANSI_ARGS_((Tcl_Channel chan, Tcl_Obj * objPtr)); /* 170 */ + int (*tcl_GetServiceMode) _ANSI_ARGS_((void)); /* 171 */ + Tcl_Interp * (*tcl_GetSlave) _ANSI_ARGS_((Tcl_Interp * interp, char * slaveName)); /* 172 */ + Tcl_Channel (*tcl_GetStdChannel) _ANSI_ARGS_((int type)); /* 173 */ + char * (*tcl_GetStringResult) _ANSI_ARGS_((Tcl_Interp * interp)); /* 174 */ + char * (*tcl_GetVar) _ANSI_ARGS_((Tcl_Interp * interp, char * varName, int flags)); /* 175 */ + char * (*tcl_GetVar2) _ANSI_ARGS_((Tcl_Interp * interp, char * part1, char * part2, int flags)); /* 176 */ + int (*tcl_GlobalEval) _ANSI_ARGS_((Tcl_Interp * interp, char * command)); /* 177 */ + int (*tcl_GlobalEvalObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 178 */ + int (*tcl_HideCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * cmdName, char * hiddenCmdToken)); /* 179 */ + int (*tcl_Init) _ANSI_ARGS_((Tcl_Interp * interp)); /* 180 */ + void (*tcl_InitHashTable) _ANSI_ARGS_((Tcl_HashTable * tablePtr, int keyType)); /* 181 */ + int (*tcl_InputBlocked) _ANSI_ARGS_((Tcl_Channel chan)); /* 182 */ + int (*tcl_InputBuffered) _ANSI_ARGS_((Tcl_Channel chan)); /* 183 */ + int (*tcl_InterpDeleted) _ANSI_ARGS_((Tcl_Interp * interp)); /* 184 */ + int (*tcl_IsSafe) _ANSI_ARGS_((Tcl_Interp * interp)); /* 185 */ + char * (*tcl_JoinPath) _ANSI_ARGS_((int argc, char ** argv, Tcl_DString * resultPtr)); /* 186 */ + int (*tcl_LinkVar) _ANSI_ARGS_((Tcl_Interp * interp, char * varName, char * addr, int type)); /* 187 */ + void *reserved188; + Tcl_Channel (*tcl_MakeFileChannel) _ANSI_ARGS_((ClientData handle, int mode)); /* 189 */ + int (*tcl_MakeSafe) _ANSI_ARGS_((Tcl_Interp * interp)); /* 190 */ + Tcl_Channel (*tcl_MakeTcpClientChannel) _ANSI_ARGS_((ClientData tcpSocket)); /* 191 */ + char * (*tcl_Merge) _ANSI_ARGS_((int argc, char ** argv)); /* 192 */ + Tcl_HashEntry * (*tcl_NextHashEntry) _ANSI_ARGS_((Tcl_HashSearch * searchPtr)); /* 193 */ + void (*tcl_NotifyChannel) _ANSI_ARGS_((Tcl_Channel channel, int mask)); /* 194 */ + Tcl_Obj * (*tcl_ObjGetVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, int flags)); /* 195 */ + Tcl_Obj * (*tcl_ObjSetVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, Tcl_Obj * newValuePtr, int flags)); /* 196 */ + Tcl_Channel (*tcl_OpenCommandChannel) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, int flags)); /* 197 */ + Tcl_Channel (*tcl_OpenFileChannel) _ANSI_ARGS_((Tcl_Interp * interp, char * fileName, char * modeString, int permissions)); /* 198 */ + Tcl_Channel (*tcl_OpenTcpClient) _ANSI_ARGS_((Tcl_Interp * interp, int port, char * address, char * myaddr, int myport, int async)); /* 199 */ + Tcl_Channel (*tcl_OpenTcpServer) _ANSI_ARGS_((Tcl_Interp * interp, int port, char * host, Tcl_TcpAcceptProc * acceptProc, ClientData callbackData)); /* 200 */ + void (*tcl_Preserve) _ANSI_ARGS_((ClientData data)); /* 201 */ + void (*tcl_PrintDouble) _ANSI_ARGS_((Tcl_Interp * interp, double value, char * dst)); /* 202 */ + int (*tcl_PutEnv) _ANSI_ARGS_((CONST char * string)); /* 203 */ + char * (*tcl_PosixError) _ANSI_ARGS_((Tcl_Interp * interp)); /* 204 */ + void (*tcl_QueueEvent) _ANSI_ARGS_((Tcl_Event * evPtr, Tcl_QueuePosition position)); /* 205 */ + int (*tcl_Read) _ANSI_ARGS_((Tcl_Channel chan, char * bufPtr, int toRead)); /* 206 */ + void (*tcl_ReapDetachedProcs) _ANSI_ARGS_((void)); /* 207 */ + int (*tcl_RecordAndEval) _ANSI_ARGS_((Tcl_Interp * interp, char * cmd, int flags)); /* 208 */ + int (*tcl_RecordAndEvalObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * cmdPtr, int flags)); /* 209 */ + void (*tcl_RegisterChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 210 */ + void (*tcl_RegisterObjType) _ANSI_ARGS_((Tcl_ObjType * typePtr)); /* 211 */ + Tcl_RegExp (*tcl_RegExpCompile) _ANSI_ARGS_((Tcl_Interp * interp, char * string)); /* 212 */ + int (*tcl_RegExpExec) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_RegExp regexp, CONST char * str, CONST char * start)); /* 213 */ + int (*tcl_RegExpMatch) _ANSI_ARGS_((Tcl_Interp * interp, char * str, char * pattern)); /* 214 */ + void (*tcl_RegExpRange) _ANSI_ARGS_((Tcl_RegExp regexp, int index, char ** startPtr, char ** endPtr)); /* 215 */ + void (*tcl_Release) _ANSI_ARGS_((ClientData clientData)); /* 216 */ + void (*tcl_ResetResult) _ANSI_ARGS_((Tcl_Interp * interp)); /* 217 */ + int (*tcl_ScanElement) _ANSI_ARGS_((CONST char * str, int * flagPtr)); /* 218 */ + int (*tcl_ScanCountedElement) _ANSI_ARGS_((CONST char * str, int length, int * flagPtr)); /* 219 */ + int (*tcl_Seek) _ANSI_ARGS_((Tcl_Channel chan, int offset, int mode)); /* 220 */ + int (*tcl_ServiceAll) _ANSI_ARGS_((void)); /* 221 */ + int (*tcl_ServiceEvent) _ANSI_ARGS_((int flags)); /* 222 */ + void (*tcl_SetAssocData) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_InterpDeleteProc * proc, ClientData clientData)); /* 223 */ + void (*tcl_SetChannelBufferSize) _ANSI_ARGS_((Tcl_Channel chan, int sz)); /* 224 */ + int (*tcl_SetChannelOption) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan, char * optionName, char * newValue)); /* 225 */ + int (*tcl_SetCommandInfo) _ANSI_ARGS_((Tcl_Interp * interp, char * cmdName, Tcl_CmdInfo * infoPtr)); /* 226 */ + void (*tcl_SetErrno) _ANSI_ARGS_((int err)); /* 227 */ + void (*tcl_SetErrorCode) _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); /* 228 */ + void (*tcl_SetMaxBlockTime) _ANSI_ARGS_((Tcl_Time * timePtr)); /* 229 */ + void (*tcl_SetPanicProc) _ANSI_ARGS_((Tcl_PanicProc * panicProc)); /* 230 */ + int (*tcl_SetRecursionLimit) _ANSI_ARGS_((Tcl_Interp * interp, int depth)); /* 231 */ + void (*tcl_SetResult) _ANSI_ARGS_((Tcl_Interp * interp, char * str, Tcl_FreeProc * freeProc)); /* 232 */ + int (*tcl_SetServiceMode) _ANSI_ARGS_((int mode)); /* 233 */ + void (*tcl_SetObjErrorCode) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * errorObjPtr)); /* 234 */ + void (*tcl_SetObjResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * resultObjPtr)); /* 235 */ + void (*tcl_SetStdChannel) _ANSI_ARGS_((Tcl_Channel channel, int type)); /* 236 */ + char * (*tcl_SetVar) _ANSI_ARGS_((Tcl_Interp * interp, char * varName, char * newValue, int flags)); /* 237 */ + char * (*tcl_SetVar2) _ANSI_ARGS_((Tcl_Interp * interp, char * part1, char * part2, char * newValue, int flags)); /* 238 */ + char * (*tcl_SignalId) _ANSI_ARGS_((int sig)); /* 239 */ + char * (*tcl_SignalMsg) _ANSI_ARGS_((int sig)); /* 240 */ + void (*tcl_SourceRCFile) _ANSI_ARGS_((Tcl_Interp * interp)); /* 241 */ + int (*tcl_SplitList) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * listStr, int * argcPtr, char *** argvPtr)); /* 242 */ + void (*tcl_SplitPath) _ANSI_ARGS_((CONST char * path, int * argcPtr, char *** argvPtr)); /* 243 */ + void (*tcl_StaticPackage) _ANSI_ARGS_((Tcl_Interp * interp, char * pkgName, Tcl_PackageInitProc * initProc, Tcl_PackageInitProc * safeInitProc)); /* 244 */ + int (*tcl_StringMatch) _ANSI_ARGS_((CONST char * str, CONST char * pattern)); /* 245 */ + int (*tcl_Tell) _ANSI_ARGS_((Tcl_Channel chan)); /* 246 */ + int (*tcl_TraceVar) _ANSI_ARGS_((Tcl_Interp * interp, char * varName, int flags, Tcl_VarTraceProc * proc, ClientData clientData)); /* 247 */ + int (*tcl_TraceVar2) _ANSI_ARGS_((Tcl_Interp * interp, char * part1, char * part2, int flags, Tcl_VarTraceProc * proc, ClientData clientData)); /* 248 */ + char * (*tcl_TranslateFileName) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_DString * bufferPtr)); /* 249 */ + int (*tcl_Ungets) _ANSI_ARGS_((Tcl_Channel chan, char * str, int len, int atHead)); /* 250 */ + void (*tcl_UnlinkVar) _ANSI_ARGS_((Tcl_Interp * interp, char * varName)); /* 251 */ + int (*tcl_UnregisterChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 252 */ + int (*tcl_UnsetVar) _ANSI_ARGS_((Tcl_Interp * interp, char * varName, int flags)); /* 253 */ + int (*tcl_UnsetVar2) _ANSI_ARGS_((Tcl_Interp * interp, char * part1, char * part2, int flags)); /* 254 */ + void (*tcl_UntraceVar) _ANSI_ARGS_((Tcl_Interp * interp, char * varName, int flags, Tcl_VarTraceProc * proc, ClientData clientData)); /* 255 */ + void (*tcl_UntraceVar2) _ANSI_ARGS_((Tcl_Interp * interp, char * part1, char * part2, int flags, Tcl_VarTraceProc * proc, ClientData clientData)); /* 256 */ + void (*tcl_UpdateLinkedVar) _ANSI_ARGS_((Tcl_Interp * interp, char * varName)); /* 257 */ + int (*tcl_UpVar) _ANSI_ARGS_((Tcl_Interp * interp, char * frameName, char * varName, char * localName, int flags)); /* 258 */ + int (*tcl_UpVar2) _ANSI_ARGS_((Tcl_Interp * interp, char * frameName, char * part1, char * part2, char * localName, int flags)); /* 259 */ + int (*tcl_VarEval) _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); /* 260 */ + ClientData (*tcl_VarTraceInfo) _ANSI_ARGS_((Tcl_Interp * interp, char * varName, int flags, Tcl_VarTraceProc * procPtr, ClientData prevClientData)); /* 261 */ + ClientData (*tcl_VarTraceInfo2) _ANSI_ARGS_((Tcl_Interp * interp, char * part1, char * part2, int flags, Tcl_VarTraceProc * procPtr, ClientData prevClientData)); /* 262 */ + int (*tcl_Write) _ANSI_ARGS_((Tcl_Channel chan, char * s, int slen)); /* 263 */ + void (*tcl_WrongNumArgs) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], char * message)); /* 264 */ + int (*tcl_DumpActiveMemory) _ANSI_ARGS_((char * fileName)); /* 265 */ + void (*tcl_ValidateAllMemory) _ANSI_ARGS_((char * file, int line)); /* 266 */ + void (*tcl_AppendResultVA) _ANSI_ARGS_((Tcl_Interp * interp, va_list argList)); /* 267 */ + void (*tcl_AppendStringsToObjVA) _ANSI_ARGS_((Tcl_Obj * objPtr, va_list argList)); /* 268 */ + char * (*tcl_HashStats) _ANSI_ARGS_((Tcl_HashTable * tablePtr)); /* 269 */ + char * (*tcl_ParseVar) _ANSI_ARGS_((Tcl_Interp * interp, char * str, char ** termPtr)); /* 270 */ + char * (*tcl_PkgPresent) _ANSI_ARGS_((Tcl_Interp * interp, char * name, char * version, int exact)); /* 271 */ + char * (*tcl_PkgPresentEx) _ANSI_ARGS_((Tcl_Interp * interp, char * name, char * version, int exact, ClientData * clientDataPtr)); /* 272 */ + int (*tcl_PkgProvide) _ANSI_ARGS_((Tcl_Interp * interp, char * name, char * version)); /* 273 */ + char * (*tcl_PkgRequire) _ANSI_ARGS_((Tcl_Interp * interp, char * name, char * version, int exact)); /* 274 */ + void (*tcl_SetErrorCodeVA) _ANSI_ARGS_((Tcl_Interp * interp, va_list argList)); /* 275 */ + int (*tcl_VarEvalVA) _ANSI_ARGS_((Tcl_Interp * interp, va_list argList)); /* 276 */ + Tcl_Pid (*tcl_WaitPid) _ANSI_ARGS_((Tcl_Pid pid, int * statPtr, int options)); /* 277 */ + void (*tcl_PanicVA) _ANSI_ARGS_((char * format, va_list argList)); /* 278 */ + void (*tcl_GetVersion) _ANSI_ARGS_((int * major, int * minor, int * patchLevel, int * type)); /* 279 */ + void (*tcl_InitMemory) _ANSI_ARGS_((Tcl_Interp * interp)); /* 280 */ + void *reserved281; + void *reserved282; + void *reserved283; + void *reserved284; + void *reserved285; + void (*tcl_AppendObjToObj) _ANSI_ARGS_((Tcl_Obj * objPtr, Tcl_Obj * appendObjPtr)); /* 286 */ + Tcl_Encoding (*tcl_CreateEncoding) _ANSI_ARGS_((Tcl_EncodingType * typePtr)); /* 287 */ + void (*tcl_CreateThreadExitHandler) _ANSI_ARGS_((Tcl_ExitProc * proc, ClientData clientData)); /* 288 */ + void (*tcl_DeleteThreadExitHandler) _ANSI_ARGS_((Tcl_ExitProc * proc, ClientData clientData)); /* 289 */ + void (*tcl_DiscardResult) _ANSI_ARGS_((Tcl_SavedResult * statePtr)); /* 290 */ + int (*tcl_EvalEx) _ANSI_ARGS_((Tcl_Interp * interp, char * script, int numBytes, int flags)); /* 291 */ + int (*tcl_EvalObjv) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 292 */ + int (*tcl_EvalObjEx) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int flags)); /* 293 */ + void (*tcl_ExitThread) _ANSI_ARGS_((int status)); /* 294 */ + int (*tcl_ExternalToUtf) _ANSI_ARGS_((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) _ANSI_ARGS_((Tcl_Encoding encoding, CONST char * src, int srcLen, Tcl_DString * dsPtr)); /* 296 */ + void (*tcl_FinalizeThread) _ANSI_ARGS_((void)); /* 297 */ + void (*tcl_FinalizeNotifier) _ANSI_ARGS_((ClientData clientData)); /* 298 */ + void (*tcl_FreeEncoding) _ANSI_ARGS_((Tcl_Encoding encoding)); /* 299 */ + Tcl_ThreadId (*tcl_GetCurrentThread) _ANSI_ARGS_((void)); /* 300 */ + Tcl_Encoding (*tcl_GetEncoding) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name)); /* 301 */ + char * (*tcl_GetEncodingName) _ANSI_ARGS_((Tcl_Encoding encoding)); /* 302 */ + void (*tcl_GetEncodingNames) _ANSI_ARGS_((Tcl_Interp * interp)); /* 303 */ + int (*tcl_GetIndexFromObjStruct) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, char ** tablePtr, int offset, char * msg, int flags, int * indexPtr)); /* 304 */ + VOID * (*tcl_GetThreadData) _ANSI_ARGS_((Tcl_ThreadDataKey * keyPtr, int size)); /* 305 */ + Tcl_Obj * (*tcl_GetVar2Ex) _ANSI_ARGS_((Tcl_Interp * interp, char * part1, char * part2, int flags)); /* 306 */ + ClientData (*tcl_InitNotifier) _ANSI_ARGS_((void)); /* 307 */ + void (*tcl_MutexLock) _ANSI_ARGS_((Tcl_Mutex * mutexPtr)); /* 308 */ + void (*tcl_MutexUnlock) _ANSI_ARGS_((Tcl_Mutex * mutexPtr)); /* 309 */ + void (*tcl_ConditionNotify) _ANSI_ARGS_((Tcl_Condition * condPtr)); /* 310 */ + void (*tcl_ConditionWait) _ANSI_ARGS_((Tcl_Condition * condPtr, Tcl_Mutex * mutexPtr, Tcl_Time * timePtr)); /* 311 */ + int (*tcl_NumUtfChars) _ANSI_ARGS_((CONST char * src, int len)); /* 312 */ + int (*tcl_ReadChars) _ANSI_ARGS_((Tcl_Channel channel, Tcl_Obj * objPtr, int charsToRead, int appendFlag)); /* 313 */ + void (*tcl_RestoreResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_SavedResult * statePtr)); /* 314 */ + void (*tcl_SaveResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_SavedResult * statePtr)); /* 315 */ + int (*tcl_SetSystemEncoding) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name)); /* 316 */ + Tcl_Obj * (*tcl_SetVar2Ex) _ANSI_ARGS_((Tcl_Interp * interp, char * part1, char * part2, Tcl_Obj * newValuePtr, int flags)); /* 317 */ + void (*tcl_ThreadAlert) _ANSI_ARGS_((Tcl_ThreadId threadId)); /* 318 */ + void (*tcl_ThreadQueueEvent) _ANSI_ARGS_((Tcl_ThreadId threadId, Tcl_Event* evPtr, Tcl_QueuePosition position)); /* 319 */ + Tcl_UniChar (*tcl_UniCharAtIndex) _ANSI_ARGS_((CONST char * src, int index)); /* 320 */ + Tcl_UniChar (*tcl_UniCharToLower) _ANSI_ARGS_((int ch)); /* 321 */ + Tcl_UniChar (*tcl_UniCharToTitle) _ANSI_ARGS_((int ch)); /* 322 */ + Tcl_UniChar (*tcl_UniCharToUpper) _ANSI_ARGS_((int ch)); /* 323 */ + int (*tcl_UniCharToUtf) _ANSI_ARGS_((int ch, char * buf)); /* 324 */ + char * (*tcl_UtfAtIndex) _ANSI_ARGS_((CONST char * src, int index)); /* 325 */ + int (*tcl_UtfCharComplete) _ANSI_ARGS_((CONST char * src, int len)); /* 326 */ + int (*tcl_UtfBackslash) _ANSI_ARGS_((CONST char * src, int * readPtr, char * dst)); /* 327 */ + char * (*tcl_UtfFindFirst) _ANSI_ARGS_((CONST char * src, int ch)); /* 328 */ + char * (*tcl_UtfFindLast) _ANSI_ARGS_((CONST char * src, int ch)); /* 329 */ + char * (*tcl_UtfNext) _ANSI_ARGS_((CONST char * src)); /* 330 */ + char * (*tcl_UtfPrev) _ANSI_ARGS_((CONST char * src, CONST char * start)); /* 331 */ + int (*tcl_UtfToExternal) _ANSI_ARGS_((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) _ANSI_ARGS_((Tcl_Encoding encoding, CONST char * src, int srcLen, Tcl_DString * dsPtr)); /* 333 */ + int (*tcl_UtfToLower) _ANSI_ARGS_((char * src)); /* 334 */ + int (*tcl_UtfToTitle) _ANSI_ARGS_((char * src)); /* 335 */ + int (*tcl_UtfToUniChar) _ANSI_ARGS_((CONST char * src, Tcl_UniChar * chPtr)); /* 336 */ + int (*tcl_UtfToUpper) _ANSI_ARGS_((char * src)); /* 337 */ + int (*tcl_WriteChars) _ANSI_ARGS_((Tcl_Channel chan, CONST char * src, int srcLen)); /* 338 */ + int (*tcl_WriteObj) _ANSI_ARGS_((Tcl_Channel chan, Tcl_Obj * objPtr)); /* 339 */ + char * (*tcl_GetString) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 340 */ + char * (*tcl_GetDefaultEncodingDir) _ANSI_ARGS_((void)); /* 341 */ + void (*tcl_SetDefaultEncodingDir) _ANSI_ARGS_((char * path)); /* 342 */ + void (*tcl_AlertNotifier) _ANSI_ARGS_((ClientData clientData)); /* 343 */ + void (*tcl_ServiceModeHook) _ANSI_ARGS_((int mode)); /* 344 */ + int (*tcl_UniCharIsAlnum) _ANSI_ARGS_((int ch)); /* 345 */ + int (*tcl_UniCharIsAlpha) _ANSI_ARGS_((int ch)); /* 346 */ + int (*tcl_UniCharIsDigit) _ANSI_ARGS_((int ch)); /* 347 */ + int (*tcl_UniCharIsLower) _ANSI_ARGS_((int ch)); /* 348 */ + int (*tcl_UniCharIsSpace) _ANSI_ARGS_((int ch)); /* 349 */ + int (*tcl_UniCharIsUpper) _ANSI_ARGS_((int ch)); /* 350 */ + int (*tcl_UniCharIsWordChar) _ANSI_ARGS_((int ch)); /* 351 */ + int (*tcl_UniCharLen) _ANSI_ARGS_((Tcl_UniChar * str)); /* 352 */ + int (*tcl_UniCharNcmp) _ANSI_ARGS_((const Tcl_UniChar * cs, const Tcl_UniChar * ct, size_t n)); /* 353 */ + char * (*tcl_UniCharToUtfDString) _ANSI_ARGS_((CONST Tcl_UniChar * string, int numChars, Tcl_DString * dsPtr)); /* 354 */ + Tcl_UniChar * (*tcl_UtfToUniCharDString) _ANSI_ARGS_((CONST char * string, int length, Tcl_DString * dsPtr)); /* 355 */ + Tcl_RegExp (*tcl_GetRegExpFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * patObj, int flags)); /* 356 */ + Tcl_Obj * (*tcl_EvalTokens) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Token * tokenPtr, int count)); /* 357 */ + void (*tcl_FreeParse) _ANSI_ARGS_((Tcl_Parse * parsePtr)); /* 358 */ + void (*tcl_LogCommandInfo) _ANSI_ARGS_((Tcl_Interp * interp, char * script, char * command, int length)); /* 359 */ + int (*tcl_ParseBraces) _ANSI_ARGS_((Tcl_Interp * interp, char * string, int numBytes, Tcl_Parse * parsePtr, int append, char ** termPtr)); /* 360 */ + int (*tcl_ParseCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * string, int numBytes, int nested, Tcl_Parse * parsePtr)); /* 361 */ + int (*tcl_ParseExpr) _ANSI_ARGS_((Tcl_Interp * interp, char * string, int numBytes, Tcl_Parse * parsePtr)); /* 362 */ + int (*tcl_ParseQuotedString) _ANSI_ARGS_((Tcl_Interp * interp, char * string, int numBytes, Tcl_Parse * parsePtr, int append, char ** termPtr)); /* 363 */ + int (*tcl_ParseVarName) _ANSI_ARGS_((Tcl_Interp * interp, char * string, int numBytes, Tcl_Parse * parsePtr, int append)); /* 364 */ + char * (*tcl_GetCwd) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * cwdPtr)); /* 365 */ + int (*tcl_Chdir) _ANSI_ARGS_((CONST char * dirName)); /* 366 */ +} TclStubs; + +extern TclStubs *tclStubsPtr; + +#if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifndef Tcl_PkgProvideEx +#define Tcl_PkgProvideEx \ + (tclStubsPtr->tcl_PkgProvideEx) /* 0 */ +#endif +#ifndef Tcl_PkgRequireEx +#define Tcl_PkgRequireEx \ + (tclStubsPtr->tcl_PkgRequireEx) /* 1 */ +#endif +#ifndef Tcl_Panic +#define Tcl_Panic \ + (tclStubsPtr->tcl_Panic) /* 2 */ +#endif +#ifndef Tcl_Alloc +#define Tcl_Alloc \ + (tclStubsPtr->tcl_Alloc) /* 3 */ +#endif +#ifndef Tcl_Free +#define Tcl_Free \ + (tclStubsPtr->tcl_Free) /* 4 */ +#endif +#ifndef Tcl_Realloc +#define Tcl_Realloc \ + (tclStubsPtr->tcl_Realloc) /* 5 */ +#endif +#ifndef Tcl_DbCkalloc +#define Tcl_DbCkalloc \ + (tclStubsPtr->tcl_DbCkalloc) /* 6 */ +#endif +#ifndef Tcl_DbCkfree +#define Tcl_DbCkfree \ + (tclStubsPtr->tcl_DbCkfree) /* 7 */ +#endif +#ifndef Tcl_DbCkrealloc +#define Tcl_DbCkrealloc \ + (tclStubsPtr->tcl_DbCkrealloc) /* 8 */ +#endif +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef Tcl_CreateFileHandler +#define Tcl_CreateFileHandler \ + (tclStubsPtr->tcl_CreateFileHandler) /* 9 */ +#endif +#endif /* UNIX */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef Tcl_DeleteFileHandler +#define Tcl_DeleteFileHandler \ + (tclStubsPtr->tcl_DeleteFileHandler) /* 10 */ +#endif +#endif /* UNIX */ +#ifndef Tcl_SetTimer +#define Tcl_SetTimer \ + (tclStubsPtr->tcl_SetTimer) /* 11 */ +#endif +#ifndef Tcl_Sleep +#define Tcl_Sleep \ + (tclStubsPtr->tcl_Sleep) /* 12 */ +#endif +#ifndef Tcl_WaitForEvent +#define Tcl_WaitForEvent \ + (tclStubsPtr->tcl_WaitForEvent) /* 13 */ +#endif +#ifndef Tcl_AppendAllObjTypes +#define Tcl_AppendAllObjTypes \ + (tclStubsPtr->tcl_AppendAllObjTypes) /* 14 */ +#endif +#ifndef Tcl_AppendStringsToObj +#define Tcl_AppendStringsToObj \ + (tclStubsPtr->tcl_AppendStringsToObj) /* 15 */ +#endif +#ifndef Tcl_AppendToObj +#define Tcl_AppendToObj \ + (tclStubsPtr->tcl_AppendToObj) /* 16 */ +#endif +#ifndef Tcl_ConcatObj +#define Tcl_ConcatObj \ + (tclStubsPtr->tcl_ConcatObj) /* 17 */ +#endif +#ifndef Tcl_ConvertToType +#define Tcl_ConvertToType \ + (tclStubsPtr->tcl_ConvertToType) /* 18 */ +#endif +#ifndef Tcl_DbDecrRefCount +#define Tcl_DbDecrRefCount \ + (tclStubsPtr->tcl_DbDecrRefCount) /* 19 */ +#endif +#ifndef Tcl_DbIncrRefCount +#define Tcl_DbIncrRefCount \ + (tclStubsPtr->tcl_DbIncrRefCount) /* 20 */ +#endif +#ifndef Tcl_DbIsShared +#define Tcl_DbIsShared \ + (tclStubsPtr->tcl_DbIsShared) /* 21 */ +#endif +#ifndef Tcl_DbNewBooleanObj +#define Tcl_DbNewBooleanObj \ + (tclStubsPtr->tcl_DbNewBooleanObj) /* 22 */ +#endif +#ifndef Tcl_DbNewByteArrayObj +#define Tcl_DbNewByteArrayObj \ + (tclStubsPtr->tcl_DbNewByteArrayObj) /* 23 */ +#endif +#ifndef Tcl_DbNewDoubleObj +#define Tcl_DbNewDoubleObj \ + (tclStubsPtr->tcl_DbNewDoubleObj) /* 24 */ +#endif +#ifndef Tcl_DbNewListObj +#define Tcl_DbNewListObj \ + (tclStubsPtr->tcl_DbNewListObj) /* 25 */ +#endif +#ifndef Tcl_DbNewLongObj +#define Tcl_DbNewLongObj \ + (tclStubsPtr->tcl_DbNewLongObj) /* 26 */ +#endif +#ifndef Tcl_DbNewObj +#define Tcl_DbNewObj \ + (tclStubsPtr->tcl_DbNewObj) /* 27 */ +#endif +#ifndef Tcl_DbNewStringObj +#define Tcl_DbNewStringObj \ + (tclStubsPtr->tcl_DbNewStringObj) /* 28 */ +#endif +#ifndef Tcl_DuplicateObj +#define Tcl_DuplicateObj \ + (tclStubsPtr->tcl_DuplicateObj) /* 29 */ +#endif +#ifndef TclFreeObj +#define TclFreeObj \ + (tclStubsPtr->tclFreeObj) /* 30 */ +#endif +#ifndef Tcl_GetBoolean +#define Tcl_GetBoolean \ + (tclStubsPtr->tcl_GetBoolean) /* 31 */ +#endif +#ifndef Tcl_GetBooleanFromObj +#define Tcl_GetBooleanFromObj \ + (tclStubsPtr->tcl_GetBooleanFromObj) /* 32 */ +#endif +#ifndef Tcl_GetByteArrayFromObj +#define Tcl_GetByteArrayFromObj \ + (tclStubsPtr->tcl_GetByteArrayFromObj) /* 33 */ +#endif +#ifndef Tcl_GetDouble +#define Tcl_GetDouble \ + (tclStubsPtr->tcl_GetDouble) /* 34 */ +#endif +#ifndef Tcl_GetDoubleFromObj +#define Tcl_GetDoubleFromObj \ + (tclStubsPtr->tcl_GetDoubleFromObj) /* 35 */ +#endif +#ifndef Tcl_GetIndexFromObj +#define Tcl_GetIndexFromObj \ + (tclStubsPtr->tcl_GetIndexFromObj) /* 36 */ +#endif +#ifndef Tcl_GetInt +#define Tcl_GetInt \ + (tclStubsPtr->tcl_GetInt) /* 37 */ +#endif +#ifndef Tcl_GetIntFromObj +#define Tcl_GetIntFromObj \ + (tclStubsPtr->tcl_GetIntFromObj) /* 38 */ +#endif +#ifndef Tcl_GetLongFromObj +#define Tcl_GetLongFromObj \ + (tclStubsPtr->tcl_GetLongFromObj) /* 39 */ +#endif +#ifndef Tcl_GetObjType +#define Tcl_GetObjType \ + (tclStubsPtr->tcl_GetObjType) /* 40 */ +#endif +#ifndef Tcl_GetStringFromObj +#define Tcl_GetStringFromObj \ + (tclStubsPtr->tcl_GetStringFromObj) /* 41 */ +#endif +#ifndef Tcl_InvalidateStringRep +#define Tcl_InvalidateStringRep \ + (tclStubsPtr->tcl_InvalidateStringRep) /* 42 */ +#endif +#ifndef Tcl_ListObjAppendList +#define Tcl_ListObjAppendList \ + (tclStubsPtr->tcl_ListObjAppendList) /* 43 */ +#endif +#ifndef Tcl_ListObjAppendElement +#define Tcl_ListObjAppendElement \ + (tclStubsPtr->tcl_ListObjAppendElement) /* 44 */ +#endif +#ifndef Tcl_ListObjGetElements +#define Tcl_ListObjGetElements \ + (tclStubsPtr->tcl_ListObjGetElements) /* 45 */ +#endif +#ifndef Tcl_ListObjIndex +#define Tcl_ListObjIndex \ + (tclStubsPtr->tcl_ListObjIndex) /* 46 */ +#endif +#ifndef Tcl_ListObjLength +#define Tcl_ListObjLength \ + (tclStubsPtr->tcl_ListObjLength) /* 47 */ +#endif +#ifndef Tcl_ListObjReplace +#define Tcl_ListObjReplace \ + (tclStubsPtr->tcl_ListObjReplace) /* 48 */ +#endif +#ifndef Tcl_NewBooleanObj +#define Tcl_NewBooleanObj \ + (tclStubsPtr->tcl_NewBooleanObj) /* 49 */ +#endif +#ifndef Tcl_NewByteArrayObj +#define Tcl_NewByteArrayObj \ + (tclStubsPtr->tcl_NewByteArrayObj) /* 50 */ +#endif +#ifndef Tcl_NewDoubleObj +#define Tcl_NewDoubleObj \ + (tclStubsPtr->tcl_NewDoubleObj) /* 51 */ +#endif +#ifndef Tcl_NewIntObj +#define Tcl_NewIntObj \ + (tclStubsPtr->tcl_NewIntObj) /* 52 */ +#endif +#ifndef Tcl_NewListObj +#define Tcl_NewListObj \ + (tclStubsPtr->tcl_NewListObj) /* 53 */ +#endif +#ifndef Tcl_NewLongObj +#define Tcl_NewLongObj \ + (tclStubsPtr->tcl_NewLongObj) /* 54 */ +#endif +#ifndef Tcl_NewObj +#define Tcl_NewObj \ + (tclStubsPtr->tcl_NewObj) /* 55 */ +#endif +#ifndef Tcl_NewStringObj +#define Tcl_NewStringObj \ + (tclStubsPtr->tcl_NewStringObj) /* 56 */ +#endif +#ifndef Tcl_SetBooleanObj +#define Tcl_SetBooleanObj \ + (tclStubsPtr->tcl_SetBooleanObj) /* 57 */ +#endif +#ifndef Tcl_SetByteArrayLength +#define Tcl_SetByteArrayLength \ + (tclStubsPtr->tcl_SetByteArrayLength) /* 58 */ +#endif +#ifndef Tcl_SetByteArrayObj +#define Tcl_SetByteArrayObj \ + (tclStubsPtr->tcl_SetByteArrayObj) /* 59 */ +#endif +#ifndef Tcl_SetDoubleObj +#define Tcl_SetDoubleObj \ + (tclStubsPtr->tcl_SetDoubleObj) /* 60 */ +#endif +#ifndef Tcl_SetIntObj +#define Tcl_SetIntObj \ + (tclStubsPtr->tcl_SetIntObj) /* 61 */ +#endif +#ifndef Tcl_SetListObj +#define Tcl_SetListObj \ + (tclStubsPtr->tcl_SetListObj) /* 62 */ +#endif +#ifndef Tcl_SetLongObj +#define Tcl_SetLongObj \ + (tclStubsPtr->tcl_SetLongObj) /* 63 */ +#endif +#ifndef Tcl_SetObjLength +#define Tcl_SetObjLength \ + (tclStubsPtr->tcl_SetObjLength) /* 64 */ +#endif +#ifndef Tcl_SetStringObj +#define Tcl_SetStringObj \ + (tclStubsPtr->tcl_SetStringObj) /* 65 */ +#endif +#ifndef Tcl_AddErrorInfo +#define Tcl_AddErrorInfo \ + (tclStubsPtr->tcl_AddErrorInfo) /* 66 */ +#endif +#ifndef Tcl_AddObjErrorInfo +#define Tcl_AddObjErrorInfo \ + (tclStubsPtr->tcl_AddObjErrorInfo) /* 67 */ +#endif +#ifndef Tcl_AllowExceptions +#define Tcl_AllowExceptions \ + (tclStubsPtr->tcl_AllowExceptions) /* 68 */ +#endif +#ifndef Tcl_AppendElement +#define Tcl_AppendElement \ + (tclStubsPtr->tcl_AppendElement) /* 69 */ +#endif +#ifndef Tcl_AppendResult +#define Tcl_AppendResult \ + (tclStubsPtr->tcl_AppendResult) /* 70 */ +#endif +#ifndef Tcl_AsyncCreate +#define Tcl_AsyncCreate \ + (tclStubsPtr->tcl_AsyncCreate) /* 71 */ +#endif +#ifndef Tcl_AsyncDelete +#define Tcl_AsyncDelete \ + (tclStubsPtr->tcl_AsyncDelete) /* 72 */ +#endif +#ifndef Tcl_AsyncInvoke +#define Tcl_AsyncInvoke \ + (tclStubsPtr->tcl_AsyncInvoke) /* 73 */ +#endif +#ifndef Tcl_AsyncMark +#define Tcl_AsyncMark \ + (tclStubsPtr->tcl_AsyncMark) /* 74 */ +#endif +#ifndef Tcl_AsyncReady +#define Tcl_AsyncReady \ + (tclStubsPtr->tcl_AsyncReady) /* 75 */ +#endif +#ifndef Tcl_BackgroundError +#define Tcl_BackgroundError \ + (tclStubsPtr->tcl_BackgroundError) /* 76 */ +#endif +#ifndef Tcl_Backslash +#define Tcl_Backslash \ + (tclStubsPtr->tcl_Backslash) /* 77 */ +#endif +#ifndef Tcl_BadChannelOption +#define Tcl_BadChannelOption \ + (tclStubsPtr->tcl_BadChannelOption) /* 78 */ +#endif +#ifndef Tcl_CallWhenDeleted +#define Tcl_CallWhenDeleted \ + (tclStubsPtr->tcl_CallWhenDeleted) /* 79 */ +#endif +#ifndef Tcl_CancelIdleCall +#define Tcl_CancelIdleCall \ + (tclStubsPtr->tcl_CancelIdleCall) /* 80 */ +#endif +#ifndef Tcl_Close +#define Tcl_Close \ + (tclStubsPtr->tcl_Close) /* 81 */ +#endif +#ifndef Tcl_CommandComplete +#define Tcl_CommandComplete \ + (tclStubsPtr->tcl_CommandComplete) /* 82 */ +#endif +#ifndef Tcl_Concat +#define Tcl_Concat \ + (tclStubsPtr->tcl_Concat) /* 83 */ +#endif +#ifndef Tcl_ConvertElement +#define Tcl_ConvertElement \ + (tclStubsPtr->tcl_ConvertElement) /* 84 */ +#endif +#ifndef Tcl_ConvertCountedElement +#define Tcl_ConvertCountedElement \ + (tclStubsPtr->tcl_ConvertCountedElement) /* 85 */ +#endif +#ifndef Tcl_CreateAlias +#define Tcl_CreateAlias \ + (tclStubsPtr->tcl_CreateAlias) /* 86 */ +#endif +#ifndef Tcl_CreateAliasObj +#define Tcl_CreateAliasObj \ + (tclStubsPtr->tcl_CreateAliasObj) /* 87 */ +#endif +#ifndef Tcl_CreateChannel +#define Tcl_CreateChannel \ + (tclStubsPtr->tcl_CreateChannel) /* 88 */ +#endif +#ifndef Tcl_CreateChannelHandler +#define Tcl_CreateChannelHandler \ + (tclStubsPtr->tcl_CreateChannelHandler) /* 89 */ +#endif +#ifndef Tcl_CreateCloseHandler +#define Tcl_CreateCloseHandler \ + (tclStubsPtr->tcl_CreateCloseHandler) /* 90 */ +#endif +#ifndef Tcl_CreateCommand +#define Tcl_CreateCommand \ + (tclStubsPtr->tcl_CreateCommand) /* 91 */ +#endif +#ifndef Tcl_CreateEventSource +#define Tcl_CreateEventSource \ + (tclStubsPtr->tcl_CreateEventSource) /* 92 */ +#endif +#ifndef Tcl_CreateExitHandler +#define Tcl_CreateExitHandler \ + (tclStubsPtr->tcl_CreateExitHandler) /* 93 */ +#endif +#ifndef Tcl_CreateInterp +#define Tcl_CreateInterp \ + (tclStubsPtr->tcl_CreateInterp) /* 94 */ +#endif +#ifndef Tcl_CreateMathFunc +#define Tcl_CreateMathFunc \ + (tclStubsPtr->tcl_CreateMathFunc) /* 95 */ +#endif +#ifndef Tcl_CreateObjCommand +#define Tcl_CreateObjCommand \ + (tclStubsPtr->tcl_CreateObjCommand) /* 96 */ +#endif +#ifndef Tcl_CreateSlave +#define Tcl_CreateSlave \ + (tclStubsPtr->tcl_CreateSlave) /* 97 */ +#endif +#ifndef Tcl_CreateTimerHandler +#define Tcl_CreateTimerHandler \ + (tclStubsPtr->tcl_CreateTimerHandler) /* 98 */ +#endif +#ifndef Tcl_CreateTrace +#define Tcl_CreateTrace \ + (tclStubsPtr->tcl_CreateTrace) /* 99 */ +#endif +#ifndef Tcl_DeleteAssocData +#define Tcl_DeleteAssocData \ + (tclStubsPtr->tcl_DeleteAssocData) /* 100 */ +#endif +#ifndef Tcl_DeleteChannelHandler +#define Tcl_DeleteChannelHandler \ + (tclStubsPtr->tcl_DeleteChannelHandler) /* 101 */ +#endif +#ifndef Tcl_DeleteCloseHandler +#define Tcl_DeleteCloseHandler \ + (tclStubsPtr->tcl_DeleteCloseHandler) /* 102 */ +#endif +#ifndef Tcl_DeleteCommand +#define Tcl_DeleteCommand \ + (tclStubsPtr->tcl_DeleteCommand) /* 103 */ +#endif +#ifndef Tcl_DeleteCommandFromToken +#define Tcl_DeleteCommandFromToken \ + (tclStubsPtr->tcl_DeleteCommandFromToken) /* 104 */ +#endif +#ifndef Tcl_DeleteEvents +#define Tcl_DeleteEvents \ + (tclStubsPtr->tcl_DeleteEvents) /* 105 */ +#endif +#ifndef Tcl_DeleteEventSource +#define Tcl_DeleteEventSource \ + (tclStubsPtr->tcl_DeleteEventSource) /* 106 */ +#endif +#ifndef Tcl_DeleteExitHandler +#define Tcl_DeleteExitHandler \ + (tclStubsPtr->tcl_DeleteExitHandler) /* 107 */ +#endif +#ifndef Tcl_DeleteHashEntry +#define Tcl_DeleteHashEntry \ + (tclStubsPtr->tcl_DeleteHashEntry) /* 108 */ +#endif +#ifndef Tcl_DeleteHashTable +#define Tcl_DeleteHashTable \ + (tclStubsPtr->tcl_DeleteHashTable) /* 109 */ +#endif +#ifndef Tcl_DeleteInterp +#define Tcl_DeleteInterp \ + (tclStubsPtr->tcl_DeleteInterp) /* 110 */ +#endif +#ifndef Tcl_DetachPids +#define Tcl_DetachPids \ + (tclStubsPtr->tcl_DetachPids) /* 111 */ +#endif +#ifndef Tcl_DeleteTimerHandler +#define Tcl_DeleteTimerHandler \ + (tclStubsPtr->tcl_DeleteTimerHandler) /* 112 */ +#endif +#ifndef Tcl_DeleteTrace +#define Tcl_DeleteTrace \ + (tclStubsPtr->tcl_DeleteTrace) /* 113 */ +#endif +#ifndef Tcl_DontCallWhenDeleted +#define Tcl_DontCallWhenDeleted \ + (tclStubsPtr->tcl_DontCallWhenDeleted) /* 114 */ +#endif +#ifndef Tcl_DoOneEvent +#define Tcl_DoOneEvent \ + (tclStubsPtr->tcl_DoOneEvent) /* 115 */ +#endif +#ifndef Tcl_DoWhenIdle +#define Tcl_DoWhenIdle \ + (tclStubsPtr->tcl_DoWhenIdle) /* 116 */ +#endif +#ifndef Tcl_DStringAppend +#define Tcl_DStringAppend \ + (tclStubsPtr->tcl_DStringAppend) /* 117 */ +#endif +#ifndef Tcl_DStringAppendElement +#define Tcl_DStringAppendElement \ + (tclStubsPtr->tcl_DStringAppendElement) /* 118 */ +#endif +#ifndef Tcl_DStringEndSublist +#define Tcl_DStringEndSublist \ + (tclStubsPtr->tcl_DStringEndSublist) /* 119 */ +#endif +#ifndef Tcl_DStringFree +#define Tcl_DStringFree \ + (tclStubsPtr->tcl_DStringFree) /* 120 */ +#endif +#ifndef Tcl_DStringGetResult +#define Tcl_DStringGetResult \ + (tclStubsPtr->tcl_DStringGetResult) /* 121 */ +#endif +#ifndef Tcl_DStringInit +#define Tcl_DStringInit \ + (tclStubsPtr->tcl_DStringInit) /* 122 */ +#endif +#ifndef Tcl_DStringResult +#define Tcl_DStringResult \ + (tclStubsPtr->tcl_DStringResult) /* 123 */ +#endif +#ifndef Tcl_DStringSetLength +#define Tcl_DStringSetLength \ + (tclStubsPtr->tcl_DStringSetLength) /* 124 */ +#endif +#ifndef Tcl_DStringStartSublist +#define Tcl_DStringStartSublist \ + (tclStubsPtr->tcl_DStringStartSublist) /* 125 */ +#endif +#ifndef Tcl_Eof +#define Tcl_Eof \ + (tclStubsPtr->tcl_Eof) /* 126 */ +#endif +#ifndef Tcl_ErrnoId +#define Tcl_ErrnoId \ + (tclStubsPtr->tcl_ErrnoId) /* 127 */ +#endif +#ifndef Tcl_ErrnoMsg +#define Tcl_ErrnoMsg \ + (tclStubsPtr->tcl_ErrnoMsg) /* 128 */ +#endif +#ifndef Tcl_Eval +#define Tcl_Eval \ + (tclStubsPtr->tcl_Eval) /* 129 */ +#endif +#ifndef Tcl_EvalFile +#define Tcl_EvalFile \ + (tclStubsPtr->tcl_EvalFile) /* 130 */ +#endif +#ifndef Tcl_EvalObj +#define Tcl_EvalObj \ + (tclStubsPtr->tcl_EvalObj) /* 131 */ +#endif +#ifndef Tcl_EventuallyFree +#define Tcl_EventuallyFree \ + (tclStubsPtr->tcl_EventuallyFree) /* 132 */ +#endif +#ifndef Tcl_Exit +#define Tcl_Exit \ + (tclStubsPtr->tcl_Exit) /* 133 */ +#endif +#ifndef Tcl_ExposeCommand +#define Tcl_ExposeCommand \ + (tclStubsPtr->tcl_ExposeCommand) /* 134 */ +#endif +#ifndef Tcl_ExprBoolean +#define Tcl_ExprBoolean \ + (tclStubsPtr->tcl_ExprBoolean) /* 135 */ +#endif +#ifndef Tcl_ExprBooleanObj +#define Tcl_ExprBooleanObj \ + (tclStubsPtr->tcl_ExprBooleanObj) /* 136 */ +#endif +#ifndef Tcl_ExprDouble +#define Tcl_ExprDouble \ + (tclStubsPtr->tcl_ExprDouble) /* 137 */ +#endif +#ifndef Tcl_ExprDoubleObj +#define Tcl_ExprDoubleObj \ + (tclStubsPtr->tcl_ExprDoubleObj) /* 138 */ +#endif +#ifndef Tcl_ExprLong +#define Tcl_ExprLong \ + (tclStubsPtr->tcl_ExprLong) /* 139 */ +#endif +#ifndef Tcl_ExprLongObj +#define Tcl_ExprLongObj \ + (tclStubsPtr->tcl_ExprLongObj) /* 140 */ +#endif +#ifndef Tcl_ExprObj +#define Tcl_ExprObj \ + (tclStubsPtr->tcl_ExprObj) /* 141 */ +#endif +#ifndef Tcl_ExprString +#define Tcl_ExprString \ + (tclStubsPtr->tcl_ExprString) /* 142 */ +#endif +#ifndef Tcl_Finalize +#define Tcl_Finalize \ + (tclStubsPtr->tcl_Finalize) /* 143 */ +#endif +#ifndef Tcl_FindExecutable +#define Tcl_FindExecutable \ + (tclStubsPtr->tcl_FindExecutable) /* 144 */ +#endif +#ifndef Tcl_FirstHashEntry +#define Tcl_FirstHashEntry \ + (tclStubsPtr->tcl_FirstHashEntry) /* 145 */ +#endif +#ifndef Tcl_Flush +#define Tcl_Flush \ + (tclStubsPtr->tcl_Flush) /* 146 */ +#endif +#ifndef Tcl_FreeResult +#define Tcl_FreeResult \ + (tclStubsPtr->tcl_FreeResult) /* 147 */ +#endif +#ifndef Tcl_GetAlias +#define Tcl_GetAlias \ + (tclStubsPtr->tcl_GetAlias) /* 148 */ +#endif +#ifndef Tcl_GetAliasObj +#define Tcl_GetAliasObj \ + (tclStubsPtr->tcl_GetAliasObj) /* 149 */ +#endif +#ifndef Tcl_GetAssocData +#define Tcl_GetAssocData \ + (tclStubsPtr->tcl_GetAssocData) /* 150 */ +#endif +#ifndef Tcl_GetChannel +#define Tcl_GetChannel \ + (tclStubsPtr->tcl_GetChannel) /* 151 */ +#endif +#ifndef Tcl_GetChannelBufferSize +#define Tcl_GetChannelBufferSize \ + (tclStubsPtr->tcl_GetChannelBufferSize) /* 152 */ +#endif +#ifndef Tcl_GetChannelHandle +#define Tcl_GetChannelHandle \ + (tclStubsPtr->tcl_GetChannelHandle) /* 153 */ +#endif +#ifndef Tcl_GetChannelInstanceData +#define Tcl_GetChannelInstanceData \ + (tclStubsPtr->tcl_GetChannelInstanceData) /* 154 */ +#endif +#ifndef Tcl_GetChannelMode +#define Tcl_GetChannelMode \ + (tclStubsPtr->tcl_GetChannelMode) /* 155 */ +#endif +#ifndef Tcl_GetChannelName +#define Tcl_GetChannelName \ + (tclStubsPtr->tcl_GetChannelName) /* 156 */ +#endif +#ifndef Tcl_GetChannelOption +#define Tcl_GetChannelOption \ + (tclStubsPtr->tcl_GetChannelOption) /* 157 */ +#endif +#ifndef Tcl_GetChannelType +#define Tcl_GetChannelType \ + (tclStubsPtr->tcl_GetChannelType) /* 158 */ +#endif +#ifndef Tcl_GetCommandInfo +#define Tcl_GetCommandInfo \ + (tclStubsPtr->tcl_GetCommandInfo) /* 159 */ +#endif +#ifndef Tcl_GetCommandName +#define Tcl_GetCommandName \ + (tclStubsPtr->tcl_GetCommandName) /* 160 */ +#endif +#ifndef Tcl_GetErrno +#define Tcl_GetErrno \ + (tclStubsPtr->tcl_GetErrno) /* 161 */ +#endif +#ifndef Tcl_GetHostName +#define Tcl_GetHostName \ + (tclStubsPtr->tcl_GetHostName) /* 162 */ +#endif +#ifndef Tcl_GetInterpPath +#define Tcl_GetInterpPath \ + (tclStubsPtr->tcl_GetInterpPath) /* 163 */ +#endif +#ifndef Tcl_GetMaster +#define Tcl_GetMaster \ + (tclStubsPtr->tcl_GetMaster) /* 164 */ +#endif +#ifndef Tcl_GetNameOfExecutable +#define Tcl_GetNameOfExecutable \ + (tclStubsPtr->tcl_GetNameOfExecutable) /* 165 */ +#endif +#ifndef Tcl_GetObjResult +#define Tcl_GetObjResult \ + (tclStubsPtr->tcl_GetObjResult) /* 166 */ +#endif +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef Tcl_GetOpenFile +#define Tcl_GetOpenFile \ + (tclStubsPtr->tcl_GetOpenFile) /* 167 */ +#endif +#endif /* UNIX */ +#ifndef Tcl_GetPathType +#define Tcl_GetPathType \ + (tclStubsPtr->tcl_GetPathType) /* 168 */ +#endif +#ifndef Tcl_Gets +#define Tcl_Gets \ + (tclStubsPtr->tcl_Gets) /* 169 */ +#endif +#ifndef Tcl_GetsObj +#define Tcl_GetsObj \ + (tclStubsPtr->tcl_GetsObj) /* 170 */ +#endif +#ifndef Tcl_GetServiceMode +#define Tcl_GetServiceMode \ + (tclStubsPtr->tcl_GetServiceMode) /* 171 */ +#endif +#ifndef Tcl_GetSlave +#define Tcl_GetSlave \ + (tclStubsPtr->tcl_GetSlave) /* 172 */ +#endif +#ifndef Tcl_GetStdChannel +#define Tcl_GetStdChannel \ + (tclStubsPtr->tcl_GetStdChannel) /* 173 */ +#endif +#ifndef Tcl_GetStringResult +#define Tcl_GetStringResult \ + (tclStubsPtr->tcl_GetStringResult) /* 174 */ +#endif +#ifndef Tcl_GetVar +#define Tcl_GetVar \ + (tclStubsPtr->tcl_GetVar) /* 175 */ +#endif +#ifndef Tcl_GetVar2 +#define Tcl_GetVar2 \ + (tclStubsPtr->tcl_GetVar2) /* 176 */ +#endif +#ifndef Tcl_GlobalEval +#define Tcl_GlobalEval \ + (tclStubsPtr->tcl_GlobalEval) /* 177 */ +#endif +#ifndef Tcl_GlobalEvalObj +#define Tcl_GlobalEvalObj \ + (tclStubsPtr->tcl_GlobalEvalObj) /* 178 */ +#endif +#ifndef Tcl_HideCommand +#define Tcl_HideCommand \ + (tclStubsPtr->tcl_HideCommand) /* 179 */ +#endif +#ifndef Tcl_Init +#define Tcl_Init \ + (tclStubsPtr->tcl_Init) /* 180 */ +#endif +#ifndef Tcl_InitHashTable +#define Tcl_InitHashTable \ + (tclStubsPtr->tcl_InitHashTable) /* 181 */ +#endif +#ifndef Tcl_InputBlocked +#define Tcl_InputBlocked \ + (tclStubsPtr->tcl_InputBlocked) /* 182 */ +#endif +#ifndef Tcl_InputBuffered +#define Tcl_InputBuffered \ + (tclStubsPtr->tcl_InputBuffered) /* 183 */ +#endif +#ifndef Tcl_InterpDeleted +#define Tcl_InterpDeleted \ + (tclStubsPtr->tcl_InterpDeleted) /* 184 */ +#endif +#ifndef Tcl_IsSafe +#define Tcl_IsSafe \ + (tclStubsPtr->tcl_IsSafe) /* 185 */ +#endif +#ifndef Tcl_JoinPath +#define Tcl_JoinPath \ + (tclStubsPtr->tcl_JoinPath) /* 186 */ +#endif +#ifndef Tcl_LinkVar +#define Tcl_LinkVar \ + (tclStubsPtr->tcl_LinkVar) /* 187 */ +#endif +/* Slot 188 is reserved */ +#ifndef Tcl_MakeFileChannel +#define Tcl_MakeFileChannel \ + (tclStubsPtr->tcl_MakeFileChannel) /* 189 */ +#endif +#ifndef Tcl_MakeSafe +#define Tcl_MakeSafe \ + (tclStubsPtr->tcl_MakeSafe) /* 190 */ +#endif +#ifndef Tcl_MakeTcpClientChannel +#define Tcl_MakeTcpClientChannel \ + (tclStubsPtr->tcl_MakeTcpClientChannel) /* 191 */ +#endif +#ifndef Tcl_Merge +#define Tcl_Merge \ + (tclStubsPtr->tcl_Merge) /* 192 */ +#endif +#ifndef Tcl_NextHashEntry +#define Tcl_NextHashEntry \ + (tclStubsPtr->tcl_NextHashEntry) /* 193 */ +#endif +#ifndef Tcl_NotifyChannel +#define Tcl_NotifyChannel \ + (tclStubsPtr->tcl_NotifyChannel) /* 194 */ +#endif +#ifndef Tcl_ObjGetVar2 +#define Tcl_ObjGetVar2 \ + (tclStubsPtr->tcl_ObjGetVar2) /* 195 */ +#endif +#ifndef Tcl_ObjSetVar2 +#define Tcl_ObjSetVar2 \ + (tclStubsPtr->tcl_ObjSetVar2) /* 196 */ +#endif +#ifndef Tcl_OpenCommandChannel +#define Tcl_OpenCommandChannel \ + (tclStubsPtr->tcl_OpenCommandChannel) /* 197 */ +#endif +#ifndef Tcl_OpenFileChannel +#define Tcl_OpenFileChannel \ + (tclStubsPtr->tcl_OpenFileChannel) /* 198 */ +#endif +#ifndef Tcl_OpenTcpClient +#define Tcl_OpenTcpClient \ + (tclStubsPtr->tcl_OpenTcpClient) /* 199 */ +#endif +#ifndef Tcl_OpenTcpServer +#define Tcl_OpenTcpServer \ + (tclStubsPtr->tcl_OpenTcpServer) /* 200 */ +#endif +#ifndef Tcl_Preserve +#define Tcl_Preserve \ + (tclStubsPtr->tcl_Preserve) /* 201 */ +#endif +#ifndef Tcl_PrintDouble +#define Tcl_PrintDouble \ + (tclStubsPtr->tcl_PrintDouble) /* 202 */ +#endif +#ifndef Tcl_PutEnv +#define Tcl_PutEnv \ + (tclStubsPtr->tcl_PutEnv) /* 203 */ +#endif +#ifndef Tcl_PosixError +#define Tcl_PosixError \ + (tclStubsPtr->tcl_PosixError) /* 204 */ +#endif +#ifndef Tcl_QueueEvent +#define Tcl_QueueEvent \ + (tclStubsPtr->tcl_QueueEvent) /* 205 */ +#endif +#ifndef Tcl_Read +#define Tcl_Read \ + (tclStubsPtr->tcl_Read) /* 206 */ +#endif +#ifndef Tcl_ReapDetachedProcs +#define Tcl_ReapDetachedProcs \ + (tclStubsPtr->tcl_ReapDetachedProcs) /* 207 */ +#endif +#ifndef Tcl_RecordAndEval +#define Tcl_RecordAndEval \ + (tclStubsPtr->tcl_RecordAndEval) /* 208 */ +#endif +#ifndef Tcl_RecordAndEvalObj +#define Tcl_RecordAndEvalObj \ + (tclStubsPtr->tcl_RecordAndEvalObj) /* 209 */ +#endif +#ifndef Tcl_RegisterChannel +#define Tcl_RegisterChannel \ + (tclStubsPtr->tcl_RegisterChannel) /* 210 */ +#endif +#ifndef Tcl_RegisterObjType +#define Tcl_RegisterObjType \ + (tclStubsPtr->tcl_RegisterObjType) /* 211 */ +#endif +#ifndef Tcl_RegExpCompile +#define Tcl_RegExpCompile \ + (tclStubsPtr->tcl_RegExpCompile) /* 212 */ +#endif +#ifndef Tcl_RegExpExec +#define Tcl_RegExpExec \ + (tclStubsPtr->tcl_RegExpExec) /* 213 */ +#endif +#ifndef Tcl_RegExpMatch +#define Tcl_RegExpMatch \ + (tclStubsPtr->tcl_RegExpMatch) /* 214 */ +#endif +#ifndef Tcl_RegExpRange +#define Tcl_RegExpRange \ + (tclStubsPtr->tcl_RegExpRange) /* 215 */ +#endif +#ifndef Tcl_Release +#define Tcl_Release \ + (tclStubsPtr->tcl_Release) /* 216 */ +#endif +#ifndef Tcl_ResetResult +#define Tcl_ResetResult \ + (tclStubsPtr->tcl_ResetResult) /* 217 */ +#endif +#ifndef Tcl_ScanElement +#define Tcl_ScanElement \ + (tclStubsPtr->tcl_ScanElement) /* 218 */ +#endif +#ifndef Tcl_ScanCountedElement +#define Tcl_ScanCountedElement \ + (tclStubsPtr->tcl_ScanCountedElement) /* 219 */ +#endif +#ifndef Tcl_Seek +#define Tcl_Seek \ + (tclStubsPtr->tcl_Seek) /* 220 */ +#endif +#ifndef Tcl_ServiceAll +#define Tcl_ServiceAll \ + (tclStubsPtr->tcl_ServiceAll) /* 221 */ +#endif +#ifndef Tcl_ServiceEvent +#define Tcl_ServiceEvent \ + (tclStubsPtr->tcl_ServiceEvent) /* 222 */ +#endif +#ifndef Tcl_SetAssocData +#define Tcl_SetAssocData \ + (tclStubsPtr->tcl_SetAssocData) /* 223 */ +#endif +#ifndef Tcl_SetChannelBufferSize +#define Tcl_SetChannelBufferSize \ + (tclStubsPtr->tcl_SetChannelBufferSize) /* 224 */ +#endif +#ifndef Tcl_SetChannelOption +#define Tcl_SetChannelOption \ + (tclStubsPtr->tcl_SetChannelOption) /* 225 */ +#endif +#ifndef Tcl_SetCommandInfo +#define Tcl_SetCommandInfo \ + (tclStubsPtr->tcl_SetCommandInfo) /* 226 */ +#endif +#ifndef Tcl_SetErrno +#define Tcl_SetErrno \ + (tclStubsPtr->tcl_SetErrno) /* 227 */ +#endif +#ifndef Tcl_SetErrorCode +#define Tcl_SetErrorCode \ + (tclStubsPtr->tcl_SetErrorCode) /* 228 */ +#endif +#ifndef Tcl_SetMaxBlockTime +#define Tcl_SetMaxBlockTime \ + (tclStubsPtr->tcl_SetMaxBlockTime) /* 229 */ +#endif +#ifndef Tcl_SetPanicProc +#define Tcl_SetPanicProc \ + (tclStubsPtr->tcl_SetPanicProc) /* 230 */ +#endif +#ifndef Tcl_SetRecursionLimit +#define Tcl_SetRecursionLimit \ + (tclStubsPtr->tcl_SetRecursionLimit) /* 231 */ +#endif +#ifndef Tcl_SetResult +#define Tcl_SetResult \ + (tclStubsPtr->tcl_SetResult) /* 232 */ +#endif +#ifndef Tcl_SetServiceMode +#define Tcl_SetServiceMode \ + (tclStubsPtr->tcl_SetServiceMode) /* 233 */ +#endif +#ifndef Tcl_SetObjErrorCode +#define Tcl_SetObjErrorCode \ + (tclStubsPtr->tcl_SetObjErrorCode) /* 234 */ +#endif +#ifndef Tcl_SetObjResult +#define Tcl_SetObjResult \ + (tclStubsPtr->tcl_SetObjResult) /* 235 */ +#endif +#ifndef Tcl_SetStdChannel +#define Tcl_SetStdChannel \ + (tclStubsPtr->tcl_SetStdChannel) /* 236 */ +#endif +#ifndef Tcl_SetVar +#define Tcl_SetVar \ + (tclStubsPtr->tcl_SetVar) /* 237 */ +#endif +#ifndef Tcl_SetVar2 +#define Tcl_SetVar2 \ + (tclStubsPtr->tcl_SetVar2) /* 238 */ +#endif +#ifndef Tcl_SignalId +#define Tcl_SignalId \ + (tclStubsPtr->tcl_SignalId) /* 239 */ +#endif +#ifndef Tcl_SignalMsg +#define Tcl_SignalMsg \ + (tclStubsPtr->tcl_SignalMsg) /* 240 */ +#endif +#ifndef Tcl_SourceRCFile +#define Tcl_SourceRCFile \ + (tclStubsPtr->tcl_SourceRCFile) /* 241 */ +#endif +#ifndef Tcl_SplitList +#define Tcl_SplitList \ + (tclStubsPtr->tcl_SplitList) /* 242 */ +#endif +#ifndef Tcl_SplitPath +#define Tcl_SplitPath \ + (tclStubsPtr->tcl_SplitPath) /* 243 */ +#endif +#ifndef Tcl_StaticPackage +#define Tcl_StaticPackage \ + (tclStubsPtr->tcl_StaticPackage) /* 244 */ +#endif +#ifndef Tcl_StringMatch +#define Tcl_StringMatch \ + (tclStubsPtr->tcl_StringMatch) /* 245 */ +#endif +#ifndef Tcl_Tell +#define Tcl_Tell \ + (tclStubsPtr->tcl_Tell) /* 246 */ +#endif +#ifndef Tcl_TraceVar +#define Tcl_TraceVar \ + (tclStubsPtr->tcl_TraceVar) /* 247 */ +#endif +#ifndef Tcl_TraceVar2 +#define Tcl_TraceVar2 \ + (tclStubsPtr->tcl_TraceVar2) /* 248 */ +#endif +#ifndef Tcl_TranslateFileName +#define Tcl_TranslateFileName \ + (tclStubsPtr->tcl_TranslateFileName) /* 249 */ +#endif +#ifndef Tcl_Ungets +#define Tcl_Ungets \ + (tclStubsPtr->tcl_Ungets) /* 250 */ +#endif +#ifndef Tcl_UnlinkVar +#define Tcl_UnlinkVar \ + (tclStubsPtr->tcl_UnlinkVar) /* 251 */ +#endif +#ifndef Tcl_UnregisterChannel +#define Tcl_UnregisterChannel \ + (tclStubsPtr->tcl_UnregisterChannel) /* 252 */ +#endif +#ifndef Tcl_UnsetVar +#define Tcl_UnsetVar \ + (tclStubsPtr->tcl_UnsetVar) /* 253 */ +#endif +#ifndef Tcl_UnsetVar2 +#define Tcl_UnsetVar2 \ + (tclStubsPtr->tcl_UnsetVar2) /* 254 */ +#endif +#ifndef Tcl_UntraceVar +#define Tcl_UntraceVar \ + (tclStubsPtr->tcl_UntraceVar) /* 255 */ +#endif +#ifndef Tcl_UntraceVar2 +#define Tcl_UntraceVar2 \ + (tclStubsPtr->tcl_UntraceVar2) /* 256 */ +#endif +#ifndef Tcl_UpdateLinkedVar +#define Tcl_UpdateLinkedVar \ + (tclStubsPtr->tcl_UpdateLinkedVar) /* 257 */ +#endif +#ifndef Tcl_UpVar +#define Tcl_UpVar \ + (tclStubsPtr->tcl_UpVar) /* 258 */ +#endif +#ifndef Tcl_UpVar2 +#define Tcl_UpVar2 \ + (tclStubsPtr->tcl_UpVar2) /* 259 */ +#endif +#ifndef Tcl_VarEval +#define Tcl_VarEval \ + (tclStubsPtr->tcl_VarEval) /* 260 */ +#endif +#ifndef Tcl_VarTraceInfo +#define Tcl_VarTraceInfo \ + (tclStubsPtr->tcl_VarTraceInfo) /* 261 */ +#endif +#ifndef Tcl_VarTraceInfo2 +#define Tcl_VarTraceInfo2 \ + (tclStubsPtr->tcl_VarTraceInfo2) /* 262 */ +#endif +#ifndef Tcl_Write +#define Tcl_Write \ + (tclStubsPtr->tcl_Write) /* 263 */ +#endif +#ifndef Tcl_WrongNumArgs +#define Tcl_WrongNumArgs \ + (tclStubsPtr->tcl_WrongNumArgs) /* 264 */ +#endif +#ifndef Tcl_DumpActiveMemory +#define Tcl_DumpActiveMemory \ + (tclStubsPtr->tcl_DumpActiveMemory) /* 265 */ +#endif +#ifndef Tcl_ValidateAllMemory +#define Tcl_ValidateAllMemory \ + (tclStubsPtr->tcl_ValidateAllMemory) /* 266 */ +#endif +#ifndef Tcl_AppendResultVA +#define Tcl_AppendResultVA \ + (tclStubsPtr->tcl_AppendResultVA) /* 267 */ +#endif +#ifndef Tcl_AppendStringsToObjVA +#define Tcl_AppendStringsToObjVA \ + (tclStubsPtr->tcl_AppendStringsToObjVA) /* 268 */ +#endif +#ifndef Tcl_HashStats +#define Tcl_HashStats \ + (tclStubsPtr->tcl_HashStats) /* 269 */ +#endif +#ifndef Tcl_ParseVar +#define Tcl_ParseVar \ + (tclStubsPtr->tcl_ParseVar) /* 270 */ +#endif +#ifndef Tcl_PkgPresent +#define Tcl_PkgPresent \ + (tclStubsPtr->tcl_PkgPresent) /* 271 */ +#endif +#ifndef Tcl_PkgPresentEx +#define Tcl_PkgPresentEx \ + (tclStubsPtr->tcl_PkgPresentEx) /* 272 */ +#endif +#ifndef Tcl_PkgProvide +#define Tcl_PkgProvide \ + (tclStubsPtr->tcl_PkgProvide) /* 273 */ +#endif +#ifndef Tcl_PkgRequire +#define Tcl_PkgRequire \ + (tclStubsPtr->tcl_PkgRequire) /* 274 */ +#endif +#ifndef Tcl_SetErrorCodeVA +#define Tcl_SetErrorCodeVA \ + (tclStubsPtr->tcl_SetErrorCodeVA) /* 275 */ +#endif +#ifndef Tcl_VarEvalVA +#define Tcl_VarEvalVA \ + (tclStubsPtr->tcl_VarEvalVA) /* 276 */ +#endif +#ifndef Tcl_WaitPid +#define Tcl_WaitPid \ + (tclStubsPtr->tcl_WaitPid) /* 277 */ +#endif +#ifndef Tcl_PanicVA +#define Tcl_PanicVA \ + (tclStubsPtr->tcl_PanicVA) /* 278 */ +#endif +#ifndef Tcl_GetVersion +#define Tcl_GetVersion \ + (tclStubsPtr->tcl_GetVersion) /* 279 */ +#endif +#ifndef Tcl_InitMemory +#define Tcl_InitMemory \ + (tclStubsPtr->tcl_InitMemory) /* 280 */ +#endif +/* Slot 281 is reserved */ +/* Slot 282 is reserved */ +/* Slot 283 is reserved */ +/* Slot 284 is reserved */ +/* Slot 285 is reserved */ +#ifndef Tcl_AppendObjToObj +#define Tcl_AppendObjToObj \ + (tclStubsPtr->tcl_AppendObjToObj) /* 286 */ +#endif +#ifndef Tcl_CreateEncoding +#define Tcl_CreateEncoding \ + (tclStubsPtr->tcl_CreateEncoding) /* 287 */ +#endif +#ifndef Tcl_CreateThreadExitHandler +#define Tcl_CreateThreadExitHandler \ + (tclStubsPtr->tcl_CreateThreadExitHandler) /* 288 */ +#endif +#ifndef Tcl_DeleteThreadExitHandler +#define Tcl_DeleteThreadExitHandler \ + (tclStubsPtr->tcl_DeleteThreadExitHandler) /* 289 */ +#endif +#ifndef Tcl_DiscardResult +#define Tcl_DiscardResult \ + (tclStubsPtr->tcl_DiscardResult) /* 290 */ +#endif +#ifndef Tcl_EvalEx +#define Tcl_EvalEx \ + (tclStubsPtr->tcl_EvalEx) /* 291 */ +#endif +#ifndef Tcl_EvalObjv +#define Tcl_EvalObjv \ + (tclStubsPtr->tcl_EvalObjv) /* 292 */ +#endif +#ifndef Tcl_EvalObjEx +#define Tcl_EvalObjEx \ + (tclStubsPtr->tcl_EvalObjEx) /* 293 */ +#endif +#ifndef Tcl_ExitThread +#define Tcl_ExitThread \ + (tclStubsPtr->tcl_ExitThread) /* 294 */ +#endif +#ifndef Tcl_ExternalToUtf +#define Tcl_ExternalToUtf \ + (tclStubsPtr->tcl_ExternalToUtf) /* 295 */ +#endif +#ifndef Tcl_ExternalToUtfDString +#define Tcl_ExternalToUtfDString \ + (tclStubsPtr->tcl_ExternalToUtfDString) /* 296 */ +#endif +#ifndef Tcl_FinalizeThread +#define Tcl_FinalizeThread \ + (tclStubsPtr->tcl_FinalizeThread) /* 297 */ +#endif +#ifndef Tcl_FinalizeNotifier +#define Tcl_FinalizeNotifier \ + (tclStubsPtr->tcl_FinalizeNotifier) /* 298 */ +#endif +#ifndef Tcl_FreeEncoding +#define Tcl_FreeEncoding \ + (tclStubsPtr->tcl_FreeEncoding) /* 299 */ +#endif +#ifndef Tcl_GetCurrentThread +#define Tcl_GetCurrentThread \ + (tclStubsPtr->tcl_GetCurrentThread) /* 300 */ +#endif +#ifndef Tcl_GetEncoding +#define Tcl_GetEncoding \ + (tclStubsPtr->tcl_GetEncoding) /* 301 */ +#endif +#ifndef Tcl_GetEncodingName +#define Tcl_GetEncodingName \ + (tclStubsPtr->tcl_GetEncodingName) /* 302 */ +#endif +#ifndef Tcl_GetEncodingNames +#define Tcl_GetEncodingNames \ + (tclStubsPtr->tcl_GetEncodingNames) /* 303 */ +#endif +#ifndef Tcl_GetIndexFromObjStruct +#define Tcl_GetIndexFromObjStruct \ + (tclStubsPtr->tcl_GetIndexFromObjStruct) /* 304 */ +#endif +#ifndef Tcl_GetThreadData +#define Tcl_GetThreadData \ + (tclStubsPtr->tcl_GetThreadData) /* 305 */ +#endif +#ifndef Tcl_GetVar2Ex +#define Tcl_GetVar2Ex \ + (tclStubsPtr->tcl_GetVar2Ex) /* 306 */ +#endif +#ifndef Tcl_InitNotifier +#define Tcl_InitNotifier \ + (tclStubsPtr->tcl_InitNotifier) /* 307 */ +#endif +#ifndef Tcl_MutexLock +#define Tcl_MutexLock \ + (tclStubsPtr->tcl_MutexLock) /* 308 */ +#endif +#ifndef Tcl_MutexUnlock +#define Tcl_MutexUnlock \ + (tclStubsPtr->tcl_MutexUnlock) /* 309 */ +#endif +#ifndef Tcl_ConditionNotify +#define Tcl_ConditionNotify \ + (tclStubsPtr->tcl_ConditionNotify) /* 310 */ +#endif +#ifndef Tcl_ConditionWait +#define Tcl_ConditionWait \ + (tclStubsPtr->tcl_ConditionWait) /* 311 */ +#endif +#ifndef Tcl_NumUtfChars +#define Tcl_NumUtfChars \ + (tclStubsPtr->tcl_NumUtfChars) /* 312 */ +#endif +#ifndef Tcl_ReadChars +#define Tcl_ReadChars \ + (tclStubsPtr->tcl_ReadChars) /* 313 */ +#endif +#ifndef Tcl_RestoreResult +#define Tcl_RestoreResult \ + (tclStubsPtr->tcl_RestoreResult) /* 314 */ +#endif +#ifndef Tcl_SaveResult +#define Tcl_SaveResult \ + (tclStubsPtr->tcl_SaveResult) /* 315 */ +#endif +#ifndef Tcl_SetSystemEncoding +#define Tcl_SetSystemEncoding \ + (tclStubsPtr->tcl_SetSystemEncoding) /* 316 */ +#endif +#ifndef Tcl_SetVar2Ex +#define Tcl_SetVar2Ex \ + (tclStubsPtr->tcl_SetVar2Ex) /* 317 */ +#endif +#ifndef Tcl_ThreadAlert +#define Tcl_ThreadAlert \ + (tclStubsPtr->tcl_ThreadAlert) /* 318 */ +#endif +#ifndef Tcl_ThreadQueueEvent +#define Tcl_ThreadQueueEvent \ + (tclStubsPtr->tcl_ThreadQueueEvent) /* 319 */ +#endif +#ifndef Tcl_UniCharAtIndex +#define Tcl_UniCharAtIndex \ + (tclStubsPtr->tcl_UniCharAtIndex) /* 320 */ +#endif +#ifndef Tcl_UniCharToLower +#define Tcl_UniCharToLower \ + (tclStubsPtr->tcl_UniCharToLower) /* 321 */ +#endif +#ifndef Tcl_UniCharToTitle +#define Tcl_UniCharToTitle \ + (tclStubsPtr->tcl_UniCharToTitle) /* 322 */ +#endif +#ifndef Tcl_UniCharToUpper +#define Tcl_UniCharToUpper \ + (tclStubsPtr->tcl_UniCharToUpper) /* 323 */ +#endif +#ifndef Tcl_UniCharToUtf +#define Tcl_UniCharToUtf \ + (tclStubsPtr->tcl_UniCharToUtf) /* 324 */ +#endif +#ifndef Tcl_UtfAtIndex +#define Tcl_UtfAtIndex \ + (tclStubsPtr->tcl_UtfAtIndex) /* 325 */ +#endif +#ifndef Tcl_UtfCharComplete +#define Tcl_UtfCharComplete \ + (tclStubsPtr->tcl_UtfCharComplete) /* 326 */ +#endif +#ifndef Tcl_UtfBackslash +#define Tcl_UtfBackslash \ + (tclStubsPtr->tcl_UtfBackslash) /* 327 */ +#endif +#ifndef Tcl_UtfFindFirst +#define Tcl_UtfFindFirst \ + (tclStubsPtr->tcl_UtfFindFirst) /* 328 */ +#endif +#ifndef Tcl_UtfFindLast +#define Tcl_UtfFindLast \ + (tclStubsPtr->tcl_UtfFindLast) /* 329 */ +#endif +#ifndef Tcl_UtfNext +#define Tcl_UtfNext \ + (tclStubsPtr->tcl_UtfNext) /* 330 */ +#endif +#ifndef Tcl_UtfPrev +#define Tcl_UtfPrev \ + (tclStubsPtr->tcl_UtfPrev) /* 331 */ +#endif +#ifndef Tcl_UtfToExternal +#define Tcl_UtfToExternal \ + (tclStubsPtr->tcl_UtfToExternal) /* 332 */ +#endif +#ifndef Tcl_UtfToExternalDString +#define Tcl_UtfToExternalDString \ + (tclStubsPtr->tcl_UtfToExternalDString) /* 333 */ +#endif +#ifndef Tcl_UtfToLower +#define Tcl_UtfToLower \ + (tclStubsPtr->tcl_UtfToLower) /* 334 */ +#endif +#ifndef Tcl_UtfToTitle +#define Tcl_UtfToTitle \ + (tclStubsPtr->tcl_UtfToTitle) /* 335 */ +#endif +#ifndef Tcl_UtfToUniChar +#define Tcl_UtfToUniChar \ + (tclStubsPtr->tcl_UtfToUniChar) /* 336 */ +#endif +#ifndef Tcl_UtfToUpper +#define Tcl_UtfToUpper \ + (tclStubsPtr->tcl_UtfToUpper) /* 337 */ +#endif +#ifndef Tcl_WriteChars +#define Tcl_WriteChars \ + (tclStubsPtr->tcl_WriteChars) /* 338 */ +#endif +#ifndef Tcl_WriteObj +#define Tcl_WriteObj \ + (tclStubsPtr->tcl_WriteObj) /* 339 */ +#endif +#ifndef Tcl_GetString +#define Tcl_GetString \ + (tclStubsPtr->tcl_GetString) /* 340 */ +#endif +#ifndef Tcl_GetDefaultEncodingDir +#define Tcl_GetDefaultEncodingDir \ + (tclStubsPtr->tcl_GetDefaultEncodingDir) /* 341 */ +#endif +#ifndef Tcl_SetDefaultEncodingDir +#define Tcl_SetDefaultEncodingDir \ + (tclStubsPtr->tcl_SetDefaultEncodingDir) /* 342 */ +#endif +#ifndef Tcl_AlertNotifier +#define Tcl_AlertNotifier \ + (tclStubsPtr->tcl_AlertNotifier) /* 343 */ +#endif +#ifndef Tcl_ServiceModeHook +#define Tcl_ServiceModeHook \ + (tclStubsPtr->tcl_ServiceModeHook) /* 344 */ +#endif +#ifndef Tcl_UniCharIsAlnum +#define Tcl_UniCharIsAlnum \ + (tclStubsPtr->tcl_UniCharIsAlnum) /* 345 */ +#endif +#ifndef Tcl_UniCharIsAlpha +#define Tcl_UniCharIsAlpha \ + (tclStubsPtr->tcl_UniCharIsAlpha) /* 346 */ +#endif +#ifndef Tcl_UniCharIsDigit +#define Tcl_UniCharIsDigit \ + (tclStubsPtr->tcl_UniCharIsDigit) /* 347 */ +#endif +#ifndef Tcl_UniCharIsLower +#define Tcl_UniCharIsLower \ + (tclStubsPtr->tcl_UniCharIsLower) /* 348 */ +#endif +#ifndef Tcl_UniCharIsSpace +#define Tcl_UniCharIsSpace \ + (tclStubsPtr->tcl_UniCharIsSpace) /* 349 */ +#endif +#ifndef Tcl_UniCharIsUpper +#define Tcl_UniCharIsUpper \ + (tclStubsPtr->tcl_UniCharIsUpper) /* 350 */ +#endif +#ifndef Tcl_UniCharIsWordChar +#define Tcl_UniCharIsWordChar \ + (tclStubsPtr->tcl_UniCharIsWordChar) /* 351 */ +#endif +#ifndef Tcl_UniCharLen +#define Tcl_UniCharLen \ + (tclStubsPtr->tcl_UniCharLen) /* 352 */ +#endif +#ifndef Tcl_UniCharNcmp +#define Tcl_UniCharNcmp \ + (tclStubsPtr->tcl_UniCharNcmp) /* 353 */ +#endif +#ifndef Tcl_UniCharToUtfDString +#define Tcl_UniCharToUtfDString \ + (tclStubsPtr->tcl_UniCharToUtfDString) /* 354 */ +#endif +#ifndef Tcl_UtfToUniCharDString +#define Tcl_UtfToUniCharDString \ + (tclStubsPtr->tcl_UtfToUniCharDString) /* 355 */ +#endif +#ifndef Tcl_GetRegExpFromObj +#define Tcl_GetRegExpFromObj \ + (tclStubsPtr->tcl_GetRegExpFromObj) /* 356 */ +#endif +#ifndef Tcl_EvalTokens +#define Tcl_EvalTokens \ + (tclStubsPtr->tcl_EvalTokens) /* 357 */ +#endif +#ifndef Tcl_FreeParse +#define Tcl_FreeParse \ + (tclStubsPtr->tcl_FreeParse) /* 358 */ +#endif +#ifndef Tcl_LogCommandInfo +#define Tcl_LogCommandInfo \ + (tclStubsPtr->tcl_LogCommandInfo) /* 359 */ +#endif +#ifndef Tcl_ParseBraces +#define Tcl_ParseBraces \ + (tclStubsPtr->tcl_ParseBraces) /* 360 */ +#endif +#ifndef Tcl_ParseCommand +#define Tcl_ParseCommand \ + (tclStubsPtr->tcl_ParseCommand) /* 361 */ +#endif +#ifndef Tcl_ParseExpr +#define Tcl_ParseExpr \ + (tclStubsPtr->tcl_ParseExpr) /* 362 */ +#endif +#ifndef Tcl_ParseQuotedString +#define Tcl_ParseQuotedString \ + (tclStubsPtr->tcl_ParseQuotedString) /* 363 */ +#endif +#ifndef Tcl_ParseVarName +#define Tcl_ParseVarName \ + (tclStubsPtr->tcl_ParseVarName) /* 364 */ +#endif +#ifndef Tcl_GetCwd +#define Tcl_GetCwd \ + (tclStubsPtr->tcl_GetCwd) /* 365 */ +#endif +#ifndef Tcl_Chdir +#define Tcl_Chdir \ + (tclStubsPtr->tcl_Chdir) /* 366 */ +#endif + +#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#endif /* _TCLDECLS */ + ADDED generic/tclEncoding.c Index: generic/tclEncoding.c ================================================================== --- /dev/null +++ generic/tclEncoding.c @@ -0,0 +1,2685 @@ +/* + * 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. + * + * RCS: @(#) $Id: tclEncoding.c,v 1.1.2.12 1999/04/14 00:33:21 surles Exp $ + */ + +#include "tclInt.h" +#include "tclPort.h" + +typedef size_t (LengthProc)_ANSI_ARGS_((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; + /* Procedure to convert from external + * encoding into UTF-8. */ + Tcl_EncodingConvertProc *fromUtfProc; + /* Procedure to convert from UTF-8 into + * external encoding. */ + Tcl_EncodingFreeProc *freeProc; + /* If non-NULL, procedure 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 procedures. */ + 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 int 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 int initLen; /* Length of following string. */ + char init[16]; /* String to emit or expect before first char + * in conversion. */ + unsigned int 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 + +/* + * Initialize the default encoding directory. If this variable contains + * a non NULL value, it will be the first path used to locate the + * system encoding files. + */ + +char *tclDefaultEncodingDir = NULL; + +/* + * 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; +static Tcl_Encoding systemEncoding; + +/* + * 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]; + +/* + * Procedures used only in this module. + */ + +static int BinaryProc _ANSI_ARGS_((ClientData clientData, + CONST char *src, int srcLen, int flags, + Tcl_EncodingState *statePtr, char *dst, int dstLen, + int *srcReadPtr, int *dstWrotePtr, + int *dstCharsPtr)); +static void EscapeFreeProc _ANSI_ARGS_((ClientData clientData)); +static int EscapeFromUtfProc _ANSI_ARGS_((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 _ANSI_ARGS_((ClientData clientData, + CONST char *src, int srcLen, int flags, + Tcl_EncodingState *statePtr, char *dst, int dstLen, + int *srcReadPtr, int *dstWrotePtr, + int *dstCharsPtr)); +static void FreeEncoding _ANSI_ARGS_((Tcl_Encoding encoding)); +static Encoding * GetTableEncoding _ANSI_ARGS_(( + EscapeEncodingData *dataPtr, int state)); +static Tcl_Encoding LoadEncodingFile _ANSI_ARGS_((Tcl_Interp *interp, + CONST char *name)); +static Tcl_Encoding LoadTableEncoding _ANSI_ARGS_((Tcl_Interp *interp, + CONST char *name, int type, Tcl_Channel chan)); +static Tcl_Encoding LoadEscapeEncoding _ANSI_ARGS_((CONST char *name, + Tcl_Channel chan)); +static Tcl_Channel OpenEncodingFile _ANSI_ARGS_((CONST char *dir, + CONST char *name)); +static void TableFreeProc _ANSI_ARGS_((ClientData clientData)); +static int TableFromUtfProc _ANSI_ARGS_((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 _ANSI_ARGS_((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 _ANSI_ARGS_((CONST char *src)); +static int UnicodeToUtfProc _ANSI_ARGS_((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 _ANSI_ARGS_((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 _ANSI_ARGS_((ClientData clientData, + CONST char *src, int srcLen, int flags, + Tcl_EncodingState *statePtr, char *dst, int dstLen, + int *srcReadPtr, int *dstWrotePtr, + int *dstCharsPtr)); + + +/* + *--------------------------------------------------------------------------- + * + * TclInitEncodingSubsystem -- + * + * Initialize all resources used by this subsystem on a per-process + * basis. + * + * Results: + * None. + * + * Side effects: + * Depends on the memory, object, and IO subsystems. + * + *--------------------------------------------------------------------------- + */ + +void +TclInitEncodingSubsystem() +{ + Tcl_EncodingType type; + + Tcl_MutexLock(&encodingMutex); + Tcl_InitHashTable(&encodingTable, TCL_STRING_KEYS); + Tcl_MutexUnlock(&encodingMutex); + + /* + * Create a few initial encodings. 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. + */ + + type.encodingName = "identity"; + type.toUtfProc = BinaryProc; + type.fromUtfProc = BinaryProc; + type.freeProc = NULL; + type.nullSize = 1; + type.clientData = NULL; + + defaultEncoding = Tcl_CreateEncoding(&type); + systemEncoding = Tcl_GetEncoding(NULL, type.encodingName); + + type.encodingName = "utf-8"; + type.toUtfProc = UtfToUtfProc; + type.fromUtfProc = UtfToUtfProc; + type.freeProc = NULL; + type.nullSize = 1; + type.clientData = NULL; + Tcl_CreateEncoding(&type); + + type.encodingName = "unicode"; + type.toUtfProc = UnicodeToUtfProc; + type.fromUtfProc = UtfToUnicodeProc; + type.freeProc = NULL; + type.nullSize = 2; + type.clientData = NULL; + Tcl_CreateEncoding(&type); +} + + +/* + *---------------------------------------------------------------------- + * + * TclFinalizeEncodingSubsystem -- + * + * Release the state associated with the encoding subsystem. + * + * Results: + * None. + * + * Side effects: + * Frees all of the encodings. + * + *---------------------------------------------------------------------- + */ + +void +TclFinalizeEncodingSubsystem() +{ + Tcl_HashSearch search; + Tcl_HashEntry *hPtr; + Encoding *encodingPtr; + + Tcl_MutexLock(&encodingMutex); + hPtr = Tcl_FirstHashEntry(&encodingTable, &search); + while (hPtr != NULL) { + encodingPtr = (Encoding *) Tcl_GetHashValue(hPtr); + if (encodingPtr->freeProc != NULL) { + (*encodingPtr->freeProc)(encodingPtr->clientData); + } + ckfree((char *) encodingPtr->name); + ckfree((char *) encodingPtr); + hPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&encodingTable); + Tcl_MutexUnlock(&encodingMutex); +} + +/* + *------------------------------------------------------------------------- + * + * Tcl_GetDefaultEncodingDir -- + * + * + * Results: + * + * Side effects: + * + *------------------------------------------------------------------------- + */ + +char * +Tcl_GetDefaultEncodingDir() +{ + return tclDefaultEncodingDir; +} + +/* + *------------------------------------------------------------------------- + * + * Tcl_SetDefaultEncodingDir -- + * + * + * Results: + * + * Side effects: + * + *------------------------------------------------------------------------- + */ + +void +Tcl_SetDefaultEncodingDir(path) + char *path; +{ + tclDefaultEncodingDir = (char *)ckalloc((unsigned) strlen(path) + 1); + strcpy(tclDefaultEncodingDir, path); +} + +/* + *------------------------------------------------------------------------- + * + * 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 procedure, 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(interp, name) + 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 = (Encoding *) Tcl_GetHashValue(hPtr); + encodingPtr->refCount++; + Tcl_MutexUnlock(&encodingMutex); + return (Tcl_Encoding) encodingPtr; + } + Tcl_MutexUnlock(&encodingMutex); + return LoadEncodingFile(interp, name); +} + +/* + *--------------------------------------------------------------------------- + * + * Tcl_FreeEncoding -- + * + * This procedure 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(encoding) + Tcl_Encoding encoding; +{ + Tcl_MutexLock(&encodingMutex); + FreeEncoding(encoding); + Tcl_MutexUnlock(&encodingMutex); +} + +/* + *---------------------------------------------------------------------- + * + * FreeEncoding -- + * + * This procedure is called to release an encoding by procedures + * 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(encoding) + Tcl_Encoding encoding; +{ + Encoding *encodingPtr; + + encodingPtr = (Encoding *) encoding; + if (encodingPtr == NULL) { + return; + } + encodingPtr->refCount--; + if (encodingPtr->refCount == 0) { + if (encodingPtr->freeProc != NULL) { + (*encodingPtr->freeProc)(encodingPtr->clientData); + } + if (encodingPtr->hPtr != NULL) { + Tcl_DeleteHashEntry(encodingPtr->hPtr); + } + ckfree((char *) encodingPtr->name); + ckfree((char *) 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. + * + *--------------------------------------------------------------------------- + */ + +char * +Tcl_GetEncodingName(encoding) + Tcl_Encoding encoding; /* The encoding whose name to fetch. */ +{ + Encoding *encodingPtr; + + if (encoding == NULL) { + encoding = systemEncoding; + } + encodingPtr = (Encoding *) encoding; + return encodingPtr->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(interp) + Tcl_Interp *interp; /* Interp to hold result. */ +{ + Tcl_HashSearch search; + Tcl_HashEntry *hPtr; + Tcl_Obj *pathPtr, *resultPtr; + int dummy; + + Tcl_HashTable table; + + Tcl_MutexLock(&encodingMutex); + Tcl_InitHashTable(&table, TCL_STRING_KEYS); + hPtr = Tcl_FirstHashEntry(&encodingTable, &search); + while (hPtr != NULL) { + Encoding *encodingPtr; + + encodingPtr = (Encoding *) Tcl_GetHashValue(hPtr); + Tcl_CreateHashEntry(&table, encodingPtr->name, &dummy); + hPtr = Tcl_NextHashEntry(&search); + } + Tcl_MutexUnlock(&encodingMutex); + + pathPtr = TclGetLibraryPath(); + if (pathPtr != NULL) { + int i, objc; + Tcl_Obj **objv; + Tcl_DString pwdString; + char globArgString[10]; + + objc = 0; + Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv); + + Tcl_GetCwd(interp, &pwdString); + + for (i = 0; i < objc; i++) { + char *string; + int j, objc2, length; + Tcl_Obj **objv2; + + string = Tcl_GetStringFromObj(objv[i], NULL); + Tcl_ResetResult(interp); + + /* + * TclGlob() changes the contents of globArgString, which causes + * a segfault if we pass in a pointer to non-writeable memory. + * TclGlob() puts its results directly into interp. + */ + + strcpy(globArgString, "*.enc"); + if ((Tcl_Chdir(string) == 0) + && (Tcl_Chdir("encoding") == 0) + && (TclGlob(interp, globArgString, 0) == TCL_OK)) { + objc2 = 0; + + Tcl_ListObjGetElements(NULL, Tcl_GetObjResult(interp), &objc2, + &objv2); + + for (j = 0; j < objc2; j++) { + string = Tcl_GetStringFromObj(objv2[j], &length); + length -= 4; + if (length > 0) { + string[length] = '\0'; + Tcl_CreateHashEntry(&table, string, &dummy); + string[length] = '.'; + } + } + } + Tcl_Chdir(Tcl_DStringValue(&pwdString)); + } + Tcl_DStringFree(&pwdString); + } + + /* + * Clear any values placed in the result by globbing. + */ + + Tcl_ResetResult(interp); + resultPtr = Tcl_GetObjResult(interp); + + hPtr = Tcl_FirstHashEntry(&table, &search); + while (hPtr != NULL) { + Tcl_Obj *strPtr; + + strPtr = Tcl_NewStringObj(Tcl_GetHashKey(&table, hPtr), -1); + Tcl_ListObjAppendElement(NULL, resultPtr, strPtr); + hPtr = Tcl_NextHashEntry(&search); + } + 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(interp, name) + 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 == NULL) { + 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 procedure is called to define a new encoding and the procedures + * 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 procedure, 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(typePtr) + Tcl_EncodingType *typePtr; /* The encoding type. */ +{ + Tcl_HashEntry *hPtr; + int new; + Encoding *encodingPtr; + char *name; + + Tcl_MutexLock(&encodingMutex); + hPtr = Tcl_CreateHashEntry(&encodingTable, typePtr->encodingName, &new); + if (new == 0) { + /* + * Remove old encoding from hash table, but don't delete it until + * last reference goes away. + */ + + encodingPtr = (Encoding *) Tcl_GetHashValue(hPtr); + encodingPtr->hPtr = NULL; + } + + name = ckalloc((unsigned) strlen(typePtr->encodingName) + 1); + + encodingPtr = (Encoding *) 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 = strlen; + } else { + encodingPtr->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(encoding, src, srcLen, dstPtr) + 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; + 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(interp, encoding, src, srcLen, flags, statePtr, dst, + dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr) + 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. */ +{ + 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 = (*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; + } + + /* + * 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. + */ + + dstLen--; + result = (*encodingPtr->toUtfProc)(encodingPtr->clientData, src, srcLen, + flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, + dstCharsPtr); + 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(encoding, src, srcLen, dstPtr) + 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; + 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(interp, encoding, src, srcLen, flags, statePtr, dst, + dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr) + 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. */ +{ + 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 procedure computes the absolute path name of the current + * application, given its argv[0] value. + * + * Results: + * None. + * + * Side effects: + * The variable tclExecutableName gets filled in with the file + * name for the application, if we figured it out. If we couldn't + * figure it out, tclExecutableName is set to NULL. + * + *--------------------------------------------------------------------------- + */ + +void +Tcl_FindExecutable(argv0) + CONST char *argv0; /* The value of the application's argv[0] + * (native). */ +{ + CONST char *name; + Tcl_DString buffer, nameString; + + TclInitSubsystems(argv0); + + if (argv0 == NULL) { + goto done; + } + if (tclExecutableName != NULL) { + ckfree(tclExecutableName); + tclExecutableName = NULL; + } + if ((name = TclpFindExecutable(argv0)) == NULL) { + goto done; + } + + /* + * The value returned from TclpNameOfExecutable is a UTF string that + * is possibly dirty depending on when it was initialized. To assure + * that the UTF string is a properly encoded native string for this + * system, convert the UTF string to the default native encoding + * before the default encoding is initialized. Then, convert it back + * to UTF after the system encoding is loaded. + */ + + Tcl_UtfToExternalDString(NULL, name, -1, &buffer); + TclFindEncodings(argv0); + + /* + * Now it is OK to convert the native string back to UTF and set + * the value of the tclExecutableName. + */ + + Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&buffer), -1, &nameString); + tclExecutableName = (char *) + ckalloc((unsigned) (Tcl_DStringLength(&nameString) + 1)); + strcpy(tclExecutableName, Tcl_DStringValue(&nameString)); + + Tcl_DStringFree(&buffer); + Tcl_DStringFree(&nameString); + return; + + done: + TclFindEncodings(argv0); +} + +/* + *--------------------------------------------------------------------------- + * + * LoadEncodingFile -- + * + * Read a file that describes an encoding and create a new Encoding + * from the data. + * + * Results: + * The return value is the newly loaded Encoding, or NULL if + * the file didn't exist of was in the incorrect format. If NULL was + * returned, an error message is left in interp's result object, + * unless interp was NULL. + * + * Side effects: + * File read from disk. + * + *--------------------------------------------------------------------------- + */ + +static Tcl_Encoding +LoadEncodingFile(interp, name) + 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. */ +{ + int objc, i, ch; + Tcl_Obj **objv; + Tcl_Obj *pathPtr; + Tcl_Channel chan; + Tcl_Encoding encoding; + + pathPtr = TclGetLibraryPath(); + if (pathPtr == NULL) { + goto unknown; + } + objc = 0; + Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv); + + chan = NULL; + for (i = 0; i < objc; i++) { + chan = OpenEncodingFile(Tcl_GetString(objv[i]), name); + if (chan != NULL) { + break; + } + } + + if (chan == NULL) { + goto unknown; + } + + Tcl_SetChannelOption(NULL, chan, "-encoding", "utf-8"); + + while (1) { + Tcl_DString ds; + + Tcl_DStringInit(&ds); + Tcl_Gets(chan, &ds); + ch = Tcl_DStringValue(&ds)[0]; + Tcl_DStringFree(&ds); + if (ch != '#') { + break; + } + } + + encoding = NULL; + switch (ch) { + case 'S': { + encoding = LoadTableEncoding(interp, name, ENCODING_SINGLEBYTE, + chan); + break; + } + case 'D': { + encoding = LoadTableEncoding(interp, name, ENCODING_DOUBLEBYTE, + chan); + break; + } + case 'M': { + encoding = LoadTableEncoding(interp, name, ENCODING_MULTIBYTE, + chan); + break; + } + case 'E': { + encoding = LoadEscapeEncoding(name, chan); + break; + } + } + if ((encoding == NULL) && (interp != NULL)) { + Tcl_AppendResult(interp, "invalid encoding file \"", name, "\"", NULL); + } + Tcl_Close(NULL, chan); + return encoding; + + unknown: + if (interp != NULL) { + Tcl_AppendResult(interp, "unknown encoding \"", name, "\"", NULL); + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * OpenEncodingFile -- + * + * Look for the file encoding/.enc in the specified + * directory. + * + * Results: + * Returns an open file channel if the file exists. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static Tcl_Channel +OpenEncodingFile(dir, name) + CONST char *dir; + CONST char *name; + +{ + char *argv[3]; + Tcl_DString pathString; + char *path; + Tcl_Channel chan; + + argv[0] = (char *) dir; + argv[1] = "encoding"; + argv[2] = (char *) name; + + Tcl_DStringInit(&pathString); + Tcl_JoinPath(3, argv, &pathString); + path = Tcl_DStringAppend(&pathString, ".enc", -1); + chan = Tcl_OpenFileChannel(NULL, path, "r", 0); + Tcl_DStringFree(&pathString); + + return chan; +} + +/* + *------------------------------------------------------------------------- + * + * LoadTableEncoding -- + * + * Helper function for LoadEncodingTable(). Loads a table to that + * converts between Unicode and some other encoding and creates an + * encoding (using a TableEncoding structure) from that information. + * + * File contains binary data, but begins with a marker to indicate + * byte-ordering, so that same binary file can be read on either + * endian platforms. + * + * 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 +LoadTableEncoding(interp, name, type, chan) + Tcl_Interp *interp; /* Interp for temporary obj while reading. */ + CONST char *name; /* Name for new encoding. */ + int type; /* Type of encoding (ENCODING_?????). */ + Tcl_Channel chan; /* File containing new encoding. */ +{ + Tcl_DString lineString; + Tcl_Obj *objPtr; + char *line; + int i, hi, lo, numPages, symbol, fallback; + unsigned char used[256]; + unsigned int size; + TableEncodingData *dataPtr; + unsigned short *pageMemPtr; + Tcl_EncodingType encType; + char *hex; + static char staticHex[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, + 10, 11, 12, 13, 14, 15 + }; + + hex = staticHex - '0'; + + Tcl_DStringInit(&lineString); + Tcl_Gets(chan, &lineString); + line = Tcl_DStringValue(&lineString); + + fallback = (int) strtol(line, &line, 16); + symbol = (int) strtol(line, &line, 10); + numPages = (int) strtol(line, &line, 10); + Tcl_DStringFree(&lineString); + + if (numPages < 0) { + numPages = 0; + } else if (numPages > 256) { + numPages = 256; + } + + memset(used, 0, sizeof(used)); + +#undef PAGESIZE +#define PAGESIZE (256 * sizeof(unsigned short)) + + dataPtr = (TableEncodingData *) 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 = (unsigned short **) ckalloc(size); + memset(dataPtr->toUnicode, 0, size); + pageMemPtr = (unsigned short *) (dataPtr->toUnicode + 256); + + if (interp == NULL) { + objPtr = Tcl_NewObj(); + } else { + objPtr = Tcl_GetObjResult(interp); + } + for (i = 0; i < numPages; i++) { + int ch; + char *p; + + Tcl_ReadChars(chan, objPtr, 3 + 16 * (16 * 4 + 1), 0); + p = Tcl_GetString(objPtr); + hi = (hex[(int)p[0]] << 4) + hex[(int)p[1]]; + dataPtr->toUnicode[hi] = pageMemPtr; + p += 2; + for (lo = 0; lo < 256; lo++) { + if ((lo & 0x0f) == 0) { + p++; + } + ch = (hex[(int)p[0]] << 12) + (hex[(int)p[1]] << 8) + + (hex[(int)p[2]] << 4) + hex[(int)p[3]]; + if (ch != 0) { + used[ch >> 8] = 1; + } + *pageMemPtr = (unsigned short) ch; + pageMemPtr++; + p += 4; + } + } + if (interp == NULL) { + Tcl_DecrRefCount(objPtr); + } else { + Tcl_ResetResult(interp); + } + + 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 = (unsigned short **) 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; + } else { + for (lo = 0; lo < 256; lo++) { + int ch; + + ch = dataPtr->toUnicode[hi][lo]; + if (ch != 0) { + unsigned short *page; + + 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) { + unsigned short *page; + + /* + * 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; + } + } + encType.encodingName = name; + encType.toUtfProc = TableToUtfProc; + encType.fromUtfProc = TableFromUtfProc; + encType.freeProc = TableFreeProc; + encType.nullSize = (type == ENCODING_DOUBLEBYTE) ? 2 : 1; + encType.clientData = (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(name, chan) + CONST char *name; /* Name for new encoding. */ + Tcl_Channel chan; /* File containing new encoding. */ +{ + int i; + unsigned int 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; + 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) { + continue; + } + if (argc >= 2) { + if (strcmp(argv[0], "name") == 0) { + ; + } 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; + + 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'; + + est.encodingPtr = NULL; + Tcl_DStringAppend(&escapeData, (char *) &est, sizeof(est)); + } + } + ckfree((char *) argv); + Tcl_DStringFree(&lineString); + } + + size = sizeof(EscapeEncodingData) + - sizeof(EscapeSubTable) + Tcl_DStringLength(&escapeData); + dataPtr = (EscapeEncodingData *) ckalloc(size); + dataPtr->initLen = strlen(init); + strcpy(dataPtr->init, init); + dataPtr->finalLen = strlen(final); + strcpy(dataPtr->final, final); + dataPtr->numSubTables = Tcl_DStringLength(&escapeData) / sizeof(EscapeSubTable); + memcpy((VOID *) dataPtr->subTables, (VOID *) 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; + } + + type.encodingName = name; + type.toUtfProc = EscapeToUtfProc; + type.fromUtfProc = EscapeFromUtfProc; + type.freeProc = EscapeFreeProc; + type.nullSize = 1; + type.clientData = (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, src, srcLen, flags, statePtr, dst, dstLen, + srcReadPtr, dstWrotePtr, dstCharsPtr) + 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 (srcLen > dstLen) { + srcLen = dstLen; + result = TCL_CONVERT_NOSPACE; + } + + *srcReadPtr = srcLen; + *dstWrotePtr = srcLen; + *dstCharsPtr = srcLen; + for ( ; --srcLen >= 0; ) { + *dst++ = *src++; + } + return result; +} + +/* + *------------------------------------------------------------------------- + * + * 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, src, srcLen, flags, statePtr, dst, dstLen, + srcReadPtr, dstWrotePtr, dstCharsPtr) + 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. */ +{ + CONST char *srcStart, *srcEnd, *srcClose; + char *dstStart, *dstEnd; + int result, numChars; + Tcl_UniChar ch; + + 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 - TCL_UTF_MAX; + + 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 += 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, src, srcLen, flags, statePtr, dst, dstLen, + srcReadPtr, dstWrotePtr, dstCharsPtr) + 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 Tcl_UniChar *wSrc, *wSrcStart, *wSrcEnd; + char *dstEnd, *dstStart; + int result, numChars; + + result = TCL_OK; + if ((srcLen % sizeof(Tcl_UniChar)) != 0) { + result = TCL_CONVERT_MULTIBYTE; + srcLen /= sizeof(Tcl_UniChar); + srcLen *= sizeof(Tcl_UniChar); + } + + wSrc = (Tcl_UniChar *) src; + + wSrcStart = (Tcl_UniChar *) src; + wSrcEnd = (Tcl_UniChar *) (src + srcLen); + + dstStart = dst; + dstEnd = dst + dstLen - TCL_UTF_MAX; + + for (numChars = 0; wSrc < wSrcEnd; numChars++) { + if (dst > dstEnd) { + result = TCL_CONVERT_NOSPACE; + break; + } + dst += Tcl_UniCharToUtf(*wSrc, dst); + wSrc++; + } + + *srcReadPtr = (char *) wSrc - (char *) wSrcStart; + *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, src, srcLen, flags, statePtr, dst, dstLen, + srcReadPtr, dstWrotePtr, dstCharsPtr) + 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; + Tcl_UniChar *wDst, *wDstStart, *wDstEnd; + int result, numChars; + + srcStart = src; + srcEnd = src + srcLen; + srcClose = srcEnd; + if ((flags & TCL_ENCODING_END) == 0) { + srcClose -= TCL_UTF_MAX; + } + + wDst = (Tcl_UniChar *) dst; + wDstStart = (Tcl_UniChar *) dst; + wDstEnd = (Tcl_UniChar *) (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 (wDst > wDstEnd) { + result = TCL_CONVERT_NOSPACE; + break; + } + src += Tcl_UtfToUniChar(src, wDst); + wDst++; + } + *srcReadPtr = src - srcStart; + *dstWrotePtr = (char *) wDst - (char *) wDstStart; + *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, src, srcLen, flags, statePtr, dst, dstLen, + srcReadPtr, dstWrotePtr, dstCharsPtr) + 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; + char *dstEnd, *dstStart, *prefixBytes; + int result, byte, numChars; + Tcl_UniChar ch; + unsigned short **toUnicode; + unsigned short *pageZero; + TableEncodingData *dataPtr; + + srcStart = src; + srcEnd = src + srcLen; + + dstStart = dst; + dstEnd = dst + dstLen - TCL_UTF_MAX; + + dataPtr = (TableEncodingData *) clientData; + toUnicode = dataPtr->toUnicode; + prefixBytes = dataPtr->prefixBytes; + pageZero = toUnicode[0]; + + result = TCL_OK; + for (numChars = 0; src < srcEnd; 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; + } + 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, src, srcLen, flags, statePtr, dst, dstLen, + srcReadPtr, dstWrotePtr, dstCharsPtr) + 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; + char *dstStart, *dstEnd, *prefixBytes; + Tcl_UniChar ch; + int result, len, word, numChars; + TableEncodingData *dataPtr; + unsigned short **fromUnicode; + + result = TCL_OK; + + dataPtr = (TableEncodingData *) clientData; + prefixBytes = dataPtr->prefixBytes; + fromUnicode = 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 = Tcl_UtfToUniChar(src, &ch); + 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; +} + +/* + *--------------------------------------------------------------------------- + * + * TableFreeProc -- + * + * This procedure 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 clientData; /* TableEncodingData that specifies + * encoding. */ +{ + TableEncodingData *dataPtr; + + dataPtr = (TableEncodingData *) clientData; + ckfree((char *) dataPtr->toUnicode); + ckfree((char *) dataPtr->fromUnicode); + ckfree((char *) 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, src, srcLen, flags, statePtr, dst, dstLen, + srcReadPtr, dstWrotePtr, dstCharsPtr) + 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; + char *prefixBytes, *tablePrefixBytes; + unsigned short **tableToUnicode; + Encoding *encodingPtr; + int state, result, numChars; + CONST char *srcStart, *srcEnd; + char *dstStart, *dstEnd; + + result = TCL_OK; + + tablePrefixBytes = NULL; /* lint. */ + tableToUnicode = NULL; /* lint. */ + + dataPtr = (EscapeEncodingData *) clientData; + prefixBytes = dataPtr->prefixBytes; + encodingPtr = NULL; + + srcStart = src; + srcEnd = src + srcLen; + + dstStart = dst; + dstEnd = dst + dstLen - TCL_UTF_MAX; + + state = (int) *statePtr; + if (flags & TCL_ENCODING_START) { + state = 0; + } + + for (numChars = 0; src < srcEnd; ) { + int byte, hi, lo, ch; + + if (dst > dstEnd) { + result = TCL_CONVERT_NOSPACE; + break; + } + byte = *((unsigned char *) src); + if (prefixBytes[byte]) { + unsigned int left, len, longest; + int checked, i; + 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 = (TableEncodingData *) encodingPtr->clientData; + tablePrefixBytes = tableDataPtr->prefixBytes; + tableToUnicode = 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) 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, src, srcLen, flags, statePtr, dst, dstLen, + srcReadPtr, dstWrotePtr, dstCharsPtr) + 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; + Encoding *encodingPtr; + CONST char *srcStart, *srcEnd, *srcClose; + char *dstStart, *dstEnd; + int state, result, numChars; + TableEncodingData *tableDataPtr; + char *tablePrefixBytes; + unsigned short **tableFromUnicode; + + result = TCL_OK; + + dataPtr = (EscapeEncodingData *) clientData; + + srcStart = src; + srcEnd = src + srcLen; + srcClose = srcEnd; + if ((flags & TCL_ENCODING_END) == 0) { + srcClose -= TCL_UTF_MAX; + } + + dstStart = dst; + dstEnd = dst + dstLen - 1; + + if (flags & TCL_ENCODING_START) { + unsigned int len; + + state = 0; + len = dataPtr->subTables[0].sequenceLen; + if (dst + dataPtr->initLen + len > dstEnd) { + *srcReadPtr = 0; + *dstWrotePtr = 0; + return TCL_CONVERT_NOSPACE; + } + memcpy((VOID *) dst, (VOID *) dataPtr->init, + (size_t) dataPtr->initLen); + dst += dataPtr->initLen; + memcpy((VOID *) dst, (VOID *) dataPtr->subTables[0].sequence, + (size_t) len); + dst += len; + } else { + state = (int) *statePtr; + } + + encodingPtr = GetTableEncoding(dataPtr, state); + tableDataPtr = (TableEncodingData *) encodingPtr->clientData; + tablePrefixBytes = tableDataPtr->prefixBytes; + tableFromUnicode = tableDataPtr->fromUnicode; + + for (numChars = 0; src < srcEnd; numChars++) { + unsigned int 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 = Tcl_UtfToUniChar(src, &ch); + word = tableFromUnicode[(ch >> 8)][ch & 0xff]; + + if ((word == 0) && (ch != 0)) { + int oldState; + EscapeSubTable *subTablePtr; + + oldState = state; + for (state = 0; state < dataPtr->numSubTables; state++) { + encodingPtr = GetTableEncoding(dataPtr, state); + tableDataPtr = (TableEncodingData *) 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 = (TableEncodingData *) encodingPtr->clientData; + word = tableDataPtr->fallback; + } + + tablePrefixBytes = tableDataPtr->prefixBytes; + tableFromUnicode = tableDataPtr->fromUnicode; + + subTablePtr = &dataPtr->subTables[state]; + if (dst + subTablePtr->sequenceLen > dstEnd) { + result = TCL_CONVERT_NOSPACE; + break; + } + memcpy((VOID *) dst, (VOID *) 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)) { + if (dst + dataPtr->finalLen > dstEnd) { + result = TCL_CONVERT_NOSPACE; + } else { + memcpy((VOID *) dst, (VOID *) dataPtr->final, + (size_t) dataPtr->finalLen); + dst += dataPtr->finalLen; + } + } + + *statePtr = (Tcl_EncodingState) state; + *srcReadPtr = src - srcStart; + *dstWrotePtr = dst - dstStart; + *dstCharsPtr = numChars; + return result; +} + +/* + *--------------------------------------------------------------------------- + * + * EscapeFreeProc -- + * + * This procedure 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 clientData; /* EscapeEncodingData that specifies encoding. */ +{ + EscapeEncodingData *dataPtr; + EscapeSubTable *subTablePtr; + int i; + + dataPtr = (EscapeEncodingData *) clientData; + if (dataPtr == NULL) { + return; + } + subTablePtr = dataPtr->subTables; + for (i = 0; i < dataPtr->numSubTables; i++) { + FreeEncoding((Tcl_Encoding) subTablePtr->encodingPtr); + subTablePtr++; + } + ckfree((char *) 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(dataPtr, state) + EscapeEncodingData *dataPtr;/* Contains names of encodings. */ + int state; /* Index in dataPtr of desired Encoding. */ +{ + EscapeSubTable *subTablePtr; + Encoding *encodingPtr; + + subTablePtr = &dataPtr->subTables[state]; + encodingPtr = subTablePtr->encodingPtr; + if (encodingPtr == NULL) { + encodingPtr = (Encoding *) Tcl_GetEncoding(NULL, subTablePtr->name); + if ((encodingPtr == NULL) + || (encodingPtr->toUtfProc != TableToUtfProc)) { + 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(src) + CONST char *src; +{ + unsigned short *p; + + p = (unsigned short *) src; + while (*p != 0x0000) { + p++; + } + return (char *) p - src; +} + + Index: generic/tclEnv.c ================================================================== --- generic/tclEnv.c +++ generic/tclEnv.c @@ -5,38 +5,22 @@ * procedure. 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-1996 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclEnv.c 1.54 97/10/27 17:47:52 + * RCS: @(#) $Id: tclEnv.c,v 1.1.2.7 1999/04/14 00:33:22 surles Exp $ */ #include "tclInt.h" #include "tclPort.h" -/* - * The structure below is used to keep track of all of the interpereters - * for which we're managing the "env" array. It's needed so that they - * can all be updated whenever an environment variable is changed - * anywhere. - */ - -typedef struct EnvInterp { - Tcl_Interp *interp; /* Interpreter for which we're managing - * the env array. */ - struct EnvInterp *nextPtr; /* Next in list of all such interpreters, - * or zero. */ -} EnvInterp; - -static EnvInterp *firstInterpPtr = NULL; - /* First in list of all managed interpreters, - * or NULL if none. */ +TCL_DECLARE_MUTEX(envMutex) /* To serialize access to environ */ static int cacheSize = 0; /* Number of env strings in environCache. */ static char **environCache = NULL; /* Array containing all of the environment * strings that Tcl has allocated. */ @@ -54,17 +38,16 @@ */ static char * EnvTraceProc _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags)); -static int FindVariable _ANSI_ARGS_((CONST char *name, - int *lengthPtr)); static void ReplaceString _ANSI_ARGS_((CONST char *oldStr, char *newStr)); void TclSetEnv _ANSI_ARGS_((CONST char *name, CONST char *value)); void TclUnsetEnv _ANSI_ARGS_((CONST char *name)); + /* *---------------------------------------------------------------------- * * TclSetupEnv -- @@ -78,11 +61,11 @@ * * 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 Tcl_SetupEnv, then additional initialization happens, + * call to TclSetupEnv, then additional initialization happens, * such as copying the environment to dynamically-allocated space * for ease of management. * *---------------------------------------------------------------------- */ @@ -90,77 +73,63 @@ void TclSetupEnv(interp) Tcl_Interp *interp; /* Interpreter whose "env" array is to be * managed. */ { - EnvInterp *eiPtr; - char *p, *p2; - Tcl_DString ds; - int i, sz; - -#ifdef MAC_TCL - if (environ == NULL) { - environSize = TclMacCreateEnv(); - } -#endif - - /* - * Next, initialize the DString we are going to use for copying - * the names of the environment variables. - */ - - Tcl_DStringInit(&ds); - - /* - * Next, add the interpreter to the list of those that we manage. - */ - - eiPtr = (EnvInterp *) ckalloc(sizeof(EnvInterp)); - eiPtr->interp = interp; - eiPtr->nextPtr = firstInterpPtr; - firstInterpPtr = eiPtr; - - /* - * Store the environment variable values into the interpreter's - * "env" array, and arrange for us to be notified on future - * writes and unsets to that array. - */ - - (void) Tcl_UnsetVar2(interp, "env", (char *) NULL, TCL_GLOBAL_ONLY); - for (i = 0; ; i++) { - p = environ[i]; - if (p == NULL) { - break; - } - for (p2 = p; *p2 != '='; p2++) { - if (*p2 == 0) { - /* - * This condition doesn't seem like it should ever happen, - * but it does seem to happen occasionally under some + Tcl_DString envString; + char *p1, *p2; + int i; + + /* + * 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 unset. + * 2) Unset the "env" variable. + * 3) If there are no environ variables, create an empty "env" + * array. Otherwise populate the array with current values. + * 4) Add a trace that synchronizes the "env" array. + */ + + Tcl_UntraceVar2(interp, "env", (char *) NULL, + TCL_GLOBAL_ONLY | TCL_TRACE_WRITES | TCL_TRACE_UNSETS | + TCL_TRACE_READS | TCL_TRACE_ARRAY, EnvTraceProc, + (ClientData) NULL); + + Tcl_UnsetVar2(interp, "env", (char *) NULL, TCL_GLOBAL_ONLY); + + if (environ[0] == NULL) { + Tcl_Obj *varNamePtr; + + varNamePtr = Tcl_NewStringObj("env", -1); + Tcl_IncrRefCount(varNamePtr); + TclArraySet(interp, varNamePtr, NULL); + Tcl_DecrRefCount(varNamePtr); + } else { + Tcl_MutexLock(&envMutex); + for (i = 0; environ[i] != NULL; i++) { + 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; ignore the entry. */ - - goto nextEntry; - } - } - sz = p2 - p; - Tcl_DStringSetLength(&ds, 0); - Tcl_DStringAppend(&ds, p, sz); - (void) Tcl_SetVar2(interp, "env", Tcl_DStringValue(&ds), - p2+1, TCL_GLOBAL_ONLY); - nextEntry: - continue; - } + + continue; + } + p2++; + p2[-1] = '\0'; + Tcl_SetVar2(interp, "env", p1, p2, TCL_GLOBAL_ONLY); + Tcl_DStringFree(&envString); + } + Tcl_MutexUnlock(&envMutex); + } + Tcl_TraceVar2(interp, "env", (char *) NULL, - TCL_GLOBAL_ONLY | TCL_TRACE_WRITES | TCL_TRACE_UNSETS, - EnvTraceProc, (ClientData) NULL); - - /* - * Finally clean up the DString. - */ - - Tcl_DStringFree(&ds); + TCL_GLOBAL_ONLY | TCL_TRACE_WRITES | TCL_TRACE_UNSETS | + TCL_TRACE_READS | TCL_TRACE_ARRAY, EnvTraceProc, + (ClientData) NULL); } /* *---------------------------------------------------------------------- * @@ -175,110 +144,122 @@ * * Results: * None. * * Side effects: - * The environ array gets updated, as do all of the interpreters - * that we manage. + * The environ array gets updated. * *---------------------------------------------------------------------- */ void TclSetEnv(name, value) CONST char *name; /* Name of variable whose value is to be - * set. */ - CONST char *value; /* New value for variable. */ + * set (UTF-8). */ + CONST char *value; /* New value for variable (UTF-8). */ { + Tcl_DString envString; int index, length, nameLength; - char *p, *oldValue; - EnvInterp *eiPtr; - -#ifdef MAC_TCL - if (environ == NULL) { - environSize = TclMacCreateEnv(); - } -#endif + char *p, *p2, *oldValue; /* * 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. + * already exist, enlarge the array if necessary to make room. If the + * name exists, free its old entry. */ - index = FindVariable(name, &length); + Tcl_MutexLock(&envMutex); + index = TclpFindVariable(name, &length); + if (index == -1) { #ifndef USE_PUTENV - if ((length+2) > environSize) { + if ((length + 2) > environSize) { char **newEnviron; newEnviron = (char **) ckalloc((unsigned) - ((length+5) * sizeof(char *))); + ((length + 5) * sizeof(char *))); memcpy((VOID *) newEnviron, (VOID *) environ, length*sizeof(char *)); if (environSize != 0) { ckfree((char *) environ); } environ = newEnviron; - environSize = length+5; + environSize = length + 5; } index = length; - environ[index+1] = NULL; + environ[index + 1] = NULL; #endif oldValue = NULL; nameLength = strlen(name); } else { + 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. */ - if (strcmp(value, environ[index]+length+1) == 0) { + 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 = length; } /* - * Create a new entry. + * 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. */ p = (char *) ckalloc((unsigned) (nameLength + strlen(value) + 2)); strcpy(p, name); p[nameLength] = '='; strcpy(p+nameLength+1, value); + p2 = Tcl_UtfToExternalDString(NULL, p, -1, &envString); + ckfree(p); + +#ifdef USE_PUTENV /* * Update the system environment. */ -#ifdef USE_PUTENV - putenv(p); + putenv(p2); + index = TclpFindVariable(name, &length); #else + /* + * Copy the native string to heap memory. + */ + + p = (char *) ckalloc((unsigned) (strlen(p2) + 1)); + strcpy(p, p2); environ[index] = p; #endif /* - * Replace the old value with the new value in the cache. - */ - - ReplaceString(oldValue, p); - - /* - * Update all of the interpreters. + * 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. */ - for (eiPtr= firstInterpPtr; eiPtr != NULL; eiPtr = eiPtr->nextPtr) { - (void) Tcl_SetVar2(eiPtr->interp, "env", (char *) name, - (char *) value, TCL_GLOBAL_ONLY); + if (environ[index] != p) { + Tcl_DStringFree(&envString); + } else { + ReplaceString(oldValue, p); } + Tcl_MutexUnlock(&envMutex); } /* *---------------------------------------------------------------------- * @@ -303,37 +284,39 @@ */ int Tcl_PutEnv(string) CONST char *string; /* Info about environment variable in the - * form NAME=value. */ + * form NAME=value. (native) */ { + Tcl_DString nameString; int nameLength; char *name, *value; if (string == NULL) { return 0; } /* - * Separate the string into name and value parts, then call - * TclSetEnv to do all of the real work. + * 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. */ - value = strchr(string, '='); + name = Tcl_ExternalToUtfDString(NULL, string, -1, &nameString); + value = strchr(name, '='); if (value == NULL) { return 0; } - nameLength = value - string; + nameLength = value - name; if (nameLength == 0) { return 0; } - name = (char *) ckalloc((unsigned) nameLength+1); - memcpy((VOID *) name, (VOID *) string, (size_t) nameLength); - name[nameLength] = 0; + + value[0] = '\0'; TclSetEnv(name, value+1); - ckfree(name); + Tcl_DStringFree(&nameString); return 0; } /* *---------------------------------------------------------------------- @@ -355,35 +338,31 @@ *---------------------------------------------------------------------- */ void TclUnsetEnv(name) - CONST char *name; /* Name of variable to remove. */ + CONST char *name; /* Name of variable to remove (UTF-8). */ { - EnvInterp *eiPtr; char *oldValue; int length, index; #ifdef USE_PUTENV + Tcl_DString envString; char *string; #else char **envPtr; #endif -#ifdef MAC_TCL - if (environ == NULL) { - environSize = TclMacCreateEnv(); - } -#endif - - index = FindVariable(name, &length); + 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. */ @@ -398,83 +377,101 @@ #ifdef USE_PUTENV string = ckalloc(length+2); memcpy((VOID *) string, (VOID *) name, (size_t) length); string[length] = '='; string[length+1] = '\0'; - putenv(string); + + Tcl_UtfToExternalDString(NULL, string, -1, &envString); ckfree(string); + string = Tcl_DStringValue(&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) { + Tcl_DStringFree(&envString); + } else { + ReplaceString(oldValue, string); + } #else for (envPtr = environ+index+1; ; envPtr++) { envPtr[-1] = *envPtr; if (*envPtr == NULL) { break; } } + ReplaceString(oldValue, NULL); #endif - /* - * Replace the old value in the cache. - */ - - ReplaceString(oldValue, NULL); - - /* - * Update all of the interpreters. - */ - - for (eiPtr = firstInterpPtr; eiPtr != NULL; eiPtr = eiPtr->nextPtr) { - (void) Tcl_UnsetVar2(eiPtr->interp, "env", (char *) name, - TCL_GLOBAL_ONLY); - } + Tcl_MutexUnlock(&envMutex); } /* - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- * * TclGetEnv -- * * Retrieve the value of an environment variable. * * Results: - * Returns a pointer to a static string in the environment, - * or NULL if the value was not found. + * 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. * *---------------------------------------------------------------------- */ char * -TclGetEnv(name) - CONST char *name; /* Name of variable to find. */ +TclGetEnv(name, valuePtr) + 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; - -#ifdef MAC_TCL - if (environ == NULL) { - environSize = TclMacCreateEnv(); - } -#endif - - index = FindVariable(name, &length); - if ((index != -1) && (*(environ[index]+length) == '=')) { - return environ[index]+length+1; - } else { - return NULL; - } + 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 procedure is invoked whenever an environment variable - * is modified or deleted. It propagates the change to the - * "environ" array and to any other interpreters for whom - * we're managing an "env" array. + * is read, modified or deleted. It propagates the change to the global + * "environ" array. * * Results: * Always returns NULL to indicate success. * * Side effects: @@ -491,53 +488,62 @@ EnvTraceProc(clientData, interp, name1, name2, flags) ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Interpreter whose "env" variable is * being modified. */ char *name1; /* Better be "env". */ - char *name2; /* Name of variable being modified, or - * NULL if whole array is being deleted. */ + char *name2; /* Name of variable being modified, or NULL + * if whole array is being deleted (UTF-8). */ int flags; /* Indicates what's happening. */ { /* - * First see if the whole "env" variable is being deleted. If - * so, just forget about this interpreter. + * 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) { - register EnvInterp *eiPtr, *prevPtr; - - if ((flags & (TCL_TRACE_UNSETS|TCL_TRACE_DESTROYED)) - != (TCL_TRACE_UNSETS|TCL_TRACE_DESTROYED)) { - panic("EnvTraceProc called with confusing arguments"); - } - eiPtr = firstInterpPtr; - if (eiPtr->interp == interp) { - firstInterpPtr = eiPtr->nextPtr; - } else { - for (prevPtr = eiPtr, eiPtr = eiPtr->nextPtr; ; - prevPtr = eiPtr, eiPtr = eiPtr->nextPtr) { - if (eiPtr == NULL) { - panic("EnvTraceProc couldn't find interpreter"); - } - if (eiPtr->interp == interp) { - prevPtr->nextPtr = eiPtr->nextPtr; - break; - } - } - } - ckfree((char *) eiPtr); return NULL; } /* * If a value is being set, call TclSetEnv to do all of the work. */ if (flags & TCL_TRACE_WRITES) { - TclSetEnv(name2, Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY)); + 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; + char *value; + + value = TclGetEnv(name2, &valueString); + if (value == NULL) { + return "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; } @@ -602,11 +608,11 @@ /* * We need to grow the cache in order to hold the new string. */ - newCache = (char **) ckalloc((size_t) allocatedSize); + newCache = (char **) ckalloc((unsigned) allocatedSize); (VOID *) memset(newCache, (int) 0, (size_t) allocatedSize); if (environCache) { memcpy((VOID *) newCache, (VOID *) environCache, (size_t) (cacheSize * sizeof(char*))); @@ -616,54 +622,10 @@ environCache[cacheSize] = (char *) newStr; environCache[cacheSize+1] = NULL; cacheSize += 5; } } - -/* - *---------------------------------------------------------------------- - * - * FindVariable -- - * - * Locate the entry in environ for a given name. - * - * 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. - * - *---------------------------------------------------------------------- - */ - -static int -FindVariable(name, lengthPtr) - CONST char *name; /* Name of desired environment variable. */ - int *lengthPtr; /* Used to return length of name (for - * successful searches) or number of non-NULL - * entries in environ (for unsuccessful - * searches). */ -{ - int i; - register CONST char *p1, *p2; - - for (i = 0, p1 = environ[i]; p1 != NULL; i++, p1 = environ[i]) { - for (p2 = name; *p2 == *p1; p1++, p2++) { - /* NULL loop body. */ - } - if ((*p1 == '=') && (*p2 == '\0')) { - *lengthPtr = p2-name; - return i; - } - } - *lengthPtr = i; - return -1; -} /* *---------------------------------------------------------------------- * * TclFinalizeEnvironment -- @@ -699,5 +661,9 @@ #ifndef USE_PUTENV environSize = 0; #endif } } + + + + Index: generic/tclEvent.c ================================================================== --- generic/tclEvent.c +++ generic/tclEvent.c @@ -4,16 +4,16 @@ * This file implements some general event related interfaces including * background errors, exit handlers, and the "vwait" and "update" * command procedures. * * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclEvent.c 1.153 97/08/11 20:22:31 + * RCS: @(#) $Id: tclEvent.c,v 1.1.2.10 1999/04/03 01:35:19 welch Exp $ */ #include "tclInt.h" #include "tclPort.h" @@ -26,12 +26,13 @@ typedef struct BgError { Tcl_Interp *interp; /* Interpreter in which error occurred. NULL * means this error report has been cancelled * (a previous report generated a break). */ - char *errorMsg; /* The error message (interp->result when - * the error occurred). Malloc-ed. */ + char *errorMsg; /* Copy of the error message (the interp's + * result when the error occurred). + * Malloc-ed. */ char *errorInfo; /* Value of the errorInfo variable * (malloc-ed). */ char *errorCode; /* Value of the errorCode variable * (malloc-ed). */ struct BgError *nextPtr; /* Next in list of all pending error @@ -64,31 +65,42 @@ 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. */ +TCL_DECLARE_MUTEX(exitMutex) /* - * The following variable is a "secret" indication to Tcl_Exit 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; - -/* - * This variable is set to 1 when Tcl_Exit is called, and at the end of + * This variable is set to 1 when Tcl_Finalize is called, and at the end of * its work, it is reset to 0. The variable is checked by TclInExit() to * allow different behavior for exit-time processing, e.g. in closing of * files and pipes. */ -static int tclInExit = 0; +static int inFinalize = 0; +static int subsystemsInitialized = 0; +static int encodingsInitialized = 0; + +static Tcl_Obj *tclLibraryPath = 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; /* * Prototypes for procedures referenced only in this file: */ @@ -125,10 +137,11 @@ * occurred. */ { BgError *errPtr; char *errResult, *varValue; ErrAssocData *assocPtr; + int length; /* * The Tcl_AddErrorInfo call below (with an empty string) ensures that * errorInfo gets properly set. It's needed in cases where the error * came from a utility procedure like Tcl_GetVar instead of Tcl_Eval; @@ -136,16 +149,16 @@ * procedure is called. */ Tcl_AddErrorInfo(interp, ""); - errResult = TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL); + errResult = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length); errPtr = (BgError *) ckalloc(sizeof(BgError)); errPtr->interp = interp; - errPtr->errorMsg = (char *) ckalloc((unsigned) (strlen(errResult) + 1)); - strcpy(errPtr->errorMsg, errResult); + errPtr->errorMsg = (char *) ckalloc((unsigned) (length + 1)); + memcpy(errPtr->errorMsg, errResult, (size_t) (length + 1)); varValue = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); if (varValue == NULL) { varValue = errPtr->errorMsg; } errPtr->errorInfo = (char *) ckalloc((unsigned) (strlen(varValue) + 1)); @@ -204,11 +217,10 @@ static void HandleBgErrors(clientData) ClientData clientData; /* Pointer to ErrAssocData structure. */ { Tcl_Interp *interp; - char *command; char *argv[2]; int code; BgError *errPtr; ErrAssocData *assocPtr = (ErrAssocData *) clientData; Tcl_Channel errChannel; @@ -235,15 +247,14 @@ * Create and invoke the bgerror command. */ argv[0] = "bgerror"; argv[1] = assocPtr->firstBgPtr->errorMsg; - command = Tcl_Merge(2, argv); + Tcl_AllowExceptions(interp); Tcl_Preserve((ClientData) interp); - code = Tcl_GlobalEval(interp, command); - ckfree(command); + code = TclGlobalInvoke(interp, 2, argv, 0); if (code == TCL_ERROR) { /* * If the interpreter is safe, we look for a hidden command * named "bgerror" and call that with the error information. @@ -254,33 +265,15 @@ * interpose on such attacks and e.g. kill the applet after a * few attempts. */ if (Tcl_IsSafe(interp)) { - Tcl_HashTable *hTblPtr; - Tcl_HashEntry *hPtr; - - hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, - "tclHiddenCmds", NULL); - if (hTblPtr == (Tcl_HashTable *) NULL) { - goto doneWithInterp; - } - hPtr = Tcl_FindHashEntry(hTblPtr, "bgerror"); - if (hPtr == (Tcl_HashEntry *) NULL) { - goto doneWithInterp; - } - - /* - * OK, the hidden command "bgerror" exists, invoke it. - */ - - argv[0] = "bgerror"; - argv[1] = ckalloc((unsigned) - strlen(assocPtr->firstBgPtr->errorMsg)); - strcpy(argv[1], assocPtr->firstBgPtr->errorMsg); - (void) TclInvoke(interp, 2, argv, TCL_INVOKE_HIDDEN); - ckfree(argv[1]); + Tcl_SavedResult save; + + Tcl_SaveResult(interp, &save); + TclGlobalInvoke(interp, 2, argv, TCL_INVOKE_HIDDEN); + Tcl_RestoreResult(interp, &save); goto doneWithInterp; } /* @@ -288,26 +281,28 @@ * time, because the eval (above) might have changed the channel. */ errChannel = Tcl_GetStdChannel(TCL_STDERR); if (errChannel != (Tcl_Channel) NULL) { - if (strcmp(interp->result, - "\"bgerror\" is an invalid command name or ambiguous abbreviation") - == 0) { - Tcl_Write(errChannel, assocPtr->firstBgPtr->errorInfo, -1); - Tcl_Write(errChannel, "\n", -1); + char *string; + int len; + + string = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &len); + if (strcmp(string, "\"bgerror\" is an invalid command name or ambiguous abbreviation") == 0) { + Tcl_WriteChars(errChannel, assocPtr->firstBgPtr->errorInfo, -1); + Tcl_WriteChars(errChannel, "\n", -1); } else { - Tcl_Write(errChannel, + Tcl_WriteChars(errChannel, "bgerror failed to handle background error.\n", -1); - Tcl_Write(errChannel, " Original error: ", -1); - Tcl_Write(errChannel, assocPtr->firstBgPtr->errorMsg, + Tcl_WriteChars(errChannel, " Original error: ", -1); + Tcl_WriteChars(errChannel, assocPtr->firstBgPtr->errorMsg, -1); - Tcl_Write(errChannel, "\n", -1); - Tcl_Write(errChannel, " Error in bgerror: ", -1); - Tcl_Write(errChannel, interp->result, -1); - Tcl_Write(errChannel, "\n", -1); + Tcl_WriteChars(errChannel, "\n", -1); + Tcl_WriteChars(errChannel, " Error in bgerror: ", -1); + Tcl_WriteChars(errChannel, string, len); + Tcl_WriteChars(errChannel, "\n", -1); } Tcl_Flush(errChannel); } } else if (code == TCL_BREAK) { @@ -414,12 +409,14 @@ ExitHandler *exitPtr; exitPtr = (ExitHandler *) ckalloc(sizeof(ExitHandler)); exitPtr->proc = proc; exitPtr->clientData = clientData; + Tcl_MutexLock(&exitMutex); exitPtr->nextPtr = firstExitPtr; firstExitPtr = exitPtr; + Tcl_MutexUnlock(&exitMutex); } /* *---------------------------------------------------------------------- * @@ -444,19 +441,96 @@ Tcl_ExitProc *proc; /* Procedure 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; } + Tcl_MutexUnlock(&exitMutex); + ckfree((char *) exitPtr); + return; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_CreateThreadExitHandler -- + * + * Arrange for a given procedure 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(proc, clientData) + Tcl_ExitProc *proc; /* Procedure to invoke. */ + ClientData clientData; /* Arbitrary value to pass to proc. */ +{ + ExitHandler *exitPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + exitPtr = (ExitHandler *) ckalloc(sizeof(ExitHandler)); + exitPtr->proc = proc; + exitPtr->clientData = clientData; + exitPtr->nextPtr = tsdPtr->firstExitPtr; + tsdPtr->firstExitPtr = exitPtr; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DeleteThreadExitHandler -- + * + * This procedure 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 cancelled; if no such handler exists then nothing + * happens. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_DeleteThreadExitHandler(proc, clientData) + Tcl_ExitProc *proc; /* Procedure 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((char *) exitPtr); return; } } } @@ -482,68 +556,415 @@ Tcl_Exit(status) int status; /* Exit status for application; typically * 0 for normal return, 1 for error return. */ { Tcl_Finalize(); + TclpExit(status); +} + +/* + *------------------------------------------------------------------------- + * + * TclSetLibraryPath -- + * + * Set the path that will be used for searching for init.tcl and + * encodings when an interp is being created. + * + * Results: + * None. + * + * Side effects: + * Changing the library path will affect what directories are + * examined when looking for encodings for all interps from that + * point forward. + * + * The refcount of the new library path is incremented and the + * refcount of the old path is decremented. + * + *------------------------------------------------------------------------- + */ + +void +TclSetLibraryPath(pathPtr) + Tcl_Obj *pathPtr; /* A Tcl list object whose elements are + * the new library path. */ +{ + Tcl_MutexLock(&exitMutex); + if (pathPtr != NULL) { + Tcl_IncrRefCount(pathPtr); + } + if (tclLibraryPath != NULL) { + Tcl_DecrRefCount(tclLibraryPath); + } + tclLibraryPath = pathPtr; + Tcl_MutexUnlock(&exitMutex); +} + +/* + *------------------------------------------------------------------------- + * + * TclGetLibraryPath -- + * + * Return a Tcl list object whose elements are the library path. + * The caller should not modify the contents of the returned object. + * + * Results: + * As above. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +Tcl_Obj * +TclGetLibraryPath() +{ + return tclLibraryPath; +} + +/* + *------------------------------------------------------------------------- + * + * 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(argv0) + CONST char *argv0; /* Name of executable from argv[0] to main() + * in native multi-byte encoding. */ +{ + ThreadSpecificData *tsdPtr; + + if (inFinalize != 0) { + panic("TclInitSubsystems called while finalizing"); + } + + /* + * Grab the thread local storage pointer before doing anything because + * the initialization routines will be registering exit handlers. + * We use this pointer to detect if this is the first time this + * thread has created an interpreter. + */ + + tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey); + if (subsystemsInitialized == 0) { + /* + * Double check inside the mutex. There are definitly calls + * back into this routine from some of the procedures below. + */ + + TclpInitLock(); + if (subsystemsInitialized == 0) { + /* + * Have to set this bit here to avoid deadlock with the + * routines below us that call into TclInitSubsystems. + */ + + subsystemsInitialized = 1; + + tclExecutableName = NULL; + + /* + * Initialize locks used by the memory allocators before anything + * interesting happens so we can use the allocators in the + * implementation of self-initializing locks. + */ +#if USE_TCLALLOC + TclInitAlloc(); +#endif #ifdef TCL_MEM_DEBUG - if (tclMemDumpFileName != NULL) { - Tcl_DumpActiveMemory(tclMemDumpFileName); - } + TclInitDbCkalloc(); #endif - TclPlatformExit(status); + + TclpInitPlatform(); + TclInitObjSubsystem(); + TclInitIOSubsystem(); + TclInitEncodingSubsystem(); + TclInitNamespaceSubsystem(); + } + TclpInitUnlock(); + } + + if (tsdPtr == NULL) { + /* + * First time this thread has created an interpreter. + * We fetch the key again just in case no exit handlers were + * registered by this point. + */ + + (void) TCL_TSD_INIT(&dataKey); + TclInitNotifier(); + } +} + +/* + *------------------------------------------------------------------------- + * + * TclFindEncodings -- + * + * Find and load the encoding file for this operating system. + * Before this is called, Tcl makes assumptions about the + * native string representation, but the true encoding is not + * assured. + * + * Results: + * None. + * + * Side effects: + * Varied, see the respective initialization routines. + * + *------------------------------------------------------------------------- + */ + +void +TclFindEncodings(argv0) + CONST char *argv0; /* Name of executable from argv[0] to main() + * in native multi-byte encoding. */ +{ + char *native; + Tcl_Obj *pathPtr; + Tcl_DString libPath, buffer; + + if (encodingsInitialized == 0) { + /* + * Double check inside the mutex. There may be calls + * back into this routine from some of the procedures below. + */ + + TclpInitLock(); + if (encodingsInitialized == 0) { + /* + * Have to set this bit here to avoid deadlock with the + * routines below us that call into TclInitSubsystems. + */ + + encodingsInitialized = 1; + + native = TclpFindExecutable(argv0); + TclpInitLibraryPath(native); + + /* + * The library path was set in the TclpInitLibraryPath routine. + * The string set is a dirty UTF string. To preserve the value + * convert the UTF string back to native before setting the new + * default encoding. + */ + + pathPtr = TclGetLibraryPath(); + if (pathPtr != NULL) { + Tcl_UtfToExternalDString(NULL, Tcl_GetString(pathPtr), -1, + &libPath); + } + + TclpSetInitialEncodings(); + + /* + * Now convert the native sting back to native string back to UTF. + */ + + if (pathPtr != NULL) { + Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&libPath), -1, + &buffer); + pathPtr = Tcl_NewStringObj(Tcl_DStringValue(&buffer), -1); + TclSetLibraryPath(pathPtr); + + Tcl_DStringFree(&libPath); + Tcl_DStringFree(&buffer); + } + } + TclpInitUnlock(); + } } /* *---------------------------------------------------------------------- * * Tcl_Finalize -- * - * Runs the exit handlers to allow Tcl to clean up its state prior - * to being unloaded. Called by Tcl_Exit and when Tcl was dynamically - * loaded and is now being unloaded. + * Shut down Tcl. First calls registered exit handlers, then + * carefully shuts down various subsystems. + * Called by Tcl_Exit or when the Tcl shared library is being + * unloaded. * * Results: * None. * * Side effects: - * Whatever the exit handlers do. Also frees up storage associated - * with the Tcl object type table. + * Varied, see the respective finalization routines. * *---------------------------------------------------------------------- */ void Tcl_Finalize() { ExitHandler *exitPtr; - - /* - * Invoke exit handler first. - */ - - tclInExit = 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; - (*exitPtr->proc)(exitPtr->clientData); - ckfree((char *) exitPtr); - } - - /* - * Now finalize the Tcl execution environment. Note that this must be done - * after the exit handlers, because there are order dependencies. - */ - - TclFinalizeCompExecEnv(); - TclFinalizeEnvironment(); - firstExitPtr = NULL; - tclInExit = 0; + + TclpInitLock(); + if (subsystemsInitialized != 0) { + subsystemsInitialized = 0; + encodingsInitialized = 0; + + /* + * Invoke exit handlers first. + */ + + Tcl_MutexLock(&exitMutex); + inFinalize = 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((char *) exitPtr); + Tcl_MutexLock(&exitMutex); + } + firstExitPtr = NULL; + Tcl_MutexUnlock(&exitMutex); + + /* + * 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 after this call. + */ + + Tcl_FinalizeThread(); + + /* + * Now finalize the Tcl execution environment. Note that this + * must be done after the exit handlers, because there are + * order dependencies. + */ + + TclFinalizeCompExecEnv(); + TclFinalizeEnvironment(); + + TclFinalizeEncodingSubsystem(); + + if (tclLibraryPath != NULL) { + Tcl_DecrRefCount(tclLibraryPath); + tclLibraryPath = NULL; + } + if (tclExecutableName != NULL) { + ckfree(tclExecutableName); + tclExecutableName = NULL; + } + if (tclNativeExecutableName != NULL) { + ckfree(tclNativeExecutableName); + tclNativeExecutableName = NULL; + } + if (tclDefaultEncodingDir != NULL) { + ckfree(tclDefaultEncodingDir); + tclDefaultEncodingDir = NULL; + } + + Tcl_SetPanicProc(NULL); + + /* + * Free synchronization objects. There really should only be one + * thread alive at this moment. + */ + + TclFinalizeSynchronization(); + + /* + * We defer unloading of packages until very late + * to avoid memory access issues. Both exit callbacks and + * synchronization variables may be stored in packages. + */ + + TclFinalizeLoad(); + + /* + * There shouldn't be any malloc'ed memory after this. + */ + + TclFinalizeMemorySubsystem(); + inFinalize = 0; + } + TclpInitUnlock(); +} + +/* + *---------------------------------------------------------------------- + * + * 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() +{ + ExitHandler *exitPtr; + ThreadSpecificData *tsdPtr = + (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey); + + if (tsdPtr != NULL) { + /* + * Invoke thread exit handlers first. + */ + + 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((char *) exitPtr); + } + TclFinalizeIOSubsystem(); + TclFinalizeNotifier(); + + /* + * Blow away all thread local storage blocks. + */ + + TclFinalizeThreadData(); + } } /* *---------------------------------------------------------------------- * @@ -561,17 +982,18 @@ */ int TclInExit() { - return tclInExit; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return tsdPtr->inExit; } /* *---------------------------------------------------------------------- * - * Tcl_VwaitCmd -- + * Tcl_VwaitObjCmd -- * * This procedure is invoked to process the "vwait" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -583,34 +1005,35 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_VwaitCmd(clientData, interp, argc, argv) +Tcl_VwaitObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { int done, foundEvent; + char *nameString; - if (argc != 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " name\"", (char *) NULL); + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } - if (Tcl_TraceVar(interp, argv[1], + nameString = Tcl_GetString(objv[1]); + if (Tcl_TraceVar(interp, nameString, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, VwaitVarProc, (ClientData) &done) != TCL_OK) { return TCL_ERROR; }; done = 0; foundEvent = 1; while (!done && foundEvent) { foundEvent = Tcl_DoOneEvent(TCL_ALL_EVENTS); } - Tcl_UntraceVar(interp, argv[1], + Tcl_UntraceVar(interp, nameString, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, VwaitVarProc, (ClientData) &done); /* * Clear out the interpreter's result, since it may have been set @@ -617,11 +1040,11 @@ * by event handlers. */ Tcl_ResetResult(interp); if (!foundEvent) { - Tcl_AppendResult(interp, "can't wait for variable \"", argv[1], + Tcl_AppendResult(interp, "can't wait for variable \"", nameString, "\": would wait forever", (char *) NULL); return TCL_ERROR; } return TCL_OK; } @@ -642,11 +1065,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_UpdateCmd -- + * Tcl_UpdateObjCmd -- * * This procedure is invoked to process the "update" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -658,33 +1081,42 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_UpdateCmd(clientData, interp, argc, argv) - ClientData clientData; /* Not used. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ -{ - int flags; - - if (argc == 1) { - flags = TCL_ALL_EVENTS|TCL_DONT_WAIT; - } else if (argc == 2) { - if (strncmp(argv[1], "idletasks", strlen(argv[1])) != 0) { - Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": must be idletasks", (char *) NULL); - return TCL_ERROR; - } - flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT; - } else { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " ?idletasks?\"", (char *) NULL); - return TCL_ERROR; - } - +Tcl_UpdateObjCmd(clientData, interp, objc, objv) + 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 char *updateOptions[] = {"idletasks", (char *) NULL}; + enum updateOptions {REGEXP_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 REGEXP_IDLETASKS: { + flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT; + break; + } + default: { + panic("Tcl_UpdateObjCmd: bad option index to UpdateOptions"); + } + } + } else { + Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?"); + return TCL_ERROR; + } + while (Tcl_DoOneEvent(flags) != 0) { /* Empty loop body */ } /* Index: generic/tclExecute.c ================================================================== --- generic/tclExecute.c +++ generic/tclExecute.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) tclExecute.c 1.102 97/11/06 11:36:35 + * RCS: @(#) $Id: tclExecute.c,v 1.1.2.10 1999/03/25 03:55:31 stanton Exp $ */ #include "tclInt.h" #include "tclCompile.h" @@ -46,10 +46,11 @@ * Boolean flag indicating whether the Tcl bytecode interpreter has been * initialized. */ static int execInitialized = 0; +TCL_DECLARE_MUTEX(execMutex) /* * Variable that controls whether execution tracing is enabled and, if so, * what level of tracing is desired: * 0: no execution tracing @@ -59,18 +60,23 @@ * This variable is linked to the Tcl variable "tcl_traceExec". */ int tclTraceExec = 0; -/* - * The following global variable is use to signal matherr that Tcl - * is responsible for the arithmetic, so errors can be handled in a - * fashion appropriate for Tcl. Zero means no Tcl math is in - * progress; non-zero means Tcl is doing math. - */ - -int tcl_MathInProgress = 0; +typedef struct ThreadSpecificData { + /* + * The following global variable is use to signal matherr that Tcl + * is responsible for the arithmetic, so errors can be handled in a + * fashion appropriate for Tcl. Zero means no Tcl math is in + * progress; non-zero means Tcl is doing math. + */ + + int mathInProgress; + +} ThreadSpecificData; + +static Tcl_ThreadDataKey dataKey; /* * The variable below serves no useful purpose except to generate * a reference to matherr, so that the Tcl version of matherr is * linked in rather than the system version. Without this reference @@ -81,16 +87,10 @@ #ifdef NEED_MATHERR extern int matherr(); int (*tclMatherrPtr)() = matherr; #endif -/* - * Array of instruction names. - */ - -static char *opName[256]; - /* * 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. */ @@ -108,22 +108,11 @@ #ifdef TCL_COMPILE_DEBUG static char *resultStrings[] = { "TCL_OK", "TCL_ERROR", "TCL_RETURN", "TCL_BREAK", "TCL_CONTINUE" }; -#endif /* TCL_COMPILE_DEBUG */ - -/* - * The following are statistics-related variables that record information - * about the bytecode compiler and interpreter's operation. This includes - * an array that records for each instruction how often it is executed. - */ - -#ifdef TCL_COMPILE_STATS -static long numExecutions = 0; -static int instructionCount[256]; -#endif /* TCL_COMPILE_STATS */ +#endif /* * Macros for testing floating-point values for certain special cases. Test * for not-a-number by comparing a value against itself; test for infinity * by comparing against the largest floating-point value. @@ -140,11 +129,12 @@ * Macro to adjust the program counter and restart the instruction execution * loop after each instruction is executed. */ #define ADJUST_PC(instBytes) \ - pc += instBytes; continue + pc += (instBytes); \ + continue /* * 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 TclExecuteByteCode (and a few other @@ -166,89 +156,51 @@ * 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. - */ - -#define STK_ITEM(offset) (stackPtr[stackTop + (offset)]) -#define STK_OBJECT(offset) (STK_ITEM(offset).o) -#define STK_INT(offset) (STK_ITEM(offset).i) -#define STK_POINTER(offset) (STK_ITEM(offset).p) - -/* + * * 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(stackPtr[++stackTop].o = (objPtr)) + Tcl_IncrRefCount(stackPtr[++stackTop] = (objPtr)) #define POP_OBJECT() \ - (stackPtr[stackTop--].o) + (stackPtr[stackTop--]) /* * Macros used to trace instruction execution. The macros TRACE, * TRACE_WITH_OBJ, and O2S are only used inside TclExecuteByteCode. * O2S is only used in TRACE* calls to get a string from an object. - * - * NOTE THAT CLIENTS OF O2S ARE LIKELY TO FAIL IF THE OBJECT'S - * STRING REP CONTAINS NULLS. - */ - -#ifdef TCL_COMPILE_DEBUG - -#define O2S(objPtr) \ - Tcl_GetStringFromObj((objPtr), &length) - -#ifdef TCL_COMPILE_STATS -#define TRACE(a) \ - if (traceInstructions) { \ - fprintf(stdout, "%d: %d,%ld (%u) ", iPtr->numLevels, \ - stackTop, (tclObjsAlloced - tclObjsFreed), \ - (unsigned int)(pc - codePtr->codeStart)); \ - printf a; \ - fflush(stdout); \ - } -#define TRACE_WITH_OBJ(a, objPtr) \ - if (traceInstructions) { \ - fprintf(stdout, "%d: %d,%ld (%u) ", iPtr->numLevels, \ - stackTop, (tclObjsAlloced - tclObjsFreed), \ - (unsigned int)(pc - codePtr->codeStart)); \ - printf a; \ - bytes = Tcl_GetStringFromObj((objPtr), &length); \ - TclPrintSource(stdout, bytes, TclMin(length, 30)); \ - fprintf(stdout, "\n"); \ - fflush(stdout); \ - } -#else /* not TCL_COMPILE_STATS */ -#define TRACE(a) \ - if (traceInstructions) { \ - fprintf(stdout, "%d: %d (%u) ", iPtr->numLevels, stackTop, \ - (unsigned int)(pc - codePtr->codeStart)); \ - printf a; \ - fflush(stdout); \ - } -#define TRACE_WITH_OBJ(a, objPtr) \ - if (traceInstructions) { \ - fprintf(stdout, "%d: %d (%u) ", iPtr->numLevels, stackTop, \ - (unsigned int)(pc - codePtr->codeStart)); \ - printf a; \ - bytes = Tcl_GetStringFromObj((objPtr), &length); \ - TclPrintSource(stdout, bytes, TclMin(length, 30)); \ - fprintf(stdout, "\n"); \ - fflush(stdout); \ - } -#endif /* TCL_COMPILE_STATS */ - -#else /* not TCL_COMPILE_DEBUG */ - -#define TRACE(a) -#define TRACE_WITH_OBJ(a, objPtr) -#define O2S(objPtr) - + */ + +#ifdef TCL_COMPILE_DEBUG +#define TRACE(a) \ + if (traceInstructions) { \ + fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, stackTop, \ + (unsigned int)(pc - codePtr->codeStart), \ + GetOpcodeName(pc)); \ + printf a; \ + } +#define TRACE_WITH_OBJ(a, objPtr) \ + if (traceInstructions) { \ + fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, stackTop, \ + (unsigned int)(pc - codePtr->codeStart), \ + GetOpcodeName(pc)); \ + printf a; \ + TclPrintObject(stdout, (objPtr), 30); \ + fprintf(stdout, "\n"); \ + } +#define O2S(objPtr) \ + Tcl_GetString(objPtr) +#else +#define TRACE(a) +#define TRACE_WITH_OBJ(a, objPtr) +#define O2S(objPtr) #endif /* TCL_COMPILE_DEBUG */ /* * Declarations for local procedures to this file: */ @@ -278,36 +230,38 @@ static int ExprUnaryFunc _ANSI_ARGS_((Tcl_Interp *interp, ExecEnv *eePtr, ClientData clientData)); #ifdef TCL_COMPILE_STATS static int EvalStatsCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv)); -#endif /* TCL_COMPILE_STATS */ +#endif static void FreeCmdNameInternalRep _ANSI_ARGS_(( Tcl_Obj *objPtr)); +#ifdef TCL_COMPILE_DEBUG +static char * GetOpcodeName _ANSI_ARGS_((unsigned char *pc)); +#endif +static ExceptionRange * GetExceptRangeForPc _ANSI_ARGS_((unsigned char *pc, + int catchOnly, ByteCode* codePtr)); static char * GetSrcInfoForPc _ANSI_ARGS_((unsigned char *pc, ByteCode* codePtr, int *lengthPtr)); static void GrowEvaluationStack _ANSI_ARGS_((ExecEnv *eePtr)); static void IllegalExprOperandType _ANSI_ARGS_(( - Tcl_Interp *interp, unsigned int opCode, + Tcl_Interp *interp, unsigned char *pc, Tcl_Obj *opndPtr)); static void InitByteCodeExecution _ANSI_ARGS_(( Tcl_Interp *interp)); +#ifdef TCL_COMPILE_DEBUG static void PrintByteCodeInfo _ANSI_ARGS_((ByteCode *codePtr)); -static void RecordTracebackInfo _ANSI_ARGS_((Tcl_Interp *interp, - unsigned char *pc, ByteCode *codePtr)); +#endif static int SetCmdNameFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr)); #ifdef TCL_COMPILE_DEBUG static char * StringForResultCode _ANSI_ARGS_((int result)); -#endif /* TCL_COMPILE_DEBUG */ -static void UpdateStringOfCmdName _ANSI_ARGS_((Tcl_Obj *objPtr)); -#ifdef TCL_COMPILE_DEBUG static void ValidatePcAndStackTop _ANSI_ARGS_(( ByteCode *codePtr, unsigned char *pc, int stackTop, int stackLowerBound, int stackUpperBound)); -#endif /* TCL_COMPILE_DEBUG */ +#endif /* * 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. @@ -354,11 +308,11 @@ Tcl_ObjType tclCmdNameType = { "cmdName", /* name */ FreeCmdNameInternalRep, /* freeIntRepProc */ DupCmdNameInternalRep, /* dupIntRepProc */ - UpdateStringOfCmdName, /* updateStringProc */ + (Tcl_UpdateStringProc *) NULL, /* updateStringProc */ SetCmdNameFromAny /* setFromAnyProc */ }; /* *---------------------------------------------------------------------- @@ -386,32 +340,20 @@ InitByteCodeExecution(interp) Tcl_Interp *interp; /* Interpreter for which the Tcl variable * "tcl_traceExec" is linked to control * instruction tracing. */ { - int i; - Tcl_RegisterObjType(&tclCmdNameType); - - (VOID *) memset(opName, 0, sizeof(opName)); - for (i = 0; instructionTable[i].name != NULL; i++) { - opName[i] = instructionTable[i].name; - } - -#ifdef TCL_COMPILE_STATS - (VOID *) memset(instructionCount, 0, sizeof(instructionCount)); - (VOID *) memset(tclByteCodeCount, 0, sizeof(tclByteCodeCount)); - (VOID *) memset(tclSourceCount, 0, sizeof(tclSourceCount)); - - Tcl_CreateCommand(interp, "evalstats", EvalStatsCmd, - (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); -#endif /* TCL_COMPILE_STATS */ - if (Tcl_LinkVar(interp, "tcl_traceExec", (char *) &tclTraceExec, TCL_LINK_INT) != TCL_OK) { panic("InitByteCodeExecution: can't create link for tcl_traceExec variable"); } + +#ifdef TCL_COMPILE_STATS + Tcl_CreateCommand(interp, "evalstats", EvalStatsCmd, + (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); +#endif /* TCL_COMPILE_STATS */ } /* *---------------------------------------------------------------------- * @@ -441,19 +383,22 @@ Tcl_Interp *interp; /* Interpreter for which the execution * environment is being created. */ { ExecEnv *eePtr = (ExecEnv *) ckalloc(sizeof(ExecEnv)); - eePtr->stackPtr = (StackItem *) - ckalloc((unsigned) (TCL_STACK_INITIAL_SIZE * sizeof(StackItem))); + eePtr->stackPtr = (Tcl_Obj **) + ckalloc((unsigned) (TCL_STACK_INITIAL_SIZE * sizeof(Tcl_Obj *))); eePtr->stackTop = -1; eePtr->stackEnd = (TCL_STACK_INITIAL_SIZE - 1); + Tcl_MutexLock(&execMutex); if (!execInitialized) { + TclInitAuxDataTypeTable(); InitByteCodeExecution(interp); execInitialized = 1; } + Tcl_MutexUnlock(&execMutex); return eePtr; } #undef TCL_STACK_INITIAL_SIZE @@ -483,11 +428,11 @@ } /* *---------------------------------------------------------------------- * - * TclFinalizeExecEnv -- + * TclFinalizeExecution -- * * Finalizes the execution environment setup so that it can be * later reinitialized. * * Results: @@ -499,13 +444,16 @@ * *---------------------------------------------------------------------- */ void -TclFinalizeExecEnv() +TclFinalizeExecution() { + Tcl_MutexLock(&execMutex); execInitialized = 0; + Tcl_MutexUnlock(&execMutex); + TclFinalizeAuxDataTypeTable(); } /* *---------------------------------------------------------------------- * @@ -532,13 +480,13 @@ * to eePtr->stackPtr[eePtr->stackEnd] (inclusive). */ int currElems = (eePtr->stackEnd + 1); int newElems = 2*currElems; - int currBytes = currElems * sizeof(StackItem); + int currBytes = currElems * sizeof(Tcl_Obj *); int newBytes = 2*currBytes; - StackItem *newStackPtr = (StackItem *) ckalloc((unsigned) newBytes); + Tcl_Obj **newStackPtr = (Tcl_Obj **) ckalloc((unsigned) newBytes); /* * Copy the existing stack items to the new stack space, free the old * storage if appropriate, and mark new space as malloc'ed. */ @@ -576,76 +524,63 @@ ByteCode *codePtr; /* The bytecode sequence to interpret. */ { Interp *iPtr = (Interp *) interp; ExecEnv *eePtr = iPtr->execEnvPtr; /* Points to the execution environment. */ - register StackItem *stackPtr = eePtr->stackPtr; + register Tcl_Obj **stackPtr = eePtr->stackPtr; /* Cached evaluation stack base pointer. */ register int stackTop = eePtr->stackTop; /* Cached top index of evaluation stack. */ - Tcl_Obj **objArrayPtr = codePtr->objArrayPtr; - /* Points to the ByteCode's object array. */ - unsigned char *pc = codePtr->codeStart; + register unsigned char *pc = codePtr->codeStart; /* The current program counter. */ - unsigned char opCode; /* The current instruction code. */ int opnd; /* Current instruction's operand byte. */ int pcAdjustment; /* Hold pc adjustment after instruction. */ int initStackTop = stackTop;/* Stack top at start of execution. */ 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. */ int result = TCL_OK; /* Return code returned after execution. */ int traceInstructions = (tclTraceExec == 3); - Tcl_Obj *valuePtr, *value2Ptr, *namePtr, *objPtr; + Tcl_Obj *valuePtr, *value2Ptr, *objPtr; char *bytes; int length; long i; - Tcl_DString command; /* Used for debugging. If tclTraceExec >= 2 - * holds a string representing the last - * command invoked. */ /* * This procedure uses a stack to hold information about catch commands. * This information is the current operand stack top when starting to * execute the code for each catch command. It starts out with stack- * allocated space but uses dynamically-allocated storage if needed. */ -#define STATIC_CATCH_STACK_SIZE 5 +#define STATIC_CATCH_STACK_SIZE 4 int (catchStackStorage[STATIC_CATCH_STACK_SIZE]); int *catchStackPtr = catchStackStorage; int catchTop = -1; - /* - * THIS PROC FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE. - */ - +#ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= 2) { PrintByteCodeInfo(codePtr); -#ifdef TCL_COMPILE_STATS - fprintf(stdout, " Starting stack top=%d, system objects=%ld\n", - eePtr->stackTop, (tclObjsAlloced - tclObjsFreed)); -#else fprintf(stdout, " Starting stack top=%d\n", eePtr->stackTop); -#endif /* TCL_COMPILE_STATS */ fflush(stdout); } - +#endif + #ifdef TCL_COMPILE_STATS - numExecutions++; -#endif /* TCL_COMPILE_STATS */ + iPtr->stats.numExecutions++; +#endif /* * 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. */ - if (codePtr->maxExcRangeDepth > STATIC_CATCH_STACK_SIZE) { + if (codePtr->maxExceptDepth > STATIC_CATCH_STACK_SIZE) { catchStackPtr = (int *) - ckalloc(codePtr->maxExcRangeDepth * sizeof(int)); + ckalloc(codePtr->maxExceptDepth * sizeof(int)); } /* * Make sure the stack has enough room to execute this ByteCode. */ @@ -653,17 +588,10 @@ while ((stackTop + codePtr->maxStackDepth) > eePtr->stackEnd) { GrowEvaluationStack(eePtr); stackPtr = eePtr->stackPtr; } - /* - * Initialize the buffer that holds a string containing the name and - * arguments for the last invoked command. - */ - - Tcl_DStringInit(&command); - /* * Loop executing instructions until a "done" instruction, a TCL_RETURN, * or some error. */ @@ -670,28 +598,21 @@ for (;;) { #ifdef TCL_COMPILE_DEBUG ValidatePcAndStackTop(codePtr, pc, stackTop, initStackTop, eePtr->stackEnd); #else /* not TCL_COMPILE_DEBUG */ - if (traceInstructions) { -#ifdef TCL_COMPILE_STATS - fprintf(stdout, "%d: %d,%ld ", iPtr->numLevels, stackTop, - (tclObjsAlloced - tclObjsFreed)); -#else /* TCL_COMPILE_STATS */ - fprintf(stdout, "%d: %d ", iPtr->numLevels, stackTop); -#endif /* TCL_COMPILE_STATS */ - TclPrintInstruction(codePtr, pc); - fflush(stdout); - } -#endif /* TCL_COMPILE_DEBUG */ - - opCode = *pc; -#ifdef TCL_COMPILE_STATS - instructionCount[opCode]++; -#endif /* TCL_COMPILE_STATS */ - - switch (opCode) { + if (traceInstructions) { + fprintf(stdout, "%2d: %2d ", iPtr->numLevels, stackTop); + TclPrintInstruction(codePtr, pc); + fflush(stdout); + } +#endif /* TCL_COMPILE_DEBUG */ + +#ifdef TCL_COMPILE_STATS + iPtr->stats.instructionCount[*pc]++; +#endif + switch (*pc) { case INST_DONE: /* * Pop the topmost object from the stack, set the interpreter's * object result to point to it, and return. */ @@ -701,42 +622,47 @@ if (stackTop != initStackTop) { fprintf(stderr, "\nTclExecuteByteCode: done instruction at pc %u: stack top %d != entry stack top %d\n", (unsigned int)(pc - codePtr->codeStart), (unsigned int) stackTop, (unsigned int) initStackTop); - fprintf(stderr, " Source: "); - TclPrintSource(stderr, codePtr->source, 150); panic("TclExecuteByteCode execution failure: end stack top != start stack top"); } - TRACE_WITH_OBJ(("done => return code=%d, result is ", result), + TRACE_WITH_OBJ(("=> return code=%d, result=", result), iPtr->objResultPtr); +#ifdef TCL_COMPILE_DEBUG + if (traceInstructions) { + fprintf(stdout, "\n"); + } +#endif goto done; case INST_PUSH1: - valuePtr = objArrayPtr[TclGetUInt1AtPtr(pc+1)]; +#ifdef TCL_COMPILE_DEBUG + valuePtr = codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]; PUSH_OBJECT(valuePtr); - TRACE_WITH_OBJ(("push1 %u => ", TclGetUInt1AtPtr(pc+1)), - valuePtr); + TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), valuePtr); +#else + PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]); +#endif /* TCL_COMPILE_DEBUG */ ADJUST_PC(2); case INST_PUSH4: - valuePtr = objArrayPtr[TclGetUInt4AtPtr(pc+1)]; + valuePtr = codePtr->objArrayPtr[TclGetUInt4AtPtr(pc+1)]; PUSH_OBJECT(valuePtr); - TRACE_WITH_OBJ(("push4 %u => ", TclGetUInt4AtPtr(pc+1)), - valuePtr); + TRACE_WITH_OBJ(("%u => ", TclGetUInt4AtPtr(pc+1)), valuePtr); ADJUST_PC(5); case INST_POP: valuePtr = POP_OBJECT(); - TRACE_WITH_OBJ(("pop => discarding "), valuePtr); + TRACE_WITH_OBJ(("=> discarding "), valuePtr); TclDecrRefCount(valuePtr); /* finished with pop'ed object. */ ADJUST_PC(1); case INST_DUP: - valuePtr = stackPtr[stackTop].o; + valuePtr = stackPtr[stackTop]; PUSH_OBJECT(Tcl_DuplicateObj(valuePtr)); - TRACE_WITH_OBJ(("dup => "), valuePtr); + TRACE_WITH_OBJ(("=> "), valuePtr); ADJUST_PC(1); case INST_CONCAT1: opnd = TclGetUInt1AtPtr(pc+1); { @@ -748,12 +674,11 @@ * opnd items on the stack starting with the deepest item. * First, determine how many characters are needed. */ for (i = (stackTop - (opnd-1)); i <= stackTop; i++) { - valuePtr = stackPtr[i].o; - bytes = TclGetStringFromObj(valuePtr, &length); + bytes = Tcl_GetStringFromObj(stackPtr[i], &length); if (bytes != NULL) { totalLen += length; } } @@ -766,12 +691,12 @@ if (totalLen > 0) { char *p = (char *) ckalloc((unsigned) (totalLen + 1)); concatObjPtr->bytes = p; concatObjPtr->length = totalLen; for (i = (stackTop - (opnd-1)); i <= stackTop; i++) { - valuePtr = stackPtr[i].o; - bytes = TclGetStringFromObj(valuePtr, &length); + valuePtr = stackPtr[i]; + bytes = Tcl_GetStringFromObj(valuePtr, &length); if (bytes != NULL) { memcpy((VOID *) p, (VOID *) bytes, (size_t) length); p += length; } @@ -778,18 +703,17 @@ TclDecrRefCount(valuePtr); } *p = '\0'; } else { for (i = (stackTop - (opnd-1)); i <= stackTop; i++) { - valuePtr = stackPtr[i].o; - Tcl_DecrRefCount(valuePtr); + Tcl_DecrRefCount(stackPtr[i]); } } stackTop -= opnd; PUSH_OBJECT(concatObjPtr); - TRACE_WITH_OBJ(("concat %u => ", opnd), concatObjPtr); + TRACE_WITH_OBJ(("%u => ", opnd), concatObjPtr); ADJUST_PC(2); } case INST_INVOKE_STK4: opnd = TclGetUInt4AtPtr(pc+1); @@ -800,23 +724,17 @@ opnd = TclGetUInt1AtPtr(pc+1); pcAdjustment = 2; doInvocation: { - char *cmdName; - Command *cmdPtr; /* Points to command's Command struct. */ - int objc = opnd; /* The number of arguments. */ - Tcl_Obj **objv; /* The array of argument objects. */ - Tcl_Obj *objv0Ptr; /* Holds objv[0], the command name. */ - int newPcOffset = 0; - /* Instruction offset computed during - * break, continue, error processing. - * Init. to avoid compiler warning. */ - Tcl_Command cmd; + int objc = opnd; /* The number of arguments. */ + Tcl_Obj **objv; /* The array of argument objects. */ + Command *cmdPtr; /* Points to command's Command struct. */ + int newPcOffset; /* New inst offset for break, continue. */ #ifdef TCL_COMPILE_DEBUG int isUnknownCmd = 0; - char cmdNameBuf[30]; + char cmdNameBuf[21]; #endif /* TCL_COMPILE_DEBUG */ /* * If the interpreter was deleted, return an error. */ @@ -830,53 +748,35 @@ (char *) NULL); result = TCL_ERROR; goto checkForCatch; } - objv = &(stackPtr[stackTop - (objc-1)].o); - objv0Ptr = objv[0]; - cmdName = TclGetStringFromObj(objv0Ptr, (int *) NULL); - - /* - * Find the procedure to execute this command. If there - * isn't one, then see if there is a command "unknown". If - * so, invoke it, passing it the original command words as - * arguments. - * - * We convert the objv[0] object to be a CmdName object. - * This caches a pointer to the Command structure for the - * command; this pointer is held in a ResolvedCmdName - * structure the object's internal rep. points to. - */ - - cmd = Tcl_GetCommandFromObj(interp, objv0Ptr); - cmdPtr = (Command *) cmd; - - /* - * If the command is still not found, handle it with the - * "unknown" proc. - */ - + /* + * Find the procedure to execute this command. If the + * command is not found, handle it with the "unknown" proc. + */ + + objv = &(stackPtr[stackTop - (objc-1)]); + cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]); if (cmdPtr == NULL) { - cmd = Tcl_FindCommand(interp, "unknown", - (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY); - if (cmd == (Tcl_Command) NULL) { + cmdPtr = (Command *) Tcl_FindCommand(interp, "unknown", + (Tcl_Namespace *) NULL, TCL_GLOBAL_ONLY); + if (cmdPtr == NULL) { Tcl_ResetResult(interp); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "invalid command name \"", cmdName, "\"", + "invalid command name \"", + Tcl_GetString(objv[0]), "\"", (char *) NULL); - TRACE(("%s %u => unknown proc not found: ", - opName[opCode], objc)); + TRACE(("%u => unknown proc not found: ", objc)); result = TCL_ERROR; goto checkForCatch; } - cmdPtr = (Command *) cmd; #ifdef TCL_COMPILE_DEBUG isUnknownCmd = 1; #endif /*TCL_COMPILE_DEBUG*/ stackTop++; /* need room for new inserted objv[0] */ - for (i = objc; i >= 0; i--) { + for (i = objc-1; i >= 0; i--) { objv[i+1] = objv[i]; } objc++; objv[0] = Tcl_NewStringObj("unknown", -1); Tcl_IncrRefCount(objv[0]); @@ -912,42 +812,32 @@ * default empty values since they could have gotten changed * by earlier invocations. */ Tcl_ResetResult(interp); - if (tclTraceExec >= 2) { - char buffer[50]; - - sprintf(buffer, "%d: (%u) invoking ", iPtr->numLevels, - (unsigned int)(pc - codePtr->codeStart)); - Tcl_DStringAppend(&command, buffer, -1); - #ifdef TCL_COMPILE_DEBUG - if (traceInstructions) { /* tclTraceExec == 3 */ - strncpy(cmdNameBuf, cmdName, 20); - TRACE(("%s %u => call ", opName[opCode], - (isUnknownCmd? objc-1 : objc))); + if (traceInstructions) { + strncpy(cmdNameBuf, Tcl_GetString(objv[0]), 20); + TRACE(("%u => call ", (isUnknownCmd? objc-1:objc))); } else { - fprintf(stdout, "%s", buffer); + fprintf(stdout, "%d: (%u) invoking ", + iPtr->numLevels, + (unsigned int)(pc - codePtr->codeStart)); } -#else /* TCL_COMPILE_DEBUG */ - fprintf(stdout, "%s", buffer); -#endif /*TCL_COMPILE_DEBUG*/ - for (i = 0; i < objc; i++) { - bytes = TclGetStringFromObj(objv[i], &length); - TclPrintSource(stdout, bytes, TclMin(length, 15)); + TclPrintObject(stdout, objv[i], 15); fprintf(stdout, " "); - - sprintf(buffer, "\"%.*s\" ", TclMin(length, 15), bytes); - Tcl_DStringAppend(&command, buffer, -1); } fprintf(stdout, "\n"); fflush(stdout); - - Tcl_DStringFree(&command); +#else /* TCL_COMPILE_DEBUG */ + fprintf(stdout, "%d: (%u) invoking %s\n", + iPtr->numLevels, + (unsigned int)(pc - codePtr->codeStart), + Tcl_GetString(objv[0])); +#endif /*TCL_COMPILE_DEBUG*/ } iPtr->cmdCount++; DECACHE_STACK_INFO(); result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, @@ -971,18 +861,16 @@ /* * Pop the objc top stack elements and decrement their ref * counts. */ - - i = (stackTop - (objc-1)); - while (i <= stackTop) { - valuePtr = stackPtr[i].o; + + for (i = 0; i < objc; i++) { + valuePtr = stackPtr[stackTop]; TclDecrRefCount(valuePtr); - i++; + stackTop--; } - stackTop -= objc; /* * Process the result of the Tcl_ObjCmdProc call. */ @@ -991,13 +879,12 @@ /* * Push the call's object result and continue execution * with the next instruction. */ PUSH_OBJECT(Tcl_GetObjResult(interp)); - TRACE_WITH_OBJ(("%s %u => ...after \"%.20s\", result=", - opName[opCode], objc, cmdNameBuf), - Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("%u => ...after \"%.20s\", result=", + objc, cmdNameBuf), Tcl_GetObjResult(interp)); ADJUST_PC(pcAdjustment); case TCL_BREAK: case TCL_CONTINUE: /* @@ -1007,42 +894,43 @@ * execution or skip to its next iteration. If the * closest is a catch exception range, jump to its * catchOffset. If no enclosing range is found, stop * execution and return the TCL_BREAK or TCL_CONTINUE. */ - rangePtr = TclGetExceptionRangeForPc(pc, - /*catchOnly*/ 0, codePtr); + rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 0, + codePtr); if (rangePtr == NULL) { - TRACE(("%s %u => ... after \"%.20s\", no encl. loop or catch, returning %s\n", - opName[opCode], objc, cmdNameBuf, + TRACE(("%u => ... after \"%.20s\", no encl. loop or catch, returning %s\n", + objc, cmdNameBuf, StringForResultCode(result))); goto abnormalReturn; /* no catch exists to check */ } + newPcOffset = 0; switch (rangePtr->type) { case LOOP_EXCEPTION_RANGE: if (result == TCL_BREAK) { newPcOffset = rangePtr->breakOffset; } else if (rangePtr->continueOffset == -1) { - TRACE(("%s %u => ... after \"%.20s\", %s, loop w/o continue, checking for catch\n", - opName[opCode], objc, cmdNameBuf, + TRACE(("%u => ... after \"%.20s\", %s, loop w/o continue, checking for catch\n", + objc, cmdNameBuf, StringForResultCode(result))); goto checkForCatch; } else { newPcOffset = rangePtr->continueOffset; } - TRACE(("%s %u => ... after \"%.20s\", %s, range at %d, new pc %d\n", - opName[opCode], objc, cmdNameBuf, + TRACE(("%u => ... after \"%.20s\", %s, range at %d, new pc %d\n", + objc, cmdNameBuf, StringForResultCode(result), rangePtr->codeOffset, newPcOffset)); break; case CATCH_EXCEPTION_RANGE: - TRACE(("%s %u => ... after \"%.20s\", %s...\n", - opName[opCode], objc, cmdNameBuf, + TRACE(("%u => ... after \"%.20s\", %s...\n", + objc, cmdNameBuf, StringForResultCode(result))); goto processCatch; /* it will use rangePtr */ default: - panic("TclExecuteByteCode: unrecognized ExceptionRange type %d\n", rangePtr->type); + panic("TclExecuteByteCode: bad ExceptionRange type\n"); } result = TCL_OK; pc = (codePtr->codeStart + newPcOffset); continue; /* restart outer instruction loop at pc */ @@ -1049,45 +937,43 @@ case TCL_ERROR: /* * The invoked command returned an error. Look for an * enclosing catch exception range, if any. */ - TRACE_WITH_OBJ(("%s %u => ... after \"%.20s\", TCL_ERROR ", - opName[opCode], objc, cmdNameBuf), - Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("%u => ... after \"%.20s\", TCL_ERROR ", + objc, cmdNameBuf), Tcl_GetObjResult(interp)); goto checkForCatch; case TCL_RETURN: /* * The invoked command requested that the current * procedure stop execution and return. First check * for an enclosing catch exception range, if any. */ - TRACE(("%s %u => ... after \"%.20s\", TCL_RETURN\n", - opName[opCode], objc, cmdNameBuf)); + TRACE(("%u => ... after \"%.20s\", TCL_RETURN\n", + objc, cmdNameBuf)); goto checkForCatch; default: - TRACE_WITH_OBJ(("%s %u => ... after \"%.20s\", OTHER RETURN CODE %d ", - opName[opCode], objc, cmdNameBuf, result), + TRACE_WITH_OBJ(("%u => ... after \"%.20s\", OTHER RETURN CODE %d ", + objc, cmdNameBuf, result), Tcl_GetObjResult(interp)); goto checkForCatch; - } /* end of switch on result from invoke instruction */ + } } case INST_EVAL_STK: objPtr = POP_OBJECT(); DECACHE_STACK_INFO(); - result = Tcl_EvalObj(interp, objPtr); + result = Tcl_EvalObjEx(interp, objPtr, 0); CACHE_STACK_INFO(); if (result == TCL_OK) { /* * Normal return; push the eval's object result. */ - PUSH_OBJECT(Tcl_GetObjResult(interp)); - TRACE_WITH_OBJ(("evalStk \"%.30s\" => ", O2S(objPtr)), + TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), Tcl_GetObjResult(interp)); TclDecrRefCount(objPtr); ADJUST_PC(1); } else if ((result == TCL_BREAK) || (result == TCL_CONTINUE)) { /* @@ -1101,37 +987,37 @@ int newPcOffset = 0; /* Pc offset computed during break, * continue, error processing. Init. * to avoid compiler warning. */ - rangePtr = TclGetExceptionRangeForPc(pc, /*catchOnly*/ 0, + rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 0, codePtr); if (rangePtr == NULL) { - TRACE(("evalStk \"%.30s\" => no encl. loop or catch, returning %s\n", + TRACE(("\"%.30s\" => no encl. loop or catch, returning %s\n", O2S(objPtr), StringForResultCode(result))); Tcl_DecrRefCount(objPtr); goto abnormalReturn; /* no catch exists to check */ } switch (rangePtr->type) { case LOOP_EXCEPTION_RANGE: if (result == TCL_BREAK) { newPcOffset = rangePtr->breakOffset; } else if (rangePtr->continueOffset == -1) { - TRACE(("evalStk \"%.30s\" => %s, loop w/o continue, checking for catch\n", + TRACE(("\"%.30s\" => %s, loop w/o continue, checking for catch\n", O2S(objPtr), StringForResultCode(result))); Tcl_DecrRefCount(objPtr); goto checkForCatch; } else { newPcOffset = rangePtr->continueOffset; } result = TCL_OK; - TRACE_WITH_OBJ(("evalStk \"%.30s\" => %s, range at %d, new pc %d ", + TRACE_WITH_OBJ(("\"%.30s\" => %s, range at %d, new pc %d ", O2S(objPtr), StringForResultCode(result), rangePtr->codeOffset, newPcOffset), valuePtr); break; case CATCH_EXCEPTION_RANGE: - TRACE_WITH_OBJ(("evalStk \"%.30s\" => %s ", + TRACE_WITH_OBJ(("\"%.30s\" => %s ", O2S(objPtr), StringForResultCode(result)), valuePtr); Tcl_DecrRefCount(objPtr); goto processCatch; /* it will use rangePtr */ default: @@ -1139,11 +1025,11 @@ } Tcl_DecrRefCount(objPtr); pc = (codePtr->codeStart + newPcOffset); continue; /* restart outer instruction loop at pc */ } else { /* eval returned TCL_ERROR, TCL_RETURN, unknown code */ - TRACE_WITH_OBJ(("evalStk \"%.30s\" => ERROR: ", O2S(objPtr)), + TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(objPtr)), Tcl_GetObjResult(interp)); Tcl_DecrRefCount(objPtr); goto checkForCatch; } @@ -1152,61 +1038,79 @@ Tcl_ResetResult(interp); DECACHE_STACK_INFO(); result = Tcl_ExprObj(interp, objPtr, &valuePtr); CACHE_STACK_INFO(); if (result != TCL_OK) { - TRACE_WITH_OBJ(("exprStk \"%.30s\" => ERROR: ", + TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(objPtr)), Tcl_GetObjResult(interp)); Tcl_DecrRefCount(objPtr); goto checkForCatch; } - stackPtr[++stackTop].o = valuePtr; /* already has right refct */ - TRACE_WITH_OBJ(("exprStk \"%.30s\" => ", O2S(objPtr)), valuePtr); + stackPtr[++stackTop] = valuePtr; /* already has right refct */ + TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr); TclDecrRefCount(objPtr); ADJUST_PC(1); - case INST_LOAD_SCALAR4: - opnd = TclGetInt4AtPtr(pc+1); - pcAdjustment = 5; - goto doLoadScalar; - case INST_LOAD_SCALAR1: - opnd = TclGetUInt1AtPtr(pc+1); - pcAdjustment = 2; - - doLoadScalar: +#ifdef TCL_COMPILE_DEBUG + opnd = TclGetInt1AtPtr(pc+1); + DECACHE_STACK_INFO(); + valuePtr = TclGetIndexedScalar(interp, opnd, + /*leaveErrorMsg*/ 1); + CACHE_STACK_INFO(); + if (valuePtr == NULL) { + TRACE_WITH_OBJ(("%u => ERROR: ", opnd), + Tcl_GetObjResult(interp)); + result = TCL_ERROR; + goto checkForCatch; + } + PUSH_OBJECT(valuePtr); + TRACE_WITH_OBJ(("%u => ", opnd), valuePtr); +#else /* TCL_COMPILE_DEBUG */ + DECACHE_STACK_INFO(); + valuePtr = TclGetIndexedScalar(interp, TclGetInt1AtPtr(pc+1), + /*leaveErrorMsg*/ 1); + CACHE_STACK_INFO(); + if (valuePtr == NULL) { + result = TCL_ERROR; + goto checkForCatch; + } + PUSH_OBJECT(valuePtr); +#endif /* TCL_COMPILE_DEBUG */ + ADJUST_PC(2); + + case INST_LOAD_SCALAR4: + opnd = TclGetUInt4AtPtr(pc+1); DECACHE_STACK_INFO(); valuePtr = TclGetIndexedScalar(interp, opnd, /*leaveErrorMsg*/ 1); CACHE_STACK_INFO(); if (valuePtr == NULL) { - TRACE_WITH_OBJ(("%s %u => ERROR: ", opName[opCode], opnd), - Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("%u => ERROR: ", opnd), + Tcl_GetObjResult(interp)); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(valuePtr); - TRACE_WITH_OBJ(("%s %u => ", opName[opCode], opnd), valuePtr); - ADJUST_PC(pcAdjustment); + TRACE_WITH_OBJ(("%u => ", opnd), valuePtr); + ADJUST_PC(5); case INST_LOAD_SCALAR_STK: - namePtr = POP_OBJECT(); + objPtr = POP_OBJECT(); /* scalar name */ DECACHE_STACK_INFO(); - valuePtr = Tcl_ObjGetVar2(interp, namePtr, (Tcl_Obj *) NULL, - TCL_LEAVE_ERR_MSG); + valuePtr = Tcl_ObjGetVar2(interp, objPtr, NULL, TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (valuePtr == NULL) { - TRACE_WITH_OBJ(("loadScalarStk \"%.30s\" => ERROR: ", - O2S(namePtr)), Tcl_GetObjResult(interp)); - Tcl_DecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(objPtr)), + Tcl_GetObjResult(interp)); + Tcl_DecrRefCount(objPtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(valuePtr); - TRACE_WITH_OBJ(("loadScalarStk \"%.30s\" => ", - O2S(namePtr)), valuePtr); - TclDecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr); + TclDecrRefCount(objPtr); ADJUST_PC(1); case INST_LOAD_ARRAY4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; @@ -1223,67 +1127,64 @@ DECACHE_STACK_INFO(); valuePtr = TclGetElementOfIndexedArray(interp, opnd, elemPtr, /*leaveErrorMsg*/ 1); CACHE_STACK_INFO(); if (valuePtr == NULL) { - TRACE_WITH_OBJ(("%s %u \"%.30s\" => ERROR: ", - opName[opCode], opnd, O2S(elemPtr)), - Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("%u \"%.30s\" => ERROR: ", + opnd, O2S(elemPtr)), Tcl_GetObjResult(interp)); Tcl_DecrRefCount(elemPtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(valuePtr); - TRACE_WITH_OBJ(("%s %u \"%.30s\" => ", - opName[opCode], opnd, O2S(elemPtr)), valuePtr); + TRACE_WITH_OBJ(("%u \"%.30s\" => ", + opnd, O2S(elemPtr)),valuePtr); TclDecrRefCount(elemPtr); } ADJUST_PC(pcAdjustment); case INST_LOAD_ARRAY_STK: { Tcl_Obj *elemPtr = POP_OBJECT(); - namePtr = POP_OBJECT(); + objPtr = POP_OBJECT(); /* array name */ DECACHE_STACK_INFO(); - valuePtr = Tcl_ObjGetVar2(interp, namePtr, elemPtr, + valuePtr = Tcl_ObjGetVar2(interp, objPtr, elemPtr, TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (valuePtr == NULL) { - TRACE_WITH_OBJ(("loadArrayStk \"%.30s(%.30s)\" => ERROR: ", - O2S(namePtr), O2S(elemPtr)), + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" => ERROR: ", + O2S(objPtr), O2S(elemPtr)), Tcl_GetObjResult(interp)); - Tcl_DecrRefCount(namePtr); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(elemPtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(valuePtr); - TRACE_WITH_OBJ(("loadArrayStk \"%.30s(%.30s)\" => ", - O2S(namePtr), O2S(elemPtr)), valuePtr); - TclDecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" => ", + O2S(objPtr), O2S(elemPtr)), valuePtr); + TclDecrRefCount(objPtr); TclDecrRefCount(elemPtr); } ADJUST_PC(1); case INST_LOAD_STK: - namePtr = POP_OBJECT(); + objPtr = POP_OBJECT(); /* variable name */ DECACHE_STACK_INFO(); - valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, - TCL_PARSE_PART1|TCL_LEAVE_ERR_MSG); + valuePtr = Tcl_ObjGetVar2(interp, objPtr, NULL, TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (valuePtr == NULL) { - TRACE_WITH_OBJ(("loadStk \"%.30s\" => ERROR: ", - O2S(namePtr)), Tcl_GetObjResult(interp)); - Tcl_DecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", + O2S(objPtr)), Tcl_GetObjResult(interp)); + Tcl_DecrRefCount(objPtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(valuePtr); - TRACE_WITH_OBJ(("loadStk \"%.30s\" => ", O2S(namePtr)), - valuePtr); - TclDecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr); + TclDecrRefCount(objPtr); ADJUST_PC(1); case INST_STORE_SCALAR4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; @@ -1295,50 +1196,45 @@ doStoreScalar: valuePtr = POP_OBJECT(); DECACHE_STACK_INFO(); value2Ptr = TclSetIndexedScalar(interp, opnd, valuePtr, - /*leaveErrorMsg*/ 1); + /*leaveErrorMsg*/ 1); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("%s %u <- \"%.30s\" => ERROR: ", - opName[opCode], opnd, O2S(valuePtr)), - Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("%u <- \"%.30s\" => ERROR: ", + opnd, O2S(valuePtr)), Tcl_GetObjResult(interp)); Tcl_DecrRefCount(valuePtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%s %u <- \"%.30s\" => ", - opName[opCode], opnd, O2S(valuePtr)), value2Ptr); + TRACE_WITH_OBJ(("%u <- \"%.30s\" => ", + opnd, O2S(valuePtr)), value2Ptr); TclDecrRefCount(valuePtr); ADJUST_PC(pcAdjustment); case INST_STORE_SCALAR_STK: valuePtr = POP_OBJECT(); - namePtr = POP_OBJECT(); + objPtr = POP_OBJECT(); /* scalar name */ DECACHE_STACK_INFO(); - value2Ptr = Tcl_ObjSetVar2(interp, namePtr, NULL, valuePtr, - TCL_LEAVE_ERR_MSG); + value2Ptr = Tcl_ObjSetVar2(interp, objPtr, NULL, valuePtr, + TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ( - ("storeScalarStk \"%.30s\" <- \"%.30s\" => ERROR: ", - O2S(namePtr), O2S(valuePtr)), + TRACE_WITH_OBJ(("\"%.30s\" <- \"%.30s\" => ERROR: ", + O2S(objPtr), O2S(valuePtr)), Tcl_GetObjResult(interp)); - Tcl_DecrRefCount(namePtr); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(valuePtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ( - ("storeScalarStk \"%.30s\" <- \"%.30s\" => ", - O2S(namePtr), - O2S(valuePtr)), - value2Ptr); - TclDecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s\" <- \"%.30s\" => ", + O2S(objPtr), O2S(valuePtr)), value2Ptr); + TclDecrRefCount(objPtr); TclDecrRefCount(valuePtr); ADJUST_PC(1); case INST_STORE_ARRAY4: opnd = TclGetUInt4AtPtr(pc+1); @@ -1358,23 +1254,21 @@ DECACHE_STACK_INFO(); value2Ptr = TclSetElementOfIndexedArray(interp, opnd, elemPtr, valuePtr, TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ( - ("%s %u \"%.30s\" <- \"%.30s\" => ERROR: ", - opName[opCode], opnd, O2S(elemPtr), - O2S(valuePtr)), Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("%u \"%.30s\" <- \"%.30s\" => ERROR: ", + opnd, O2S(elemPtr), O2S(valuePtr)), + Tcl_GetObjResult(interp)); Tcl_DecrRefCount(elemPtr); Tcl_DecrRefCount(valuePtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%s %u \"%.30s\" <- \"%.30s\" => ", - opName[opCode], opnd, O2S(elemPtr), O2S(valuePtr)), - value2Ptr); + TRACE_WITH_OBJ(("%u \"%.30s\" <- \"%.30s\" => ", + opnd, O2S(elemPtr), O2S(valuePtr)), value2Ptr); TclDecrRefCount(elemPtr); TclDecrRefCount(valuePtr); } ADJUST_PC(pcAdjustment); @@ -1382,65 +1276,65 @@ { Tcl_Obj *elemPtr; valuePtr = POP_OBJECT(); elemPtr = POP_OBJECT(); - namePtr = POP_OBJECT(); + objPtr = POP_OBJECT(); /* array name */ DECACHE_STACK_INFO(); - value2Ptr = Tcl_ObjSetVar2(interp, namePtr, elemPtr, - valuePtr, TCL_LEAVE_ERR_MSG); + value2Ptr = Tcl_ObjSetVar2(interp, objPtr, elemPtr, valuePtr, + TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("storeArrayStk \"%.30s(%.30s)\" <- \"%.30s\" => ERROR: ", - O2S(namePtr), O2S(elemPtr), O2S(valuePtr)), + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" <- \"%.30s\" => ERROR: ", + O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), Tcl_GetObjResult(interp)); - Tcl_DecrRefCount(namePtr); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(elemPtr); Tcl_DecrRefCount(valuePtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("storeArrayStk \"%.30s(%.30s)\" <- \"%.30s\" => ", - O2S(namePtr), O2S(elemPtr), O2S(valuePtr)), + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" <- \"%.30s\" => ", + O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), value2Ptr); - TclDecrRefCount(namePtr); + TclDecrRefCount(objPtr); TclDecrRefCount(elemPtr); TclDecrRefCount(valuePtr); } ADJUST_PC(1); case INST_STORE_STK: valuePtr = POP_OBJECT(); - namePtr = POP_OBJECT(); + objPtr = POP_OBJECT(); /* variable name */ DECACHE_STACK_INFO(); - value2Ptr = Tcl_ObjSetVar2(interp, namePtr, NULL, valuePtr, - TCL_PARSE_PART1|TCL_LEAVE_ERR_MSG); + value2Ptr = Tcl_ObjSetVar2(interp, objPtr, NULL, valuePtr, + TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("storeStk \"%.30s\" <- \"%.30s\" => ERROR: ", - O2S(namePtr), O2S(valuePtr)), + TRACE_WITH_OBJ(("\"%.30s\" <- \"%.30s\" => ERROR: ", + O2S(objPtr), O2S(valuePtr)), Tcl_GetObjResult(interp)); - Tcl_DecrRefCount(namePtr); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(valuePtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("storeStk \"%.30s\" <- \"%.30s\" => ", - O2S(namePtr), O2S(valuePtr)), value2Ptr); - TclDecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s\" <- \"%.30s\" => ", + O2S(objPtr), O2S(valuePtr)), value2Ptr); + TclDecrRefCount(objPtr); TclDecrRefCount(valuePtr); ADJUST_PC(1); case INST_INCR_SCALAR1: opnd = TclGetUInt1AtPtr(pc+1); valuePtr = POP_OBJECT(); if (valuePtr->typePtr != &tclIntType) { result = tclIntType.setFromAnyProc(interp, valuePtr); if (result != TCL_OK) { - TRACE_WITH_OBJ(("incrScalar1 %u (by %s) => ERROR converting increment amount to int: ", + TRACE_WITH_OBJ(("%u (by %s) => ERROR converting increment amount to int: ", opnd, O2S(valuePtr)), Tcl_GetObjResult(interp)); Tcl_DecrRefCount(valuePtr); goto checkForCatch; } } @@ -1447,55 +1341,53 @@ i = valuePtr->internalRep.longValue; DECACHE_STACK_INFO(); value2Ptr = TclIncrIndexedScalar(interp, opnd, i); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("incrScalar1 %u (by %ld) => ERROR: ", - opnd, i), Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("%u (by %ld) => ERROR: ", opnd, i), + Tcl_GetObjResult(interp)); Tcl_DecrRefCount(valuePtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("incrScalar1 %u (by %ld) => ", opnd, i), - value2Ptr); + TRACE_WITH_OBJ(("%u (by %ld) => ", opnd, i), value2Ptr); TclDecrRefCount(valuePtr); ADJUST_PC(2); case INST_INCR_SCALAR_STK: case INST_INCR_STK: valuePtr = POP_OBJECT(); - namePtr = POP_OBJECT(); + objPtr = POP_OBJECT(); /* scalar name */ if (valuePtr->typePtr != &tclIntType) { result = tclIntType.setFromAnyProc(interp, valuePtr); if (result != TCL_OK) { - TRACE_WITH_OBJ(("%s \"%.30s\" (by %s) => ERROR converting increment amount to int: ", - opName[opCode], O2S(namePtr), O2S(valuePtr)), + TRACE_WITH_OBJ(("\"%.30s\" (by %s) => ERROR converting increment amount to int: ", + O2S(objPtr), O2S(valuePtr)), Tcl_GetObjResult(interp)); - Tcl_DecrRefCount(namePtr); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(valuePtr); goto checkForCatch; } } i = valuePtr->internalRep.longValue; DECACHE_STACK_INFO(); - value2Ptr = TclIncrVar2(interp, namePtr, (Tcl_Obj *) NULL, i, - /*part1NotParsed*/ (opCode == INST_INCR_STK)); + value2Ptr = TclIncrVar2(interp, objPtr, (Tcl_Obj *) NULL, i, + TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("%s \"%.30s\" (by %ld) => ERROR: ", - opName[opCode], O2S(namePtr), i), - Tcl_GetObjResult(interp)); - Tcl_DecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s\" (by %ld) => ERROR: ", + O2S(objPtr), i), Tcl_GetObjResult(interp)); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(valuePtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%s \"%.30s\" (by %ld) => ", - opName[opCode], O2S(namePtr), i), value2Ptr); - Tcl_DecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s\" (by %ld) => ", O2S(objPtr), i), + value2Ptr); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(valuePtr); ADJUST_PC(1); case INST_INCR_ARRAY1: { @@ -1505,11 +1397,11 @@ valuePtr = POP_OBJECT(); elemPtr = POP_OBJECT(); if (valuePtr->typePtr != &tclIntType) { result = tclIntType.setFromAnyProc(interp, valuePtr); if (result != TCL_OK) { - TRACE_WITH_OBJ(("incrArray1 %u \"%.30s\" (by %s) => ERROR converting increment amount to int: ", + TRACE_WITH_OBJ(("%u \"%.30s\" (by %s) => ERROR converting increment amount to int: ", opnd, O2S(elemPtr), O2S(valuePtr)), Tcl_GetObjResult(interp)); Tcl_DecrRefCount(elemPtr); Tcl_DecrRefCount(valuePtr); goto checkForCatch; @@ -1519,20 +1411,20 @@ DECACHE_STACK_INFO(); value2Ptr = TclIncrElementOfIndexedArray(interp, opnd, elemPtr, i); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("incrArray1 %u \"%.30s\" (by %ld) => ERROR: ", + TRACE_WITH_OBJ(("%u \"%.30s\" (by %ld) => ERROR: ", opnd, O2S(elemPtr), i), Tcl_GetObjResult(interp)); Tcl_DecrRefCount(elemPtr); Tcl_DecrRefCount(valuePtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("incrArray1 %u \"%.30s\" (by %ld) => ", + TRACE_WITH_OBJ(("%u \"%.30s\" (by %ld) => ", opnd, O2S(elemPtr), i), value2Ptr); Tcl_DecrRefCount(elemPtr); Tcl_DecrRefCount(valuePtr); } ADJUST_PC(2); @@ -1541,42 +1433,42 @@ { Tcl_Obj *elemPtr; valuePtr = POP_OBJECT(); elemPtr = POP_OBJECT(); - namePtr = POP_OBJECT(); + objPtr = POP_OBJECT(); /* array name */ if (valuePtr->typePtr != &tclIntType) { result = tclIntType.setFromAnyProc(interp, valuePtr); if (result != TCL_OK) { - TRACE_WITH_OBJ(("incrArrayStk \"%.30s(%.30s)\" (by %s) => ERROR converting increment amount to int: ", - O2S(namePtr), O2S(elemPtr), O2S(valuePtr)), + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %s) => ERROR converting increment amount to int: ", + O2S(objPtr), O2S(elemPtr), O2S(valuePtr)), Tcl_GetObjResult(interp)); - Tcl_DecrRefCount(namePtr); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(elemPtr); Tcl_DecrRefCount(valuePtr); goto checkForCatch; } } i = valuePtr->internalRep.longValue; DECACHE_STACK_INFO(); - value2Ptr = TclIncrVar2(interp, namePtr, elemPtr, i, - /*part1NotParsed*/ 0); + value2Ptr = TclIncrVar2(interp, objPtr, elemPtr, i, + TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("incrArrayStk \"%.30s(%.30s)\" (by %ld) => ERROR: ", - O2S(namePtr), O2S(elemPtr), i), + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %ld) => ERROR: ", + O2S(objPtr), O2S(elemPtr), i), Tcl_GetObjResult(interp)); - Tcl_DecrRefCount(namePtr); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(elemPtr); Tcl_DecrRefCount(valuePtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("incrArrayStk \"%.30s(%.30s)\" (by %ld) => ", - O2S(namePtr), O2S(elemPtr), i), value2Ptr); - Tcl_DecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %ld) => ", + O2S(objPtr), O2S(elemPtr), i), value2Ptr); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(elemPtr); Tcl_DecrRefCount(valuePtr); } ADJUST_PC(1); @@ -1585,40 +1477,38 @@ i = TclGetInt1AtPtr(pc+2); DECACHE_STACK_INFO(); value2Ptr = TclIncrIndexedScalar(interp, opnd, i); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("incrScalar1Imm %u %ld => ERROR: ", - opnd, i), Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("%u %ld => ERROR: ", opnd, i), + Tcl_GetObjResult(interp)); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("incrScalar1Imm %u %ld => ", opnd, i), - value2Ptr); + TRACE_WITH_OBJ(("%u %ld => ", opnd, i), value2Ptr); ADJUST_PC(3); case INST_INCR_SCALAR_STK_IMM: case INST_INCR_STK_IMM: - namePtr = POP_OBJECT(); + objPtr = POP_OBJECT(); /* variable name */ i = TclGetInt1AtPtr(pc+1); DECACHE_STACK_INFO(); - value2Ptr = TclIncrVar2(interp, namePtr, (Tcl_Obj *) NULL, i, - /*part1NotParsed*/ (opCode == INST_INCR_STK_IMM)); + value2Ptr = TclIncrVar2(interp, objPtr, (Tcl_Obj *) NULL, i, + TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("%s \"%.30s\" %ld => ERROR: ", - opName[opCode], O2S(namePtr), i), - Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("\"%.30s\" %ld => ERROR: ", + O2S(objPtr), i), Tcl_GetObjResult(interp)); result = TCL_ERROR; - Tcl_DecrRefCount(namePtr); + Tcl_DecrRefCount(objPtr); goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("%s \"%.30s\" %ld => ", - opName[opCode], O2S(namePtr), i), value2Ptr); - TclDecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s\" %ld => ", O2S(objPtr), i), + value2Ptr); + TclDecrRefCount(objPtr); ADJUST_PC(2); case INST_INCR_ARRAY1_IMM: { Tcl_Obj *elemPtr; @@ -1629,19 +1519,19 @@ DECACHE_STACK_INFO(); value2Ptr = TclIncrElementOfIndexedArray(interp, opnd, elemPtr, i); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("incrArray1Imm %u \"%.30s\" (by %ld) => ERROR: ", + TRACE_WITH_OBJ(("%u \"%.30s\" (by %ld) => ERROR: ", opnd, O2S(elemPtr), i), Tcl_GetObjResult(interp)); Tcl_DecrRefCount(elemPtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("incrArray1Imm %u \"%.30s\" (by %ld) => ", + TRACE_WITH_OBJ(("%u \"%.30s\" (by %ld) => ", opnd, O2S(elemPtr), i), value2Ptr); Tcl_DecrRefCount(elemPtr); } ADJUST_PC(3); @@ -1649,41 +1539,46 @@ { Tcl_Obj *elemPtr; i = TclGetInt1AtPtr(pc+1); elemPtr = POP_OBJECT(); - namePtr = POP_OBJECT(); + objPtr = POP_OBJECT(); /* array name */ DECACHE_STACK_INFO(); - value2Ptr = TclIncrVar2(interp, namePtr, elemPtr, i, - /*part1NotParsed*/ 0); + value2Ptr = TclIncrVar2(interp, objPtr, elemPtr, i, + TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("incrArrayStkImm \"%.30s(%.30s)\" (by %ld) => ERROR: ", - O2S(namePtr), O2S(elemPtr), i), + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %ld) => ERROR: ", + O2S(objPtr), O2S(elemPtr), i), Tcl_GetObjResult(interp)); - Tcl_DecrRefCount(namePtr); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(elemPtr); result = TCL_ERROR; goto checkForCatch; } PUSH_OBJECT(value2Ptr); - TRACE_WITH_OBJ(("incrArrayStkImm \"%.30s(%.30s)\" (by %ld) => ", - O2S(namePtr), O2S(elemPtr), i), value2Ptr); - Tcl_DecrRefCount(namePtr); + TRACE_WITH_OBJ(("\"%.30s(%.30s)\" (by %ld) => ", + O2S(objPtr), O2S(elemPtr), i), value2Ptr); + Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(elemPtr); } ADJUST_PC(2); case INST_JUMP1: +#ifdef TCL_COMPILE_DEBUG opnd = TclGetInt1AtPtr(pc+1); - TRACE(("jump1 %d => new pc %u\n", opnd, + TRACE(("%d => new pc %u\n", opnd, (unsigned int)(pc + opnd - codePtr->codeStart))); - ADJUST_PC(opnd); + pc += opnd; +#else + pc += TclGetInt1AtPtr(pc+1); +#endif /* TCL_COMPILE_DEBUG */ + continue; case INST_JUMP4: opnd = TclGetInt4AtPtr(pc+1); - TRACE(("jump4 %d => new pc %u\n", opnd, + TRACE(("%d => new pc %u\n", opnd, (unsigned int)(pc + opnd - codePtr->codeStart))); ADJUST_PC(opnd); case INST_JUMP_TRUE4: opnd = TclGetInt4AtPtr(pc+1); @@ -1704,25 +1599,24 @@ } else if (valuePtr->typePtr == &tclDoubleType) { b = (valuePtr->internalRep.doubleValue != 0.0); } else { result = Tcl_GetBooleanFromObj(interp, valuePtr, &b); if (result != TCL_OK) { - TRACE_WITH_OBJ(("%s %d => ERROR: ", opName[opCode], - opnd), Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("%d => ERROR: ", opnd), + Tcl_GetObjResult(interp)); Tcl_DecrRefCount(valuePtr); goto checkForCatch; } } if (b) { - TRACE(("%s %d => %.20s true, new pc %u\n", - opName[opCode], opnd, O2S(valuePtr), + TRACE(("%d => %.20s true, new pc %u\n", + opnd, O2S(valuePtr), (unsigned int)(pc+opnd - codePtr->codeStart))); TclDecrRefCount(valuePtr); ADJUST_PC(opnd); } else { - TRACE(("%s %d => %.20s false\n", opName[opCode], opnd, - O2S(valuePtr))); + TRACE(("%d => %.20s false\n", opnd, O2S(valuePtr))); TclDecrRefCount(valuePtr); ADJUST_PC(pcAdjustment); } } @@ -1745,24 +1639,23 @@ } else if (valuePtr->typePtr == &tclDoubleType) { b = (valuePtr->internalRep.doubleValue != 0.0); } else { result = Tcl_GetBooleanFromObj(interp, valuePtr, &b); if (result != TCL_OK) { - TRACE_WITH_OBJ(("%s %d => ERROR: ", opName[opCode], - opnd), Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("%d => ERROR: ", opnd), + Tcl_GetObjResult(interp)); Tcl_DecrRefCount(valuePtr); goto checkForCatch; } } if (b) { - TRACE(("%s %d => %.20s true\n", opName[opCode], opnd, - O2S(valuePtr))); + TRACE(("%d => %.20s true\n", opnd, O2S(valuePtr))); TclDecrRefCount(valuePtr); ADJUST_PC(pcAdjustment); } else { - TRACE(("%s %d => %.20s false, new pc %u\n", - opName[opCode], opnd, O2S(valuePtr), + TRACE(("%d => %.20s false, new pc %u\n", + opnd, O2S(valuePtr), (unsigned int)(pc + opnd - codePtr->codeStart))); TclDecrRefCount(valuePtr); ADJUST_PC(opnd); } } @@ -1787,26 +1680,26 @@ if ((t1Ptr == &tclIntType) || (t1Ptr == &tclBooleanType)) { i1 = (valuePtr->internalRep.longValue != 0); } else if (t1Ptr == &tclDoubleType) { i1 = (valuePtr->internalRep.doubleValue != 0.0); - } else { /* FAILS IF NULL STRING REP */ - s = Tcl_GetStringFromObj(valuePtr, (int *) NULL); - if (TclLooksLikeInt(s)) { + } else { + s = Tcl_GetStringFromObj(valuePtr, &length); + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); i1 = (i != 0); } else { result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL, valuePtr, &i1); i1 = (i1 != 0); } if (result != TCL_OK) { - TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s \n", - opName[opCode], O2S(valuePtr), + TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", + O2S(valuePtr), (t1Ptr? t1Ptr->name : "null"))); - IllegalExprOperandType(interp, opCode, valuePtr); + IllegalExprOperandType(interp, pc, valuePtr); Tcl_DecrRefCount(valuePtr); Tcl_DecrRefCount(value2Ptr); goto checkForCatch; } } @@ -1813,26 +1706,25 @@ if ((t2Ptr == &tclIntType) || (t2Ptr == &tclBooleanType)) { i2 = (value2Ptr->internalRep.longValue != 0); } else if (t2Ptr == &tclDoubleType) { i2 = (value2Ptr->internalRep.doubleValue != 0.0); - } else { /* FAILS IF NULL STRING REP */ - s = Tcl_GetStringFromObj(value2Ptr, (int *) NULL); - if (TclLooksLikeInt(s)) { + } else { + s = Tcl_GetStringFromObj(value2Ptr, &length); + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, value2Ptr, &i); i2 = (i != 0); } else { result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL, value2Ptr, &i2); - i2 = (i2 != 0); } if (result != TCL_OK) { - TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s \n", - opName[opCode], O2S(value2Ptr), + TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", + O2S(value2Ptr), (t2Ptr? t2Ptr->name : "null"))); - IllegalExprOperandType(interp, opCode, value2Ptr); + IllegalExprOperandType(interp, pc, value2Ptr); Tcl_DecrRefCount(valuePtr); Tcl_DecrRefCount(value2Ptr); goto checkForCatch; } } @@ -1839,23 +1731,22 @@ /* * Reuse the valuePtr object already on stack if possible. */ - if (opCode == INST_LOR) { + if (*pc == INST_LOR) { iResult = (i1 || i2); } else { iResult = (i1 && i2); } if (Tcl_IsShared(valuePtr)) { PUSH_OBJECT(Tcl_NewLongObj(iResult)); - TRACE(("%s %.20s %.20s => %d\n", opName[opCode], + TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult)); TclDecrRefCount(valuePtr); } else { /* reuse the valuePtr object */ - TRACE(("%s %.20s %.20s => %d\n", - opName[opCode], /* NB: stack top is off by 1 */ + TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult)); Tcl_SetLongObj(valuePtr, iResult); ++stackTop; /* valuePtr now on stk top has right r.c. */ } TclDecrRefCount(value2Ptr); @@ -1887,11 +1778,11 @@ t1Ptr = valuePtr->typePtr; t2Ptr = value2Ptr->typePtr; if ((t1Ptr != &tclIntType) && (t1Ptr != &tclDoubleType)) { s1 = Tcl_GetStringFromObj(valuePtr, &length); - if (TclLooksLikeInt(s1)) { /* FAILS IF NULLS */ + if (TclLooksLikeInt(s1, length)) { (void) Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); } else { (void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d1); @@ -1898,11 +1789,11 @@ } t1Ptr = valuePtr->typePtr; } if ((t2Ptr != &tclIntType) && (t2Ptr != &tclDoubleType)) { s2 = Tcl_GetStringFromObj(value2Ptr, &length); - if (TclLooksLikeInt(s2)) { /* FAILS IF NULLS */ + if (TclLooksLikeInt(s2, length)) { (void) Tcl_GetLongFromObj((Tcl_Interp *) NULL, value2Ptr, &i2); } else { (void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, value2Ptr, &d2); @@ -1912,17 +1803,16 @@ if (((t1Ptr != &tclIntType) && (t1Ptr != &tclDoubleType)) || ((t2Ptr != &tclIntType) && (t2Ptr != &tclDoubleType))) { /* * One operand is not numeric. Compare as strings. - * THIS FAILS IF AN OBJECT'S STRING REP CONTAINS NULLS. */ int cmpValue; - s1 = TclGetStringFromObj(valuePtr, &length); - s2 = TclGetStringFromObj(value2Ptr, &length); + s1 = Tcl_GetString(valuePtr); + s2 = Tcl_GetString(value2Ptr); cmpValue = strcmp(s1, s2); - switch (opCode) { + switch (*pc) { case INST_EQ: iResult = (cmpValue == 0); break; case INST_NEQ: iResult = (cmpValue != 0); @@ -1954,11 +1844,11 @@ } } else { /* t1Ptr is int, t2Ptr is double */ d1 = valuePtr->internalRep.longValue; d2 = value2Ptr->internalRep.doubleValue; } - switch (opCode) { + switch (*pc) { case INST_EQ: iResult = d1 == d2; break; case INST_NEQ: iResult = d1 != d2; @@ -1980,11 +1870,11 @@ /* * Compare as ints. */ i = valuePtr->internalRep.longValue; i2 = value2Ptr->internalRep.longValue; - switch (opCode) { + switch (*pc) { case INST_EQ: iResult = i == i2; break; case INST_NEQ: iResult = i != i2; @@ -2008,17 +1898,16 @@ * Reuse the valuePtr object already on stack if possible. */ if (Tcl_IsShared(valuePtr)) { PUSH_OBJECT(Tcl_NewLongObj(iResult)); - TRACE(("%s %.20s %.20s => %ld\n", opName[opCode], - O2S(valuePtr), O2S(value2Ptr), iResult)); + TRACE(("%.20s %.20s => %ld\n", + O2S(valuePtr), O2S(value2Ptr), iResult)); TclDecrRefCount(valuePtr); } else { /* reuse the valuePtr object */ - TRACE(("%s %.20s %.20s => %ld\n", - opName[opCode], /* NB: stack top is off by 1 */ - O2S(valuePtr), O2S(value2Ptr), iResult)); + TRACE(("%.20s %.20s => %ld\n", + O2S(valuePtr), O2S(value2Ptr), iResult)); Tcl_SetLongObj(valuePtr, iResult); ++stackTop; /* valuePtr now on stk top has right r.c. */ } TclDecrRefCount(value2Ptr); } @@ -2044,15 +1933,15 @@ i = valuePtr->internalRep.longValue; } else { /* try to convert to int */ result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); if (result != TCL_OK) { - TRACE(("%s %.20s %.20s => ILLEGAL 1st TYPE %s\n", - opName[opCode], O2S(valuePtr), O2S(value2Ptr), + TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", + O2S(valuePtr), O2S(value2Ptr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); - IllegalExprOperandType(interp, opCode, valuePtr); + IllegalExprOperandType(interp, pc, valuePtr); Tcl_DecrRefCount(valuePtr); Tcl_DecrRefCount(value2Ptr); goto checkForCatch; } } @@ -2060,31 +1949,31 @@ i2 = value2Ptr->internalRep.longValue; } else { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, value2Ptr, &i2); if (result != TCL_OK) { - TRACE(("%s %.20s %.20s => ILLEGAL 2nd TYPE %s\n", - opName[opCode], O2S(valuePtr), O2S(value2Ptr), + TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n", + O2S(valuePtr), O2S(value2Ptr), (value2Ptr->typePtr? value2Ptr->typePtr->name : "null"))); - IllegalExprOperandType(interp, opCode, value2Ptr); + IllegalExprOperandType(interp, pc, value2Ptr); Tcl_DecrRefCount(valuePtr); Tcl_DecrRefCount(value2Ptr); goto checkForCatch; } } - switch (opCode) { + switch (*pc) { case INST_MOD: /* * This code is tricky: C doesn't guarantee much about * the quotient or remainder, but Tcl does. The * remainder always has the same sign as the divisor and * a smaller absolute value. */ if (i2 == 0) { - TRACE(("mod %ld %ld => DIVIDE BY ZERO\n", i, i2)); + TRACE(("%ld %ld => DIVIDE BY ZERO\n", i, i2)); Tcl_DecrRefCount(valuePtr); Tcl_DecrRefCount(value2Ptr); goto divideByZero; } negative = 0; @@ -2132,16 +2021,14 @@ * Reuse the valuePtr object already on stack if possible. */ if (Tcl_IsShared(valuePtr)) { PUSH_OBJECT(Tcl_NewLongObj(iResult)); - TRACE(("%s %ld %ld => %ld\n", opName[opCode], i, i2, - iResult)); + TRACE(("%ld %ld => %ld\n", i, i2, iResult)); TclDecrRefCount(valuePtr); } else { /* reuse the valuePtr object */ - TRACE(("%s %ld %ld => %ld\n", opName[opCode], i, i2, - iResult)); /* NB: stack top is off by 1 */ + TRACE(("%ld %ld => %ld\n", i, i2, iResult)); Tcl_SetLongObj(valuePtr, iResult); ++stackTop; /* valuePtr now on stk top has right r.c. */ } TclDecrRefCount(value2Ptr); } @@ -2169,53 +2056,67 @@ t1Ptr = valuePtr->typePtr; t2Ptr = value2Ptr->typePtr; if (t1Ptr == &tclIntType) { i = valuePtr->internalRep.longValue; - } else if (t1Ptr == &tclDoubleType) { + } else if ((t1Ptr == &tclDoubleType) + && (valuePtr->bytes == NULL)) { + /* + * We can only use the internal rep directly if there is + * no string rep. Otherwise the string rep might actually + * look like an integer, which is preferred. + */ + d1 = valuePtr->internalRep.doubleValue; - } else { /* try to convert; FAILS IF NULLS */ + } else { char *s = Tcl_GetStringFromObj(valuePtr, &length); - if (TclLooksLikeInt(s)) { + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d1); } if (result != TCL_OK) { - TRACE(("%s %.20s %.20s => ILLEGAL 1st TYPE %s\n", - opName[opCode], s, O2S(value2Ptr), + TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", + s, O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); - IllegalExprOperandType(interp, opCode, valuePtr); + IllegalExprOperandType(interp, pc, valuePtr); Tcl_DecrRefCount(valuePtr); Tcl_DecrRefCount(value2Ptr); goto checkForCatch; } t1Ptr = valuePtr->typePtr; } if (t2Ptr == &tclIntType) { i2 = value2Ptr->internalRep.longValue; - } else if (t2Ptr == &tclDoubleType) { + } else if ((t2Ptr == &tclDoubleType) + && (value2Ptr->bytes == NULL)) { + /* + * We can only use the internal rep directly if there is + * no string rep. Otherwise the string rep might actually + * look like an integer, which is preferred. + */ + d2 = value2Ptr->internalRep.doubleValue; - } else { /* try to convert; FAILS IF NULLS */ + } else { char *s = Tcl_GetStringFromObj(value2Ptr, &length); - if (TclLooksLikeInt(s)) { + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, value2Ptr, &i2); } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, value2Ptr, &d2); } if (result != TCL_OK) { - TRACE(("%s %.20s %.20s => ILLEGAL 2nd TYPE %s\n", - opName[opCode], O2S(valuePtr), s, + TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n", + O2S(value2Ptr), s, (value2Ptr->typePtr? value2Ptr->typePtr->name : "null"))); - IllegalExprOperandType(interp, opCode, value2Ptr); + IllegalExprOperandType(interp, pc, value2Ptr); Tcl_DecrRefCount(valuePtr); Tcl_DecrRefCount(value2Ptr); goto checkForCatch; } t2Ptr = value2Ptr->typePtr; @@ -2229,11 +2130,11 @@ if (t1Ptr == &tclIntType) { d1 = i; /* promote value 1 to double */ } else if (t2Ptr == &tclIntType) { d2 = i2; /* promote value 2 to double */ } - switch (opCode) { + switch (*pc) { case INST_ADD: dResult = d1 + d2; break; case INST_SUB: dResult = d1 - d2; @@ -2241,12 +2142,11 @@ case INST_MULT: dResult = d1 * d2; break; case INST_DIV: if (d2 == 0.0) { - TRACE(("div %.6g %.6g => DIVIDE BY ZERO\n", - d1, d2)); + TRACE(("%.6g %.6g => DIVIDE BY ZERO\n", d1, d2)); Tcl_DecrRefCount(valuePtr); Tcl_DecrRefCount(value2Ptr); goto divideByZero; } dResult = d1 / d2; @@ -2256,12 +2156,12 @@ /* * Check now for IEEE floating-point error. */ if (IS_NAN(dResult) || IS_INF(dResult)) { - TRACE(("%s %.20s %.20s => IEEE FLOATING PT ERROR\n", - opName[opCode], O2S(valuePtr), O2S(value2Ptr))); + TRACE(("%.20s %.20s => IEEE FLOATING PT ERROR\n", + O2S(valuePtr), O2S(value2Ptr))); TclExprFloatError(interp, dResult); result = TCL_ERROR; Tcl_DecrRefCount(valuePtr); Tcl_DecrRefCount(value2Ptr); goto checkForCatch; @@ -2268,11 +2168,11 @@ } } else { /* * Do integer arithmetic. */ - switch (opCode) { + switch (*pc) { case INST_ADD: iResult = i + i2; break; case INST_SUB: iResult = i - i2; @@ -2286,12 +2186,11 @@ * about the quotient or remainder, but Tcl does. * The remainder always has the same sign as the * divisor and a smaller absolute value. */ if (i2 == 0) { - TRACE(("div %ld %ld => DIVIDE BY ZERO\n", - i, i2)); + TRACE(("%ld %ld => DIVIDE BY ZERO\n", i, i2)); Tcl_DecrRefCount(valuePtr); Tcl_DecrRefCount(value2Ptr); goto divideByZero; } if (i2 < 0) { @@ -2313,26 +2212,22 @@ */ if (Tcl_IsShared(valuePtr)) { if (doDouble) { PUSH_OBJECT(Tcl_NewDoubleObj(dResult)); - TRACE(("%s %.6g %.6g => %.6g\n", opName[opCode], - d1, d2, dResult)); + TRACE(("%.6g %.6g => %.6g\n", d1, d2, dResult)); } else { PUSH_OBJECT(Tcl_NewLongObj(iResult)); - TRACE(("%s %ld %ld => %ld\n", opName[opCode], - i, i2, iResult)); + TRACE(("%ld %ld => %ld\n", i, i2, iResult)); } TclDecrRefCount(valuePtr); } else { /* reuse the valuePtr object */ if (doDouble) { /* NB: stack top is off by 1 */ - TRACE(("%s %.6g %.6g => %.6g\n", opName[opCode], - d1, d2, dResult)); + TRACE(("%.6g %.6g => %.6g\n", d1, d2, dResult)); Tcl_SetDoubleObj(valuePtr, dResult); } else { - TRACE(("%s %ld %ld => %ld\n", opName[opCode], - i, i2, iResult)); + TRACE(("%ld %ld => %ld\n", i, i2, iResult)); Tcl_SetLongObj(valuePtr, iResult); } ++stackTop; /* valuePtr now on stk top has right r.c. */ } TclDecrRefCount(value2Ptr); @@ -2346,30 +2241,56 @@ */ double d; Tcl_ObjType *tPtr; - valuePtr = stackPtr[stackTop].o; + valuePtr = stackPtr[stackTop]; tPtr = valuePtr->typePtr; - if ((tPtr != &tclIntType) && (tPtr != &tclDoubleType)) { - char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL); - if (TclLooksLikeInt(s)) { /* FAILS IF NULLS */ + if ((tPtr != &tclIntType) && ((tPtr != &tclDoubleType) + || (valuePtr->bytes != NULL))) { + char *s = Tcl_GetStringFromObj(valuePtr, &length); + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d); } if (result != TCL_OK) { - TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s \n", - opName[opCode], s, - (tPtr? tPtr->name : "null"))); - IllegalExprOperandType(interp, opCode, valuePtr); + TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", + s, (tPtr? tPtr->name : "null"))); + IllegalExprOperandType(interp, pc, valuePtr); goto checkForCatch; } + tPtr = valuePtr->typePtr; + } + + /* + * Ensure that the operand's string rep is the same as the + * formatted version of its internal rep. This makes sure + * that "expr +000123" yields "83", not "000123". 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 (Tcl_IsShared(valuePtr)) { + if (tPtr == &tclIntType) { + i = valuePtr->internalRep.longValue; + objPtr = Tcl_NewLongObj(i); + } else { + d = valuePtr->internalRep.doubleValue; + objPtr = Tcl_NewDoubleObj(d); + } + Tcl_IncrRefCount(objPtr); + Tcl_DecrRefCount(valuePtr); + valuePtr = objPtr; + stackPtr[stackTop] = valuePtr; + } else { + Tcl_InvalidateStringRep(valuePtr); } - TRACE_WITH_OBJ(("uplus %s => ", O2S(valuePtr)), valuePtr); + TRACE_WITH_OBJ(("%s => ", O2S(valuePtr)), valuePtr); } ADJUST_PC(1); case INST_UMINUS: case INST_LNOT: @@ -2384,24 +2305,24 @@ double d; Tcl_ObjType *tPtr; valuePtr = POP_OBJECT(); tPtr = valuePtr->typePtr; - if ((tPtr != &tclIntType) && (tPtr != &tclDoubleType)) { - char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL); - if (TclLooksLikeInt(s)) { /* FAILS IF NULLS */ + if ((tPtr != &tclIntType) && ((tPtr != &tclDoubleType) + || (valuePtr->bytes != NULL))) { + char *s = Tcl_GetStringFromObj(valuePtr, &length); + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d); } if (result != TCL_OK) { - TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s\n", - opName[opCode], s, - (tPtr? tPtr->name : "null"))); - IllegalExprOperandType(interp, opCode, valuePtr); + TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n", + s, (tPtr? tPtr->name : "null"))); + IllegalExprOperandType(interp, pc, valuePtr); Tcl_DecrRefCount(valuePtr); goto checkForCatch; } tPtr = valuePtr->typePtr; } @@ -2411,26 +2332,24 @@ * Create a new object. */ if (tPtr == &tclIntType) { i = valuePtr->internalRep.longValue; objPtr = Tcl_NewLongObj( - (opCode == INST_UMINUS)? -i : !i); - TRACE_WITH_OBJ(("%s %ld => ", opName[opCode], i), - objPtr); /* NB: stack top is off by 1 */ + (*pc == INST_UMINUS)? -i : !i); + TRACE_WITH_OBJ(("%ld => ", i), objPtr); } else { d = valuePtr->internalRep.doubleValue; - if (opCode == INST_UMINUS) { + if (*pc == INST_UMINUS) { objPtr = Tcl_NewDoubleObj(-d); } else { /* * Should be able to use "!d", but apparently * some compilers can't handle it. */ objPtr = Tcl_NewLongObj((d==0.0)? 1 : 0); } - TRACE_WITH_OBJ(("%s %.6g => ", opName[opCode], d), - objPtr); /* NB: stack top is off by 1 */ + TRACE_WITH_OBJ(("%.6g => ", d), objPtr); } PUSH_OBJECT(objPtr); TclDecrRefCount(valuePtr); } else { /* @@ -2437,26 +2356,24 @@ * valuePtr is unshared. Modify it directly. */ if (tPtr == &tclIntType) { i = valuePtr->internalRep.longValue; Tcl_SetLongObj(valuePtr, - (opCode == INST_UMINUS)? -i : !i); - TRACE_WITH_OBJ(("%s %ld => ", opName[opCode], i), - valuePtr); /* NB: stack top is off by 1 */ + (*pc == INST_UMINUS)? -i : !i); + TRACE_WITH_OBJ(("%ld => ", i), valuePtr); } else { d = valuePtr->internalRep.doubleValue; - if (opCode == INST_UMINUS) { + if (*pc == INST_UMINUS) { Tcl_SetDoubleObj(valuePtr, -d); } else { /* * Should be able to use "!d", but apparently * some compilers can't handle it. */ Tcl_SetLongObj(valuePtr, (d==0.0)? 1 : 0); } - TRACE_WITH_OBJ(("%s %.6g => ", opName[opCode], d), - valuePtr); /* NB: stack top is off by 1 */ + TRACE_WITH_OBJ(("%.6g => ", d), valuePtr); } ++stackTop; /* valuePtr now on stk top has right r.c. */ } } ADJUST_PC(1); @@ -2476,30 +2393,30 @@ tPtr = valuePtr->typePtr; if (tPtr != &tclIntType) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); if (result != TCL_OK) { /* try to convert to double */ - TRACE(("bitnot \"%.20s\" => ILLEGAL TYPE %s\n", + TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n", O2S(valuePtr), (tPtr? tPtr->name : "null"))); - IllegalExprOperandType(interp, opCode, valuePtr); + IllegalExprOperandType(interp, pc, valuePtr); Tcl_DecrRefCount(valuePtr); goto checkForCatch; } } i = valuePtr->internalRep.longValue; if (Tcl_IsShared(valuePtr)) { PUSH_OBJECT(Tcl_NewLongObj(~i)); - TRACE(("bitnot 0x%lx => (%lu)\n", i, ~i)); + TRACE(("0x%lx => (%lu)\n", i, ~i)); TclDecrRefCount(valuePtr); } else { /* * valuePtr is unshared. Modify it directly. */ Tcl_SetLongObj(valuePtr, ~i); ++stackTop; /* valuePtr now on stk top has right r.c. */ - TRACE(("bitnot 0x%lx => (%lu)\n", i, ~i)); + TRACE(("0x%lx => (%lu)\n", i, ~i)); } } ADJUST_PC(1); case INST_CALL_BUILTIN_FUNC1: @@ -2508,27 +2425,27 @@ /* * Call one of the built-in Tcl math functions. */ BuiltinFunc *mathFuncPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) { TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd)); panic("TclExecuteByteCode: unrecognized builtin function code %d", opnd); } mathFuncPtr = &(builtinFuncTable[opnd]); DECACHE_STACK_INFO(); - tcl_MathInProgress++; + tsdPtr->mathInProgress++; result = (*mathFuncPtr->proc)(interp, eePtr, mathFuncPtr->clientData); - tcl_MathInProgress--; + tsdPtr->mathInProgress--; CACHE_STACK_INFO(); if (result != TCL_OK) { goto checkForCatch; } - TRACE_WITH_OBJ(("callBuiltinFunc1 %d => ", opnd), - stackPtr[stackTop].o); + TRACE_WITH_OBJ(("%d => ", opnd), stackPtr[stackTop]); } ADJUST_PC(2); case INST_CALL_FUNC1: opnd = TclGetUInt1AtPtr(pc+1); @@ -2540,22 +2457,22 @@ int objc = opnd; /* Number of arguments. The function name * is the 0-th argument. */ Tcl_Obj **objv; /* The array of arguments. The function * name is objv[0]. */ - - objv = &(stackPtr[stackTop - (objc-1)].o); /* "objv[0]" */ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + objv = &(stackPtr[stackTop - (objc-1)]); /* "objv[0]" */ DECACHE_STACK_INFO(); - tcl_MathInProgress++; + tsdPtr->mathInProgress++; result = ExprCallMathFunc(interp, eePtr, objc, objv); - tcl_MathInProgress--; + tsdPtr->mathInProgress--; CACHE_STACK_INFO(); if (result != TCL_OK) { goto checkForCatch; } - TRACE_WITH_OBJ(("callFunc1 %d => ", objc), - stackPtr[stackTop].o); + TRACE_WITH_OBJ(("%d => ", objc), stackPtr[stackTop]); ADJUST_PC(2); } case INST_TRY_CVT_TO_NUMERIC: { @@ -2569,16 +2486,17 @@ double d; char *s; Tcl_ObjType *tPtr; int converted, shared; - valuePtr = stackPtr[stackTop].o; + valuePtr = stackPtr[stackTop]; tPtr = valuePtr->typePtr; converted = 0; - if ((tPtr != &tclIntType) && (tPtr != &tclDoubleType)) { - s = Tcl_GetStringFromObj(valuePtr, (int *) NULL); - if (TclLooksLikeInt(s)) { /* FAILS IF NULLS */ + if ((tPtr != &tclIntType) && ((tPtr != &tclDoubleType) + || (valuePtr->bytes != NULL))) { + s = Tcl_GetStringFromObj(valuePtr, &length); + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d); @@ -2613,35 +2531,33 @@ objPtr = Tcl_NewDoubleObj(d); } Tcl_IncrRefCount(objPtr); TclDecrRefCount(valuePtr); valuePtr = objPtr; + stackPtr[stackTop] = valuePtr; tPtr = valuePtr->typePtr; } else { Tcl_InvalidateStringRep(valuePtr); } - stackPtr[stackTop].o = valuePtr; if (tPtr == &tclDoubleType) { d = valuePtr->internalRep.doubleValue; if (IS_NAN(d) || IS_INF(d)) { - TRACE(("tryCvtToNumeric \"%.20s\" => IEEE FLOATING PT ERROR\n", + TRACE(("\"%.20s\" => IEEE FLOATING PT ERROR\n", O2S(valuePtr))); TclExprFloatError(interp, d); result = TCL_ERROR; goto checkForCatch; } } - shared = shared; /* lint, shared not used. */ - converted = converted; /* lint, converted not used. */ - TRACE(("tryCvtToNumeric \"%.20s\" => numeric, %s, %s\n", - O2S(valuePtr), + shared = shared; /* lint, shared not used. */ + converted = converted; /* lint, converted not used. */ + TRACE(("\"%.20s\" => numeric, %s, %s\n", O2S(valuePtr), (converted? "converted" : "not converted"), (shared? "shared" : "not shared"))); } else { - TRACE(("tryCvtToNumeric \"%.20s\" => not numeric\n", - O2S(valuePtr))); + TRACE(("\"%.20s\" => not numeric\n", O2S(valuePtr))); } } ADJUST_PC(1); case INST_BREAK: @@ -2652,26 +2568,25 @@ * exception range, jump to its catchOffset. If no enclosing * range is found, stop execution and return TCL_BREAK. */ Tcl_ResetResult(interp); - rangePtr = TclGetExceptionRangeForPc(pc, /*catchOnly*/ 0, - codePtr); + rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 0, codePtr); if (rangePtr == NULL) { - TRACE(("break => no encl. loop or catch, returning TCL_BREAK\n")); + TRACE(("=> no encl. loop or catch, returning TCL_BREAK\n")); result = TCL_BREAK; goto abnormalReturn; /* no catch exists to check */ } switch (rangePtr->type) { case LOOP_EXCEPTION_RANGE: result = TCL_OK; - TRACE(("break => range at %d, new pc %d\n", + TRACE(("=> range at %d, new pc %d\n", rangePtr->codeOffset, rangePtr->breakOffset)); break; case CATCH_EXCEPTION_RANGE: result = TCL_BREAK; - TRACE(("break => ...\n")); + TRACE(("=> ...\n")); goto processCatch; /* it will use rangePtr */ default: panic("TclExecuteByteCode: unrecognized ExceptionRange type %d\n", rangePtr->type); } pc = (codePtr->codeStart + rangePtr->breakOffset); @@ -2685,31 +2600,30 @@ * catchOffset. If no enclosing range is found, stop * execution and return TCL_CONTINUE. */ Tcl_ResetResult(interp); - rangePtr = TclGetExceptionRangeForPc(pc, /*catchOnly*/ 0, - codePtr); + rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 0, codePtr); if (rangePtr == NULL) { - TRACE(("continue => no encl. loop or catch, returning TCL_CONTINUE\n")); + TRACE(("=> no encl. loop or catch, returning TCL_CONTINUE\n")); result = TCL_CONTINUE; goto abnormalReturn; } switch (rangePtr->type) { case LOOP_EXCEPTION_RANGE: if (rangePtr->continueOffset == -1) { - TRACE(("continue => loop w/o continue, checking for catch\n")); + TRACE(("=> loop w/o continue, checking for catch\n")); goto checkForCatch; } else { result = TCL_OK; - TRACE(("continue => range at %d, new pc %d\n", + TRACE(("=> range at %d, new pc %d\n", rangePtr->codeOffset, rangePtr->continueOffset)); } break; case CATCH_EXCEPTION_RANGE: result = TCL_CONTINUE; - TRACE(("continue => ...\n")); + TRACE(("=> ...\n")); goto processCatch; /* it will use rangePtr */ default: panic("TclExecuteByteCode: unrecognized ExceptionRange type %d\n", rangePtr->type); } pc = (codePtr->codeStart + rangePtr->continueOffset); @@ -2723,30 +2637,24 @@ * of the number of iterations of the loop body to -1. */ ForeachInfo *infoPtr = (ForeachInfo *) codePtr->auxDataArrayPtr[opnd].clientData; - int iterTmpIndex = infoPtr->loopIterNumTmp; - CallFrame *varFramePtr = iPtr->varFramePtr; - Var *compiledLocals = varFramePtr->compiledLocals; - Var *iterVarPtr; - Tcl_Obj *oldValuePtr; - - iterVarPtr = &(compiledLocals[iterTmpIndex]); - oldValuePtr = iterVarPtr->value.objPtr; + int iterTmpIndex = infoPtr->loopCtTemp; + Var *compiledLocals = iPtr->varFramePtr->compiledLocals; + Var *iterVarPtr = &(compiledLocals[iterTmpIndex]); + Tcl_Obj *oldValuePtr = iterVarPtr->value.objPtr; + if (oldValuePtr == NULL) { iterVarPtr->value.objPtr = Tcl_NewLongObj(-1); Tcl_IncrRefCount(iterVarPtr->value.objPtr); - if (oldValuePtr != NULL) { - Tcl_DecrRefCount(oldValuePtr); - } } else { Tcl_SetLongObj(oldValuePtr, -1); } TclSetVarScalar(iterVarPtr); TclClearVarUndefined(iterVarPtr); - TRACE(("foreach_start4 %u => loop iter count temp %d\n", + TRACE(("%u => loop iter count temp %d\n", opnd, iterTmpIndex)); } ADJUST_PC(5); case INST_FOREACH_STEP4: @@ -2756,47 +2664,45 @@ * "Step" a foreach loop (i.e., begin its next iteration) by * assigning the next value list element to each loop var. */ ForeachInfo *infoPtr = (ForeachInfo *) - codePtr->auxDataArrayPtr[opnd].clientData; + codePtr->auxDataArrayPtr[opnd].clientData; ForeachVarList *varListPtr; int numLists = infoPtr->numLists; - int iterTmpIndex = infoPtr->loopIterNumTmp; - CallFrame *varFramePtr = iPtr->varFramePtr; - Var *compiledLocals = varFramePtr->compiledLocals; - int iterNum, listTmpIndex, listLen, numVars; - int varIndex, valIndex, j; - Tcl_Obj *listPtr, *elemPtr, *oldValuePtr; + Var *compiledLocals = iPtr->varFramePtr->compiledLocals; + Tcl_Obj *listPtr; List *listRepPtr; Var *iterVarPtr, *listVarPtr; - int continueLoop = 0; + int iterNum, listTmpIndex, listLen, numVars; + int varIndex, valIndex, continueLoop, j; /* * Increment the temp holding the loop iteration number. */ - iterVarPtr = &(compiledLocals[iterTmpIndex]); - oldValuePtr = iterVarPtr->value.objPtr; - iterNum = (oldValuePtr->internalRep.longValue + 1); - Tcl_SetLongObj(oldValuePtr, iterNum); + iterVarPtr = &(compiledLocals[infoPtr->loopCtTemp]); + valuePtr = iterVarPtr->value.objPtr; + iterNum = (valuePtr->internalRep.longValue + 1); + Tcl_SetLongObj(valuePtr, iterNum); /* * Check whether all value lists are exhausted and we should * stop the loop. */ - listTmpIndex = infoPtr->firstListTmp; + continueLoop = 0; + listTmpIndex = infoPtr->firstValueTemp; for (i = 0; i < numLists; i++) { varListPtr = infoPtr->varLists[i]; numVars = varListPtr->numVars; - + listVarPtr = &(compiledLocals[listTmpIndex]); listPtr = listVarPtr->value.objPtr; result = Tcl_ListObjLength(interp, listPtr, &listLen); if (result != TCL_OK) { - TRACE_WITH_OBJ(("foreach_step4 %u => ERROR converting list %ld, \"%s\": ", + TRACE_WITH_OBJ(("%u => ERROR converting list %ld, \"%s\": ", opnd, i, O2S(listPtr)), Tcl_GetObjResult(interp)); goto checkForCatch; } if (listLen > (iterNum * numVars)) { @@ -2811,42 +2717,41 @@ * element from its value list. We already checked above * that each list temp holds a valid list object. */ if (continueLoop) { - listTmpIndex = infoPtr->firstListTmp; + listTmpIndex = infoPtr->firstValueTemp; for (i = 0; i < numLists; i++) { varListPtr = infoPtr->varLists[i]; numVars = varListPtr->numVars; listVarPtr = &(compiledLocals[listTmpIndex]); listPtr = listVarPtr->value.objPtr; - listRepPtr = (List *) - listPtr->internalRep.otherValuePtr; + listRepPtr = (List *) listPtr->internalRep.otherValuePtr; listLen = listRepPtr->elemCount; valIndex = (iterNum * numVars); for (j = 0; j < numVars; j++) { int setEmptyStr = 0; if (valIndex >= listLen) { setEmptyStr = 1; - elemPtr = Tcl_NewObj(); + valuePtr = Tcl_NewObj(); } else { - elemPtr = listRepPtr->elements[valIndex]; + valuePtr = listRepPtr->elements[valIndex]; } varIndex = varListPtr->varIndexes[j]; DECACHE_STACK_INFO(); value2Ptr = TclSetIndexedScalar(interp, - varIndex, elemPtr, /*leaveErrorMsg*/ 1); + varIndex, valuePtr, /*leaveErrorMsg*/ 1); CACHE_STACK_INFO(); if (value2Ptr == NULL) { - TRACE_WITH_OBJ(("foreach_step4 %u => ERROR init. index temp %d: ", + TRACE_WITH_OBJ(("%u => ERROR init. index temp %d: ", opnd, varIndex), Tcl_GetObjResult(interp)); if (setEmptyStr) { - Tcl_DecrRefCount(elemPtr); /* unneeded */ + Tcl_DecrRefCount(valuePtr); } result = TCL_ERROR; goto checkForCatch; } valIndex++; @@ -2854,17 +2759,16 @@ listTmpIndex++; } } /* - * Now push a "1" object if at least one value list had a - * remaining element and the loop should continue. - * Otherwise push "0". + * Push 1 if at least one value list had a remaining element + * and the loop should continue. Otherwise push 0. */ PUSH_OBJECT(Tcl_NewLongObj(continueLoop)); - TRACE(("foreach_step4 %u => %d lists, iter %d, %s loop\n", + TRACE(("%u => %d lists, iter %d, %s loop\n", opnd, numLists, iterNum, (continueLoop? "continue" : "exit"))); } ADJUST_PC(5); @@ -2873,33 +2777,32 @@ * Record start of the catch command with exception range index * equal to the operand. Push the current stack depth onto the * special catch stack. */ catchStackPtr[++catchTop] = stackTop; - TRACE(("beginCatch4 %u => catchTop=%d, stackTop=%d\n", + TRACE(("%u => catchTop=%d, stackTop=%d\n", TclGetUInt4AtPtr(pc+1), catchTop, stackTop)); ADJUST_PC(5); case INST_END_CATCH: catchTop--; result = TCL_OK; - TRACE(("endCatch => catchTop=%d\n", catchTop)); + TRACE(("=> catchTop=%d\n", catchTop)); ADJUST_PC(1); case INST_PUSH_RESULT: PUSH_OBJECT(Tcl_GetObjResult(interp)); - TRACE_WITH_OBJ(("pushResult => "), Tcl_GetObjResult(interp)); + TRACE_WITH_OBJ(("=> "), Tcl_GetObjResult(interp)); ADJUST_PC(1); case INST_PUSH_RETURN_CODE: PUSH_OBJECT(Tcl_NewLongObj(result)); - TRACE(("pushReturnCode => %u\n", result)); + TRACE(("=> %u\n", result)); ADJUST_PC(1); default: - TRACE(("UNRECOGNIZED INSTRUCTION %u\n", opCode)); - panic("TclExecuteByteCode: unrecognized opCode %u", opCode); + panic("TclExecuteByteCode: unrecognized opCode %u", *pc); } /* end of switch on opCode */ /* * Division by zero in an expression. Control only reaches this * point by "goto divideByZero". @@ -2920,16 +2823,24 @@ * execution and return the "exception" code. */ checkForCatch: if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { - RecordTracebackInfo(interp, pc, codePtr); + bytes = GetSrcInfoForPc(pc, codePtr, &length); + if (bytes != NULL) { + Tcl_LogCommandInfo(interp, codePtr->source, bytes, length); + iPtr->flags |= ERR_ALREADY_LOGGED; + } } - rangePtr = TclGetExceptionRangeForPc(pc, /*catchOnly*/ 1, codePtr); + rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 1, codePtr); if (rangePtr == NULL) { - TRACE((" ... no enclosing catch, returning %s\n", - StringForResultCode(result))); +#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 @@ -2943,13 +2854,17 @@ processCatch: while (stackTop > catchStackPtr[catchTop]) { valuePtr = POP_OBJECT(); TclDecrRefCount(valuePtr); } - TRACE((" ... found catch at %d, catchTop=%d, unwound to %d, new pc %u\n", +#ifdef TCL_COMPILE_DEBUG + if (traceInstructions) { + fprintf(stdout, " ... found catch at %d, catchTop=%d, unwound to %d, new pc %u\n", rangePtr->codeOffset, catchTop, catchStackPtr[catchTop], - (unsigned int)(rangePtr->catchOffset))); + (unsigned int)(rangePtr->catchOffset)); + } +#endif pc = (codePtr->codeStart + rangePtr->catchOffset); continue; /* restart the execution loop at pc */ } /* end of infinite loop dispatching on instructions */ /* @@ -2974,10 +2889,11 @@ eePtr->stackTop = initStackTop; return result; #undef STATIC_CATCH_STACK_SIZE } +#ifdef TCL_COMPILE_DEBUG /* *---------------------------------------------------------------------- * * PrintByteCodeInfo -- * @@ -2998,49 +2914,48 @@ PrintByteCodeInfo(codePtr) register ByteCode *codePtr; /* The bytecode whose summary is printed * to stdout. */ { Proc *procPtr = codePtr->procPtr; - int numCmds = codePtr->numCommands; - int numObjs = codePtr->numObjects; - int objBytes, i; - - objBytes = (numObjs * sizeof(Tcl_Obj)); - for (i = 0; i < numObjs; i++) { - Tcl_Obj *litObjPtr = codePtr->objArrayPtr[i]; - if (litObjPtr->bytes != NULL) { - objBytes += litObjPtr->length; - } - } - - fprintf(stdout, "\nExecuting ByteCode 0x%x, ref ct %u, epoch %u, interp 0x%x(epoch %u)\n", + Interp *iPtr = (Interp *) *codePtr->interpHandle; + + fprintf(stdout, "\nExecuting ByteCode 0x%x, refCt %u, epoch %u, interp 0x%x (epoch %u)\n", (unsigned int) codePtr, codePtr->refCount, - codePtr->compileEpoch, (unsigned int) codePtr->iPtr, - codePtr->iPtr->compileEpoch); + codePtr->compileEpoch, (unsigned int) iPtr, + iPtr->compileEpoch); fprintf(stdout, " Source: "); - TclPrintSource(stdout, codePtr->source, 70); + TclPrintSource(stdout, codePtr->source, 60); - fprintf(stdout, "\n Cmds %d, chars %d, inst %u, objs %u, aux %d, stk depth %u, code/src %.2fn", - numCmds, codePtr->numSrcChars, codePtr->numCodeBytes, numObjs, + 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, - (codePtr->numSrcChars? - ((float)codePtr->totalSize)/((float)codePtr->numSrcChars) : 0.0)); - - fprintf(stdout, " Code %d = %d(header)+%d(inst)+%d(objs)+%d(exc)+%d(aux)+%d(cmd map)\n", - codePtr->totalSize, sizeof(ByteCode), codePtr->numCodeBytes, - objBytes, (codePtr->numExcRanges * sizeof(ExceptionRange)), +#ifdef TCL_COMPILE_STATS + (codePtr->numSrcBytes? + ((float)codePtr->structureSize)/((float)codePtr->numSrcBytes) : 0.0)); +#else + 0.0); +#endif +#ifdef TCL_COMPILE_STATS + fprintf(stdout, " Code %d = header %d+inst %d+litObj %d+exc %d+aux %d+cmdMap %d\n", + codePtr->structureSize, + (sizeof(ByteCode) - (sizeof(size_t) + sizeof(Tcl_Time))), + codePtr->numCodeBytes, + (codePtr->numLitObjects * sizeof(Tcl_Obj *)), + (codePtr->numExceptRanges * sizeof(ExceptionRange)), (codePtr->numAuxDataItems * sizeof(AuxData)), codePtr->numCmdLocBytes); - +#endif /* TCL_COMPILE_STATS */ if (procPtr != NULL) { fprintf(stdout, - " Proc 0x%x, ref ct %d, args %d, compiled locals %d\n", + " Proc 0x%x, refCt %d, args %d, compiled locals %d\n", (unsigned int) procPtr, procPtr->refCount, procPtr->numArgs, procPtr->numCompiledLocals); } } +#endif /* TCL_COMPILE_DEBUG */ /* *---------------------------------------------------------------------- * * ValidatePcAndStackTop -- @@ -3059,11 +2974,12 @@ *---------------------------------------------------------------------- */ #ifdef TCL_COMPILE_DEBUG static void -ValidatePcAndStackTop(codePtr, pc, stackTop, stackLowerBound, stackUpperBound) +ValidatePcAndStackTop(codePtr, pc, stackTop, stackLowerBound, + stackUpperBound) register ByteCode *codePtr; /* The bytecode whose summary is printed * to stdout. */ unsigned char *pc; /* Points to first byte of a bytecode * instruction. The program counter. */ int stackTop; /* Current stack top. Must be between @@ -3115,12 +3031,11 @@ * * IllegalExprOperandType -- * * Used by TclExecuteByteCode to add an error message to errorInfo * when an illegal operand type is detected by an expression - * instruction. The argument opCode holds the failing instruction's - * opcode and opndPtr holds the operand object in error. + * instruction. The argument opndPtr holds the operand object in error. * * Results: * None. * * Side effects: @@ -3128,27 +3043,43 @@ * *---------------------------------------------------------------------- */ static void -IllegalExprOperandType(interp, opCode, opndPtr) +IllegalExprOperandType(interp, pc, opndPtr) Tcl_Interp *interp; /* Interpreter to which error information * pertains. */ - unsigned int opCode; /* The instruction opcode being executed + 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. */ { + unsigned char opCode = *pc; + int isDouble; + Tcl_ResetResult(interp); if ((opndPtr->bytes == NULL) || (opndPtr->length == 0)) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't use empty string as operand of \"", operatorStrings[opCode - INST_LOR], "\"", (char *) NULL); } else { + isDouble = 1; + if (opndPtr->typePtr != &tclDoubleType) { + /* + * See if the operand can be interpreted as a double in order to + * improve the error message. + */ + + char *s = Tcl_GetString(opndPtr); + double d; + + if (Tcl_GetDouble((Tcl_Interp *) NULL, s, &d) != TCL_OK) { + isDouble = 0; + } + } Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't use ", - ((opndPtr->typePtr == &tclDoubleType) ? - "floating-point value" : "non-numeric string"), + (isDouble? "floating-point value" : "non-numeric string"), " as operand of \"", operatorStrings[opCode - INST_LOR], "\"", (char *) NULL); } } @@ -3191,11 +3122,10 @@ /* * Get the string rep from the objv argument objects and place their * pointers in argv. First make sure argv is large enough to hold the * objc args plus 1 extra word for the zero end-of-argv word. - * THIS FAILS IF AN OBJECT'S STRING REP CONTAINS NULLS. */ argv = (char **) ckalloc((unsigned)(objc + 1) * sizeof(char *)); for (i = 0; i < objc; i++) { argv[i] = Tcl_GetStringFromObj(objv[i], &length); @@ -3218,80 +3148,10 @@ p, cmdPtr->proc, cmdPtr->clientData, objc, argv); ckfree((char *) argv); ckfree((char *) p); } - -/* - *---------------------------------------------------------------------- - * - * RecordTracebackInfo -- - * - * Procedure called by TclExecuteByteCode to record information - * about what was being executed when the error occurred. - * - * Results: - * None. - * - * Side effects: - * Appends information about the command being executed to the - * "errorInfo" variable. Sets the errorLine field in the interpreter - * to the line number of that command. Sets the ERR_ALREADY_LOGGED - * bit in the interpreter's execution flags. - * - *---------------------------------------------------------------------- - */ - -static void -RecordTracebackInfo(interp, pc, codePtr) - Tcl_Interp *interp; /* The interpreter in which the error - * occurred. */ - unsigned char *pc; /* The program counter value where the error * occurred. This points to a bytecode - * instruction in codePtr's code. */ - ByteCode *codePtr; /* The bytecode sequence being executed. */ -{ - register Interp *iPtr = (Interp *) interp; - char *cmd, *ellipsis; - char buf[200]; - register char *p; - int numChars; - - /* - * Record the command in errorInfo (up to a certain number of - * characters, or up to the first newline). - */ - - iPtr->errorLine = 1; - cmd = GetSrcInfoForPc(pc, codePtr, &numChars); - if (cmd != NULL) { - for (p = codePtr->source; p != cmd; p++) { - if (*p == '\n') { - iPtr->errorLine++; - } - } - for ( ; (isspace(UCHAR(*p)) || (*p == ';')); p++) { - if (*p == '\n') { - iPtr->errorLine++; - } - } - - ellipsis = ""; - if (numChars > 150) { - numChars = 150; - ellipsis = "..."; - } - if (!(iPtr->flags & ERR_IN_PROGRESS)) { - sprintf(buf, "\n while executing\n\"%.*s%s\"", - numChars, cmd, ellipsis); - } else { - sprintf(buf, "\n invoked from within\n\"%.*s%s\"", - numChars, cmd, ellipsis); - } - Tcl_AddObjErrorInfo(interp, buf, -1); - iPtr->flags |= ERR_ALREADY_LOGGED; - } -} /* *---------------------------------------------------------------------- * * GetSrcInfoForPc -- @@ -3414,22 +3274,22 @@ } /* *---------------------------------------------------------------------- * - * TclGetExceptionRangeForPc -- + * GetExceptRangeForPc -- * - * Procedure that given a program counter value, returns the closest - * enclosing ExceptionRange that matches the kind requested. + * Given a program counter value, return the closest enclosing + * ExceptionRange. * * Results: * In the normal case, catchOnly is 0 (false) and this procedure * returns a pointer to the most closely enclosing ExceptionRange * structure regardless of whether it is a loop or catch exception * range. This is appropriate when processing a TCL_BREAK or * TCL_CONTINUE, which will be "handled" either by a loop exception - * range or a closer catch range. If catchOnly is nonzero (true), this + * range or a closer catch range. If catchOnly is nonzero, this * procedure ignores loop exception ranges and returns a pointer to the * closest catch range. If no matching ExceptionRange is found that * encloses pc, a NULL is returned. * * Side effects: @@ -3436,36 +3296,41 @@ * None. * *---------------------------------------------------------------------- */ -ExceptionRange * -TclGetExceptionRangeForPc(pc, catchOnly, codePtr) +static ExceptionRange * +GetExceptRangeForPc(pc, catchOnly, codePtr) 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 catchOnly; /* If 0, consider either loop or catch - * ExceptionRanges in search. Otherwise + * ExceptionRanges in search. If nonzero * consider only catch ranges (and ignore * any closer loop ranges). */ ByteCode* codePtr; /* Points to the ByteCode in which to search * for the enclosing ExceptionRange. */ { - ExceptionRange *rangeArrayPtr = codePtr->excRangeArrayPtr; - int numRanges = codePtr->numExcRanges; + ExceptionRange *rangeArrayPtr; + int numRanges = codePtr->numExceptRanges; register ExceptionRange *rangePtr; - int codeOffset = (pc - codePtr->codeStart); + int pcOffset = (pc - codePtr->codeStart); register int i, level; - for (level = codePtr->maxExcRangeDepth; level >= 0; level--) { + if (numRanges == 0) { + return NULL; + } + rangeArrayPtr = codePtr->exceptArrayPtr; + + for (level = codePtr->maxExceptDepth; level >= 0; level--) { for (i = 0; i < numRanges; i++) { rangePtr = &(rangeArrayPtr[i]); if (rangePtr->nestingLevel == level) { int start = rangePtr->codeOffset; int end = (start + rangePtr->numCodeBytes); - if ((start <= codeOffset) && (codeOffset < end)) { + if ((start <= pcOffset) && (pcOffset < end)) { if ((!catchOnly) || (rangePtr->type == CATCH_EXCEPTION_RANGE)) { return rangePtr; } } @@ -3473,10 +3338,40 @@ } } return NULL; } +/* + *---------------------------------------------------------------------- + * + * GetOpcodeName -- + * + * This procedure is called by the TRACE and TRACE_WITH_OBJ macros + * used in TclExecuteByteCode 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 char * +GetOpcodeName(pc) + unsigned char *pc; /* Points to the instruction whose name + * should be returned. */ +{ + unsigned char opCode = *pc; + + return instructionTable[opCode].name; +} +#endif /* TCL_COMPILE_DEBUG */ + /* *---------------------------------------------------------------------- * * Math Functions -- * @@ -3502,25 +3397,26 @@ * the function. */ ClientData clientData; /* Contains the address of a procedure that * takes one double argument and returns a * double result. */ { - StackItem *stackPtr; /* Cached evaluation stack base pointer. */ + Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */ register int stackTop; /* Cached top index of evaluation stack. */ register Tcl_Obj *valuePtr; Tcl_ObjType *tPtr; double d, dResult; long i; - int result = TCL_OK; + int length, result; double (*func) _ANSI_ARGS_((double)) = (double (*)_ANSI_ARGS_((double))) clientData; /* * Set stackPtr and stackTop from eePtr. */ - + + result = TCL_OK; CACHE_STACK_INFO(); /* * Pop the function's argument from the evaluation stack. Convert it * to a double if necessary. @@ -3531,14 +3427,14 @@ if (tPtr == &tclIntType) { d = (double) valuePtr->internalRep.longValue; } else if (tPtr == &tclDoubleType) { d = valuePtr->internalRep.doubleValue; - } else { /* FAILS IF STRING REP HAS NULLS */ - char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL); + } else { + char *s = Tcl_GetStringFromObj(valuePtr, &length); - if (TclLooksLikeInt(s)) { + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); d = (double) valuePtr->internalRep.longValue; } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d); } @@ -3582,26 +3478,27 @@ * the function. */ ClientData clientData; /* Contains the address of a procedure that * takes two double arguments and * returns a double result. */ { - StackItem *stackPtr; /* Cached evaluation stack base pointer. */ + Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */ register int stackTop; /* Cached top index of evaluation stack. */ register Tcl_Obj *valuePtr, *value2Ptr; Tcl_ObjType *tPtr; double d1, d2, dResult; long i; char *s; - int result = TCL_OK; + int length, result; double (*func) _ANSI_ARGS_((double, double)) = (double (*)_ANSI_ARGS_((double, double))) clientData; /* * Set stackPtr and stackTop from eePtr. */ - + + result = TCL_OK; CACHE_STACK_INFO(); /* * Pop the function's two arguments from the evaluation stack. Convert * them to doubles if necessary. @@ -3613,13 +3510,13 @@ tPtr = valuePtr->typePtr; if (tPtr == &tclIntType) { d1 = (double) valuePtr->internalRep.longValue; } else if (tPtr == &tclDoubleType) { d1 = valuePtr->internalRep.doubleValue; - } else { /* FAILS IF STRING REP HAS NULLS */ - s = Tcl_GetStringFromObj(valuePtr, (int *) NULL); - if (TclLooksLikeInt(s)) { + } else { + s = Tcl_GetStringFromObj(valuePtr, &length); + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); d1 = (double) valuePtr->internalRep.longValue; } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d1); } @@ -3635,13 +3532,13 @@ tPtr = value2Ptr->typePtr; if (tPtr == &tclIntType) { d2 = value2Ptr->internalRep.longValue; } else if (tPtr == &tclDoubleType) { d2 = value2Ptr->internalRep.doubleValue; - } else { /* FAILS IF STRING REP HAS NULLS */ - s = Tcl_GetStringFromObj(value2Ptr, (int *) NULL); - if (TclLooksLikeInt(s)) { + } else { + s = Tcl_GetStringFromObj(value2Ptr, &length); + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, value2Ptr, &i); d2 = (double) value2Ptr->internalRep.longValue; } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, value2Ptr, &d2); } @@ -3681,22 +3578,23 @@ * function. */ ExecEnv *eePtr; /* Points to the environment for executing * the function. */ ClientData clientData; /* Ignored. */ { - StackItem *stackPtr; /* Cached evaluation stack base pointer. */ + Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */ register int stackTop; /* Cached top index of evaluation stack. */ register Tcl_Obj *valuePtr; Tcl_ObjType *tPtr; long i, iResult; double d, dResult; - int result = TCL_OK; + int length, result; /* * Set stackPtr and stackTop from eePtr. */ - + + result = TCL_OK; CACHE_STACK_INFO(); /* * Pop the argument from the evaluation stack. */ @@ -3706,14 +3604,14 @@ if (tPtr == &tclIntType) { i = valuePtr->internalRep.longValue; } else if (tPtr == &tclDoubleType) { d = valuePtr->internalRep.doubleValue; - } else { /* FAILS IF STRING REP HAS NULLS */ - char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL); + } else { + char *s = Tcl_GetStringFromObj(valuePtr, &length); - if (TclLooksLikeInt(s)) { + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d); } if (result != TCL_OK) { @@ -3775,21 +3673,22 @@ * function. */ ExecEnv *eePtr; /* Points to the environment for executing * the function. */ ClientData clientData; /* Ignored. */ { - StackItem *stackPtr; /* Cached evaluation stack base pointer. */ + Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */ register int stackTop; /* Cached top index of evaluation stack. */ register Tcl_Obj *valuePtr; double dResult; long i; - int result = TCL_OK; + int length, result; /* * Set stackPtr and stackTop from eePtr. */ - + + result = TCL_OK; CACHE_STACK_INFO(); /* * Pop the argument from the evaluation stack. */ @@ -3797,14 +3696,14 @@ valuePtr = POP_OBJECT(); if (valuePtr->typePtr == &tclIntType) { dResult = (double) valuePtr->internalRep.longValue; } else if (valuePtr->typePtr == &tclDoubleType) { dResult = valuePtr->internalRep.doubleValue; - } else { /* FAILS IF STRING REP HAS NULLS */ - char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL); + } else { + char *s = Tcl_GetStringFromObj(valuePtr, &length); - if (TclLooksLikeInt(s)) { + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); dResult = (double) valuePtr->internalRep.longValue; } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &dResult); @@ -3839,23 +3738,24 @@ * function. */ ExecEnv *eePtr; /* Points to the environment for executing * the function. */ ClientData clientData; /* Ignored. */ { - StackItem *stackPtr; /* Cached evaluation stack base pointer. */ + Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */ register int stackTop; /* Cached top index of evaluation stack. */ register Tcl_Obj *valuePtr; Tcl_ObjType *tPtr; long i = 0; /* Initialized to avoid compiler warning. */ long iResult; double d; - int result = TCL_OK; + int length, result; /* * Set stackPtr and stackTop from eePtr. */ - + + result = TCL_OK; CACHE_STACK_INFO(); /* * Pop the argument from the evaluation stack. */ @@ -3865,14 +3765,14 @@ if (tPtr == &tclIntType) { i = valuePtr->internalRep.longValue; } else if (tPtr == &tclDoubleType) { d = valuePtr->internalRep.doubleValue; - } else { /* FAILS IF STRING REP HAS NULLS */ - char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL); + } else { + char *s = Tcl_GetStringFromObj(valuePtr, &length); - if (TclLooksLikeInt(s)) { + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d); } if (result != TCL_OK) { @@ -3932,11 +3832,11 @@ * function. */ ExecEnv *eePtr; /* Points to the environment for executing * the function. */ ClientData clientData; /* Ignored. */ { - StackItem *stackPtr; /* Cached evaluation stack base pointer. */ + Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */ register int stackTop; /* Cached top index of evaluation stack. */ Interp *iPtr = (Interp *) interp; double dResult; int tmp; @@ -4020,23 +3920,24 @@ * function. */ ExecEnv *eePtr; /* Points to the environment for executing * the function. */ ClientData clientData; /* Ignored. */ { - StackItem *stackPtr; /* Cached evaluation stack base pointer. */ + Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */ register int stackTop; /* Cached top index of evaluation stack. */ Tcl_Obj *valuePtr; Tcl_ObjType *tPtr; long i = 0; /* Initialized to avoid compiler warning. */ long iResult; double d, temp; - int result = TCL_OK; + int length, result; /* * Set stackPtr and stackTop from eePtr. */ - + + result = TCL_OK; CACHE_STACK_INFO(); /* * Pop the argument from the evaluation stack. */ @@ -4046,14 +3947,14 @@ if (tPtr == &tclIntType) { i = valuePtr->internalRep.longValue; } else if (tPtr == &tclDoubleType) { d = valuePtr->internalRep.doubleValue; - } else { /* FAILS IF STRING REP HAS NULLS */ - char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL); + } else { + char *s = Tcl_GetStringFromObj(valuePtr, &length); - if (TclLooksLikeInt(s)) { + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d); } if (result != TCL_OK) { @@ -4116,17 +4017,17 @@ * function. */ ExecEnv *eePtr; /* Points to the environment for executing * the function. */ ClientData clientData; /* Ignored. */ { - StackItem *stackPtr; /* Cached evaluation stack base pointer. */ + Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */ register int stackTop; /* Cached top index of evaluation stack. */ Interp *iPtr = (Interp *) interp; Tcl_Obj *valuePtr; Tcl_ObjType *tPtr; long i = 0; /* Initialized to avoid compiler warning. */ - int result; + int isDouble, result; /* * Set stackPtr and stackTop from eePtr. */ @@ -4140,16 +4041,31 @@ valuePtr = POP_OBJECT(); tPtr = valuePtr->typePtr; if (tPtr == &tclIntType) { i = valuePtr->internalRep.longValue; - } else { /* FAILS IF STRING REP HAS NULLS */ + } else { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); if (result != TCL_OK) { + /* + * See if the operand can be interpreted as a double in order to + * improve the error message. + */ + + isDouble = 1; + if (valuePtr->typePtr != &tclDoubleType) { + char *s = Tcl_GetString(valuePtr); + double d; + + if (Tcl_GetDouble((Tcl_Interp *) NULL, s, &d) != TCL_OK) { + isDouble = 0; + } + } + Tcl_ResetResult(interp); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't use ", - ((tPtr == &tclDoubleType)? "floating-point value" : "non-numeric string"), + (isDouble? "floating-point value":"non-numeric string"), " as argument to srand", (char *) NULL); Tcl_DecrRefCount(valuePtr); DECACHE_STACK_INFO(); return result; } @@ -4206,11 +4122,11 @@ * the 0-th argument. */ Tcl_Obj **objv; /* The array of arguments. The function name * is objv[0]. */ { Interp *iPtr = (Interp *) interp; - StackItem *stackPtr; /* Cached evaluation stack base pointer. */ + Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */ register int stackTop; /* Cached top index of evaluation stack. */ char *funcName; Tcl_HashEntry *hPtr; MathFunc *mathFuncPtr; /* Information about math function. */ Tcl_Value args[MAX_MATH_ARGS]; /* Arguments for function call. */ @@ -4217,26 +4133,26 @@ Tcl_Value funcResult; /* Result of function call as Tcl_Value. */ register Tcl_Obj *valuePtr; Tcl_ObjType *tPtr; long i; double d; - int j, k, result; - + int j, k, length, result; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + Tcl_ResetResult(interp); - + /* * Set stackPtr and stackTop from eePtr. */ CACHE_STACK_INFO(); /* * Look up the MathFunc record for the function. - * THIS FAILS IF THE OBJECT'S STRING REP CONTAINS NULLS. */ - funcName = Tcl_GetStringFromObj(objv[0], (int *) NULL); + funcName = Tcl_GetString(objv[0]); hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName); if (hPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "unknown math function \"", funcName, "\"", (char *) NULL); result = TCL_ERROR; @@ -4265,16 +4181,15 @@ } else if (tPtr == &tclDoubleType) { d = valuePtr->internalRep.doubleValue; } else { /* * Try to convert to int first then double. - * FAILS IF STRING REP HAS NULLS. */ - char *s = Tcl_GetStringFromObj(valuePtr, (int *) NULL); + char *s = Tcl_GetStringFromObj(valuePtr, &length); - if (TclLooksLikeInt(s)) { + if (TclLooksLikeInt(s, length)) { result = Tcl_GetLongFromObj((Tcl_Interp *) NULL, valuePtr, &i); } else { result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d); } @@ -4312,14 +4227,14 @@ /* * Invoke the function and copy its result back into valuePtr. */ - tcl_MathInProgress++; + tsdPtr->mathInProgress++; result = (*mathFuncPtr->proc)(mathFuncPtr->clientData, interp, args, &funcResult); - tcl_MathInProgress--; + tsdPtr->mathInProgress--; if (result != TCL_OK) { goto done; } /* @@ -4326,11 +4241,11 @@ * Pop the objc top stack elements and decrement their ref counts. */ i = (stackTop - (objc-1)); while (i <= stackTop) { - valuePtr = stackPtr[i].o; + valuePtr = stackPtr[i]; Tcl_DecrRefCount(valuePtr); i++; } stackTop -= objc; @@ -4398,18 +4313,42 @@ } else { s = "floating-point value too large to represent"; Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1); Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW", s, (char *) NULL); } - } else { /* FAILS IF STRING REP CONTAINS NULLS */ - char msg[100]; + } else { + char msg[64 + TCL_INTEGER_SPACE]; sprintf(msg, "unknown floating-point error, errno = %d", errno); Tcl_AppendToObj(Tcl_GetObjResult(interp), msg, -1); Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN", msg, (char *) NULL); } } + +/* + *---------------------------------------------------------------------- + * + * TclMathInProgress -- + * + * This procedure is called to find out if Tcl is doing math + * in this thread. + * + * Results: + * 0 or 1. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TclMathInProgress() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return tsdPtr->mathInProgress; +} #ifdef TCL_COMPILE_STATS /* *---------------------------------------------------------------------- * @@ -4465,124 +4404,359 @@ ClientData unused; /* Unused. */ Tcl_Interp *interp; /* The current interpreter. */ int argc; /* The number of arguments. */ char **argv; /* The argument strings. */ { - register double total = 0.0; - register int i; - int maxSizeDecade = 0; - double totalHeaderBytes = (tclNumCompilations * sizeof(ByteCode)); + 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; + numInstructions = 0.0; for (i = 0; i < 256; i++) { - if (instructionCount[i] != 0) { - total += instructionCount[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. + */ + + fprintf(stdout, "\n----------------------------------------------------------------\n"); + fprintf(stdout, + "Compilation and execution statistics for interpreter 0x%x\n", + (unsigned int) iPtr); + + fprintf(stdout, "\nNumber ByteCodes executed %ld\n", + statsPtr->numExecutions); + fprintf(stdout, "Number ByteCodes compiled %ld\n", + statsPtr->numCompilations); + fprintf(stdout, " Mean executions/compile %.1f\n", + ((float)statsPtr->numExecutions) / ((float)statsPtr->numCompilations)); + + fprintf(stdout, "\nInstructions executed %.0f\n", + numInstructions); + fprintf(stdout, " Mean inst/compile %.0f\n", + numInstructions / statsPtr->numCompilations); + fprintf(stdout, " Mean inst/execution %.0f\n", + numInstructions / statsPtr->numExecutions); + + fprintf(stdout, "\nTotal ByteCodes %ld\n", + statsPtr->numCompilations); + fprintf(stdout, " Source bytes %.6g\n", + statsPtr->totalSrcBytes); + fprintf(stdout, " Code bytes %.6g\n", + totalCodeBytes); + fprintf(stdout, " ByteCode bytes %.6g\n", + statsPtr->totalByteCodeBytes); + fprintf(stdout, " Literal bytes %.6g\n", + totalLiteralBytes); + fprintf(stdout, " table %d + bkts %d + entries %ld + objects %ld + strings %.6g\n", + sizeof(LiteralTable), + iPtr->literalTable.numBuckets * sizeof(LiteralEntry *), + statsPtr->numLiteralsCreated * sizeof(LiteralEntry), + statsPtr->numLiteralsCreated * sizeof(Tcl_Obj), + statsPtr->totalLitStringBytes); + fprintf(stdout, " Mean code/compile %.1f\n", + totalCodeBytes / statsPtr->numCompilations); + fprintf(stdout, " Mean code/source %.1f\n", + totalCodeBytes / statsPtr->totalSrcBytes); + + fprintf(stdout, "\nCurrent ByteCodes %ld\n", + numCurrentByteCodes); + fprintf(stdout, " Source bytes %.6g\n", + statsPtr->currentSrcBytes); + fprintf(stdout, " Code bytes %.6g\n", + currentCodeBytes); + fprintf(stdout, " ByteCode bytes %.6g\n", + statsPtr->currentByteCodeBytes); + fprintf(stdout, " Literal bytes %.6g\n", + currentLiteralBytes); + fprintf(stdout, " table %d + bkts %d + entries %d + objects %d + strings %.6g\n", + sizeof(LiteralTable), + iPtr->literalTable.numBuckets * sizeof(LiteralEntry *), + iPtr->literalTable.numEntries * sizeof(LiteralEntry), + iPtr->literalTable.numEntries * sizeof(Tcl_Obj), + statsPtr->currentLitStringBytes); + fprintf(stdout, " Mean code/source %.1f\n", + currentCodeBytes / statsPtr->currentSrcBytes); + fprintf(stdout, " Code + source bytes %.6g (%0.1f mean code/src)\n", + (currentCodeBytes + statsPtr->currentSrcBytes), + (currentCodeBytes / statsPtr->currentSrcBytes) + 1.0); + + /* + * 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; + + fprintf(stdout, "\nTotal objects (all interps) %ld\n", + tclObjsAlloced); + fprintf(stdout, "Current objects %ld\n", + (tclObjsAlloced - tclObjsFreed)); + fprintf(stdout, "Total literal objects %ld\n", + statsPtr->numLiteralsCreated); + + fprintf(stdout, "\nCurrent literal objects %d (%0.1f%% of current objects)\n", + globalTablePtr->numEntries, + (globalTablePtr->numEntries * 100.0) / (tclObjsAlloced-tclObjsFreed)); + fprintf(stdout, " ByteCode literals %ld (%0.1f%% of current literals)\n", + numByteCodeLits, + (numByteCodeLits * 100.0) / globalTablePtr->numEntries); + fprintf(stdout, " Literals reused > 1x %d\n", + numSharedMultX); + fprintf(stdout, " Mean reference count %.2f\n", + ((double) refCountSum) / globalTablePtr->numEntries); + fprintf(stdout, " Mean len, str reused >1x %.2f\n", + (numSharedMultX? (strBytesSharedMultX/numSharedMultX) : 0.0)); + fprintf(stdout, " Mean len, str used 1x %.2f\n", + (numSharedOnce? (strBytesSharedOnce/numSharedOnce) : 0.0)); + fprintf(stdout, " Total sharing savings %.6g (%0.1f%% of bytes if no sharing)\n", + sharingBytesSaved, + (sharingBytesSaved * 100.0) / (objBytesIfUnshared + strBytesIfUnshared)); + fprintf(stdout, " Bytes with sharing %.6g\n", + currentLiteralBytes); + fprintf(stdout, " table %d + bkts %d + entries %d + objects %d + strings %.6g\n", + sizeof(LiteralTable), + iPtr->literalTable.numBuckets * sizeof(LiteralEntry *), + iPtr->literalTable.numEntries * sizeof(LiteralEntry), + iPtr->literalTable.numEntries * sizeof(Tcl_Obj), + statsPtr->currentLitStringBytes); + fprintf(stdout, " Bytes if no sharing %.6g = objects %.6g + strings %.6g\n", + (objBytesIfUnshared + strBytesIfUnshared), + objBytesIfUnshared, strBytesIfUnshared); + fprintf(stdout, " String sharing savings %.6g = unshared %.6g - shared %.6g\n", + (strBytesIfUnshared - statsPtr->currentLitStringBytes), + strBytesIfUnshared, statsPtr->currentLitStringBytes); + fprintf(stdout, " Literal mgmt overhead %ld (%0.1f%% of bytes with sharing)\n", + literalMgmtBytes, + (literalMgmtBytes * 100.0) / currentLiteralBytes); + fprintf(stdout, " table %d + buckets %d + entries %d\n", + sizeof(LiteralTable), + iPtr->literalTable.numBuckets * sizeof(LiteralEntry *), + iPtr->literalTable.numEntries * sizeof(LiteralEntry)); + + /* + * Breakdown of current ByteCode space requirements. + */ + + fprintf(stdout, "\nBreakdown of current ByteCode requirements:\n"); + fprintf(stdout, " Bytes Pct of Avg per\n"); + fprintf(stdout, " total ByteCode\n"); + fprintf(stdout, "Total %12.6g 100.00%% %8.1f\n", + statsPtr->currentByteCodeBytes, + statsPtr->currentByteCodeBytes / numCurrentByteCodes); + fprintf(stdout, "Header %12.6g %8.1f%% %8.1f\n", + currentHeaderBytes, + ((currentHeaderBytes * 100.0) / statsPtr->currentByteCodeBytes), + currentHeaderBytes / numCurrentByteCodes); + fprintf(stdout, "Instructions %12.6g %8.1f%% %8.1f\n", + statsPtr->currentInstBytes, + ((statsPtr->currentInstBytes * 100.0) / statsPtr->currentByteCodeBytes), + statsPtr->currentInstBytes / numCurrentByteCodes); + fprintf(stdout, "Literal ptr array %12.6g %8.1f%% %8.1f\n", + statsPtr->currentLitBytes, + ((statsPtr->currentLitBytes * 100.0) / statsPtr->currentByteCodeBytes), + statsPtr->currentLitBytes / numCurrentByteCodes); + fprintf(stdout, "Exception table %12.6g %8.1f%% %8.1f\n", + statsPtr->currentExceptBytes, + ((statsPtr->currentExceptBytes * 100.0) / statsPtr->currentByteCodeBytes), + statsPtr->currentExceptBytes / numCurrentByteCodes); + fprintf(stdout, "Auxiliary data %12.6g %8.1f%% %8.1f\n", + statsPtr->currentAuxBytes, + ((statsPtr->currentAuxBytes * 100.0) / statsPtr->currentByteCodeBytes), + statsPtr->currentAuxBytes / numCurrentByteCodes); + fprintf(stdout, "Command map %12.6g %8.1f%% %8.1f\n", + statsPtr->currentCmdMapBytes, + ((statsPtr->currentCmdMapBytes * 100.0) / statsPtr->currentByteCodeBytes), + statsPtr->currentCmdMapBytes / numCurrentByteCodes); + + /* + * Detailed literal statistics. + */ + + fprintf(stdout, "\nLiteral string sizes:\n"); + fprintf(stdout, " Up to length Percentage\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]; + fprintf(stdout, " %10d %8.0f%%\n", + decadeHigh, (sum * 100.0) / statsPtr->numLiteralsCreated); + } + + litTableStats = TclLiteralStats(globalTablePtr); + fprintf(stdout, "\nCurrent literal table statistics:\n%s\n", + litTableStats); + ckfree((char *) litTableStats); + + /* + * Source and ByteCode size distributions. + */ + + fprintf(stdout, "\nSource sizes:\n"); + fprintf(stdout, " Up to size Percentage\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]; + fprintf(stdout, " %10d %8.0f%%\n", + decadeHigh, (sum * 100.0) / statsPtr->numCompilations); + } + + fprintf(stdout, "\nByteCode sizes:\n"); + fprintf(stdout, " Up to size Percentage\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]; + fprintf(stdout, " %10d %8.0f%%\n", + decadeHigh, (sum * 100.0) / statsPtr->numCompilations); + } + + fprintf(stdout, "\nByteCode longevity (excludes current ByteCodes):\n"); + fprintf(stdout, " Up to ms Percentage\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 ((tclSourceCount[i] > 0) && (tclByteCodeCount[i] > 0)) { + if (statsPtr->lifetimeCount[i] > 0) { maxSizeDecade = i; break; } - } - - fprintf(stdout, "\nNumber of compilations %ld\n", - tclNumCompilations); - fprintf(stdout, "Number of executions %ld\n", - numExecutions); - fprintf(stdout, "Average executions/compilation %.0f\n", - ((float) numExecutions/tclNumCompilations)); - - fprintf(stdout, "\nInstructions executed %.0f\n", - total); - fprintf(stdout, "Average instructions/compile %.0f\n", - total/tclNumCompilations); - fprintf(stdout, "Average instructions/execution %.0f\n", - total/numExecutions); - - fprintf(stdout, "\nTotal source bytes %.6g\n", - tclTotalSourceBytes); - fprintf(stdout, "Total code bytes %.6g\n", - tclTotalCodeBytes); - fprintf(stdout, "Average code/compilation %.0f\n", - tclTotalCodeBytes/tclNumCompilations); - fprintf(stdout, "Average code/source %.2f\n", - tclTotalCodeBytes/tclTotalSourceBytes); - fprintf(stdout, "Current source bytes %.6g\n", - tclCurrentSourceBytes); - fprintf(stdout, "Current code bytes %.6g\n", - tclCurrentCodeBytes); - fprintf(stdout, "Current code/source %.2f\n", - tclCurrentCodeBytes/tclCurrentSourceBytes); - - fprintf(stdout, "\nTotal objects allocated %ld\n", - tclObjsAlloced); - fprintf(stdout, "Total objects freed %ld\n", - tclObjsFreed); - fprintf(stdout, "Current objects: %ld\n", - (tclObjsAlloced - tclObjsFreed)); - - fprintf(stdout, "\nBreakdown of code byte requirements:\n"); - fprintf(stdout, " Total bytes Pct of Avg per\n"); - fprintf(stdout, " all code compile\n"); - fprintf(stdout, "Total code %12.6g 100%% %8.2f\n", - tclTotalCodeBytes, tclTotalCodeBytes/tclNumCompilations); - fprintf(stdout, "Header %12.6g %8.2f%% %8.2f\n", - totalHeaderBytes, - ((totalHeaderBytes * 100.0) / tclTotalCodeBytes), - totalHeaderBytes/tclNumCompilations); - fprintf(stdout, "Instructions %12.6g %8.2f%% %8.2f\n", - tclTotalInstBytes, - ((tclTotalInstBytes * 100.0) / tclTotalCodeBytes), - tclTotalInstBytes/tclNumCompilations); - fprintf(stdout, "Objects %12.6g %8.2f%% %8.2f\n", - tclTotalObjBytes, - ((tclTotalObjBytes * 100.0) / tclTotalCodeBytes), - tclTotalObjBytes/tclNumCompilations); - fprintf(stdout, "Exception table %12.6g %8.2f%% %8.2f\n", - tclTotalExceptBytes, - ((tclTotalExceptBytes * 100.0) / tclTotalCodeBytes), - tclTotalExceptBytes/tclNumCompilations); - fprintf(stdout, "Auxiliary data %12.6g %8.2f%% %8.2f\n", - tclTotalAuxBytes, - ((tclTotalAuxBytes * 100.0) / tclTotalCodeBytes), - tclTotalAuxBytes/tclNumCompilations); - fprintf(stdout, "Command map %12.6g %8.2f%% %8.2f\n", - tclTotalCmdMapBytes, - ((tclTotalCmdMapBytes * 100.0) / tclTotalCodeBytes), - tclTotalCmdMapBytes/tclNumCompilations); - - fprintf(stdout, "\nSource and ByteCode size distributions:\n"); - fprintf(stdout, " binary decade source code\n"); - for (i = 0; i <= maxSizeDecade; i++) { - int decadeLow, decadeHigh; - - if (i == 0) { - decadeLow = 0; - } else { - decadeLow = 1 << i; - } + } + sum = 0; + for (i = minSizeDecade; i <= maxSizeDecade; i++) { decadeHigh = (1 << (i+1)) - 1; - fprintf(stdout, " %6d -%6d %6d %6d\n", - decadeLow, decadeHigh, - tclSourceCount[i], tclByteCodeCount[i]); + sum += statsPtr->lifetimeCount[i]; + fprintf(stdout, " %12.3f %8.0f%%\n", + decadeHigh / 1000.0, + (sum * 100.0) / statsPtr->numByteCodesFreed); } + /* + * Instruction counts. + */ + fprintf(stdout, "\nInstruction counts:\n"); - for (i = 0; i < 256; i++) { - if (instructionCount[i]) { - fprintf(stdout, "%20s %8d %6.2f%%\n", - opName[i], instructionCount[i], - (instructionCount[i] * 100.0)/total); + for (i = 0; i <= LAST_INST_OPCODE; i++) { + if (statsPtr->instructionCount[i]) { + fprintf(stdout, "%20s %8ld %6.1f%%\n", + instructionTable[i].name, + statsPtr->instructionCount[i], + (statsPtr->instructionCount[i]*100.0) / numInstructions); + } + } + + fprintf(stdout, "\nInstructions NEVER executed:\n"); + for (i = 0; i <= LAST_INST_OPCODE; i++) { + if (statsPtr->instructionCount[i] == 0) { + fprintf(stdout, "%20s\n", + instructionTable[i].name); } } #ifdef TCL_MEM_DEBUG fprintf(stdout, "\nHeap Statistics:\n"); TclDumpMemoryInfo(stdout); -#endif /* TCL_MEM_DEBUG */ - +#endif + fprintf(stdout, "\n----------------------------------------------------------------\n"); return TCL_OK; } #endif /* TCL_COMPILE_STATS */ /* @@ -4674,16 +4848,77 @@ resPtr = (ResolvedCmdName *) objPtr->internalRep.otherValuePtr; if (resPtr != NULL) { cmdPtr = resPtr->cmdPtr; } } - - if (cmdPtr == NULL) { - return (Tcl_Command) NULL; - } return (Tcl_Command) cmdPtr; } + +/* + *---------------------------------------------------------------------- + * + * 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 + * TclExecuteByteCode has a chance to recognize that it was deleted. + * + *---------------------------------------------------------------------- + */ + +void +TclSetCmdNameObj(interp, objPtr, cmdPtr) + 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; + Tcl_ObjType *oldTypePtr = objPtr->typePtr; + register Namespace *currNsPtr; + + if (oldTypePtr == &tclCmdNameType) { + return; + } + + /* + * Get the current namespace. + */ + + if (iPtr->varFramePtr != NULL) { + currNsPtr = iPtr->varFramePtr->nsPtr; + } else { + currNsPtr = iPtr->globalNsPtr; + } + + cmdPtr->refCount++; + resPtr = (ResolvedCmdName *) ckalloc(sizeof(ResolvedCmdName)); + resPtr->cmdPtr = cmdPtr; + resPtr->refNsPtr = currNsPtr; + resPtr->refNsId = currNsPtr->nsId; + resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch; + resPtr->cmdEpoch = cmdPtr->cmdEpoch; + resPtr->refCount = 1; + + if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) { + oldTypePtr->freeIntRepProc(objPtr); + } + objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) resPtr; + objPtr->internalRep.twoPtrValue.ptr2 = NULL; + objPtr->typePtr = &tclCmdNameType; +} /* *---------------------------------------------------------------------- * * FreeCmdNameInternalRep -- @@ -4806,11 +5041,11 @@ * Get "objPtr"s string representation. Make it up-to-date if necessary. */ name = objPtr->bytes; if (name == NULL) { - name = Tcl_GetStringFromObj(objPtr, (int *) NULL); + name = Tcl_GetString(objPtr); } /* * Find the Command structure, if any, that describes the command called * "name". Build a ResolvedCmdName that holds a cached pointer to this @@ -4860,38 +5095,10 @@ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) resPtr; objPtr->internalRep.twoPtrValue.ptr2 = NULL; objPtr->typePtr = &tclCmdNameType; return TCL_OK; } - -/* - *---------------------------------------------------------------------- - * - * UpdateStringOfCmdName -- - * - * Update the string representation for an cmdName object. - * - * Results: - * None. - * - * Side effects: - * Generates a panic. - * - *---------------------------------------------------------------------- - */ - -static void -UpdateStringOfCmdName(objPtr) - Tcl_Obj *objPtr; /* CmdName obj to update string rep. */ -{ - /* - * This procedure is never invoked since the internal representation of - * a cmdName object is never modified. - */ - - panic("UpdateStringOfCmdName should never be invoked"); -} #ifdef TCL_COMPILE_DEBUG /* *---------------------------------------------------------------------- * @@ -4916,14 +5123,14 @@ static char * StringForResultCode(result) int result; /* The Tcl result code for which to * generate a string. */ { - static char buf[20]; + 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 */ Index: generic/tclFCmd.c ================================================================== --- generic/tclFCmd.c +++ generic/tclFCmd.c @@ -2,16 +2,16 @@ * tclFCmd.c * * This file implements the generic portion of file manipulation * subcommands of the "file" command. * - * Copyright (c) 1996-1997 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclFCmd.c 1.17 97/05/14 13:23:13 + * RCS: @(#) $Id: tclFCmd.c,v 1.1.2.2 1998/09/24 23:58:49 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" @@ -139,16 +139,16 @@ } result = TCL_OK; /* - * Call stat() 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. + * Call TclpStat() 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 ((stat(target, &statBuf) != 0) || !S_ISDIR(statBuf.st_mode)) { + if ((TclpStat(target, &statBuf) != 0) || !S_ISDIR(statBuf.st_mode)) { if ((argc - i) > 2) { errno = ENOTDIR; Tcl_PosixError(interp); Tcl_AppendResult(interp, "error ", ((copyFlag) ? "copying" : "renaming"), ": target \"", @@ -251,15 +251,16 @@ } for (j = 0; j < pargc; j++) { char *target = Tcl_JoinPath(j + 1, pargv, &targetBuffer); /* - * Call stat() so that if target is a symlink that points to a - * directory we will create subdirectories in that directory. + * Call TclpStat() so that if target is a symlink that points + * to a directory we will create subdirectories in that + * directory. */ - if (stat(target, &statBuf) == 0) { + if (TclpStat(target, &statBuf) == 0) { if (!S_ISDIR(statBuf.st_mode)) { errno = EEXIST; errfile = target; goto done; } @@ -347,11 +348,11 @@ /* * Call lstat() to get info so can delete symbolic link itself. */ - if (lstat(name, &statBuf) != 0) { + if (TclpLstat(name, &statBuf) != 0) { /* * Trying to delete a file that does not exist is not * considered an error, just a no-op */ @@ -451,15 +452,15 @@ * use lstat(). If target is a link, we also want to replace the * link and not the file it points to, so we also use lstat() on the * target. */ - if (lstat(sourceName, &sourceStatBuf) != 0) { + if (TclpLstat(sourceName, &sourceStatBuf) != 0) { errfile = source; goto done; } - if (lstat(targetName, &targetStatBuf) != 0) { + if (TclpLstat(targetName, &targetStatBuf) != 0) { if (errno != ENOENT) { errfile = target; goto done; } } else { @@ -603,12 +604,12 @@ * 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 - * interp->result. + * options. If an error occurred, an error message is left in the + * interp's result. * * Side effects: * None. * *--------------------------------------------------------------------------- @@ -617,11 +618,11 @@ static int FileForceOption(interp, argc, argv, forcePtr) Tcl_Interp *interp; /* Interp, for error return. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. First command line - option, if it exists, begins at */ + * 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; @@ -748,68 +749,93 @@ TclFileAttrsCmd(interp, objc, objv) Tcl_Interp *interp; /* The interpreter for error reporting. */ int objc; /* Number of command line arguments. */ Tcl_Obj *CONST objv[]; /* The command line objects. */ { - Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); - char *fileName; - int length, index; - Tcl_Obj *listObjPtr; - Tcl_Obj *elementObjPtr; - Tcl_DString buffer; - - if ((objc > 2) && ((objc % 2) == 0)) { - Tcl_AppendStringsToObj(resultPtr, - "wrong # args: must be \"file attributes name ?option? ?value? ?option value? ...\"", - (char *) NULL); - return TCL_ERROR; - } - - fileName = Tcl_GetStringFromObj(objv[0], &length); - if (Tcl_TranslateFileName(interp, fileName, &buffer) == NULL) { - return TCL_ERROR; - } - fileName = Tcl_DStringValue(&buffer); - - if (objc == 1) { - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - - for (index = 0; tclpFileAttrStrings[index] != NULL; index++) { - elementObjPtr = Tcl_NewStringObj(tclpFileAttrStrings[index], -1); - Tcl_ListObjAppendElement(interp, listObjPtr, elementObjPtr); - if ((*tclpFileAttrProcs[index].getProc)(interp, index, fileName, - &elementObjPtr) != TCL_OK) { - Tcl_DecrRefCount(listObjPtr); - return TCL_ERROR; - } - Tcl_ListObjAppendElement(interp, listObjPtr, elementObjPtr); - } - Tcl_SetObjResult(interp, listObjPtr); - } else if (objc == 2) { - if (Tcl_GetIndexFromObj(interp, objv[1], tclpFileAttrStrings, "option", - 0, &index) != TCL_OK) { - return TCL_ERROR; - } - if ((*tclpFileAttrProcs[index].getProc)(interp, index, fileName, - &elementObjPtr) != TCL_OK) { - return TCL_ERROR; - } - Tcl_SetObjResult(interp, elementObjPtr); - } else { - int i; - - for (i = 1; i < objc ; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], tclpFileAttrStrings, "option", - 0, &index) != TCL_OK) { - return TCL_ERROR; - } - if ((*tclpFileAttrProcs[index].setProc)(interp, index, fileName, - objv[i + 1]) != TCL_OK) { - return TCL_ERROR; - } - } - } - - Tcl_DStringFree(&buffer); - - return TCL_OK; + char *fileName; + int result; + Tcl_DString buffer; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, + "name ?option? ?value? ?option value ...?"); + return TCL_ERROR; + } + + fileName = Tcl_GetString(objv[2]); + fileName = Tcl_TranslateFileName(interp, fileName, &buffer); + if (fileName == NULL) { + return TCL_ERROR; + } + + objc -= 3; + objv += 3; + result = TCL_ERROR; + + if (objc == 0) { + /* + * Get all attributes. + */ + + int index; + Tcl_Obj *listPtr, *objPtr; + + listPtr = Tcl_NewListObj(0, NULL); + for (index = 0; tclpFileAttrStrings[index] != NULL; index++) { + objPtr = Tcl_NewStringObj(tclpFileAttrStrings[index], -1); + Tcl_ListObjAppendElement(interp, listPtr, objPtr); + + if ((*tclpFileAttrProcs[index].getProc)(interp, index, fileName, + &objPtr) != TCL_OK) { + Tcl_DecrRefCount(listPtr); + goto end; + } + Tcl_ListObjAppendElement(interp, listPtr, objPtr); + } + Tcl_SetObjResult(interp, listPtr); + } else if (objc == 1) { + /* + * Get one attribute. + */ + + int index; + Tcl_Obj *objPtr; + + if (Tcl_GetIndexFromObj(interp, objv[0], tclpFileAttrStrings, + "option", 0, &index) != TCL_OK) { + goto end; + } + if ((*tclpFileAttrProcs[index].getProc)(interp, index, fileName, + &objPtr) != TCL_OK) { + goto end; + } + Tcl_SetObjResult(interp, objPtr); + } else { + /* + * Set option/value pairs. + */ + + int i, index; + + for (i = 0; i < objc ; i += 2) { + if (Tcl_GetIndexFromObj(interp, objv[i], tclpFileAttrStrings, + "option", 0, &index) != TCL_OK) { + goto end; + } + if (i + 1 == objc) { + Tcl_AppendResult(interp, "value for \"", + Tcl_GetString(objv[i]), "\" missing", + (char *) NULL); + goto end; + } + if ((*tclpFileAttrProcs[index].setProc)(interp, index, fileName, + objv[i + 1]) != TCL_OK) { + goto end; + } + } + } + result = TCL_OK; + + end: + Tcl_DStringFree(&buffer); + return result; } Index: generic/tclFileName.c ================================================================== --- generic/tclFileName.c +++ generic/tclFileName.c @@ -2,36 +2,30 @@ * tclFileName.c -- * * This file contains routines for converting file names betwen * native and network form. * - * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclFileName.c 1.32 97/08/19 18:44:03 + * RCS: @(#) $Id: tclFileName.c,v 1.1.2.12 1999/04/05 23:14:26 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclRegexp.h" -/* - * This variable indicates whether the cleanup procedure has been - * registered for this file yet. - */ - -static int initialized = 0; - /* * The following regular expression matches the root portion of a Windows * absolute or volume relative path. It will match both UNC and drive relative * paths. */ -#define WIN_ROOT_PATTERN "^(([a-zA-Z]:)|[/\\][/\\]+([^/\\]+)[/\\]+([^/\\]+)|([/\\]))([/\\])*" +#define WIN_ROOT_PATTERN "^(([a-zA-Z]:)|[/\\\\][/\\\\]+([^/\\\\]+)[/\\\\]+([^/\\\\]+)|([/\\\\]))([/\\\\])*" /* * The following regular expression matches the root portion of a Macintosh * absolute path. It will match degenerate Unix-style paths, tilde paths, * Unix-style paths, and Mac paths. @@ -42,12 +36,17 @@ /* * The following variables are used to hold precompiled regular expressions * for use in filename matching. */ -static regexp *winRootPatternPtr = NULL; -static regexp *macRootPatternPtr = NULL; +typedef struct ThreadSpecificData { + int initialized; + Tcl_Obj *winRootPatternPtr; + Tcl_Obj *macRootPatternPtr; +} ThreadSpecificData; + +static Tcl_ThreadDataKey dataKey; /* * The following variable is set in the TclPlatformInit call to one * of: TCL_PLATFORM_UNIX, TCL_PLATFORM_MAC, or TCL_PLATFORM_WINDOWS. */ @@ -57,22 +56,51 @@ /* * Prototypes for local procedures defined in this file: */ static char * DoTildeSubst _ANSI_ARGS_((Tcl_Interp *interp, - char *user, Tcl_DString *resultPtr)); -static char * ExtractWinRoot _ANSI_ARGS_((char *path, + CONST char *user, Tcl_DString *resultPtr)); +static CONST char * ExtractWinRoot _ANSI_ARGS_((CONST char *path, Tcl_DString *resultPtr, int offset)); static void FileNameCleanup _ANSI_ARGS_((ClientData clientData)); +static void FileNameInit _ANSI_ARGS_((void)); static int SkipToChar _ANSI_ARGS_((char **stringPtr, char *match)); -static char * SplitMacPath _ANSI_ARGS_((char *path, +static char * SplitMacPath _ANSI_ARGS_((CONST char *path, + Tcl_DString *bufPtr)); +static char * SplitWinPath _ANSI_ARGS_((CONST char *path, Tcl_DString *bufPtr)); -static char * SplitWinPath _ANSI_ARGS_((char *path, +static char * SplitUnixPath _ANSI_ARGS_((CONST char *path, Tcl_DString *bufPtr)); -static char * SplitUnixPath _ANSI_ARGS_((char *path, - Tcl_DString *bufPtr)); + +/* + *---------------------------------------------------------------------- + * + * FileNameInit -- + * + * This procedure initializes the patterns used by this module. + * + * Results: + * None. + * + * Side effects: + * Compiles the regular expressions. + * + *---------------------------------------------------------------------- + */ + +static void +FileNameInit() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + if (!tsdPtr->initialized) { + tsdPtr->initialized = 1; + tsdPtr->winRootPatternPtr = Tcl_NewStringObj(WIN_ROOT_PATTERN, -1); + tsdPtr->macRootPatternPtr = Tcl_NewStringObj(MAC_ROOT_PATTERN, -1); + Tcl_CreateThreadExitHandler(FileNameCleanup, NULL); + } +} /* *---------------------------------------------------------------------- * * FileNameCleanup -- @@ -91,19 +119,14 @@ static void FileNameCleanup(clientData) ClientData clientData; /* Not used. */ { - if (winRootPatternPtr != NULL) { - ckfree((char *)winRootPatternPtr); - winRootPatternPtr = (regexp *) NULL; - } - if (macRootPatternPtr != NULL) { - ckfree((char *)macRootPatternPtr); - macRootPatternPtr = (regexp *) NULL; - } - initialized = 0; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + Tcl_DecrRefCount(tsdPtr->winRootPatternPtr); + Tcl_DecrRefCount(tsdPtr->macRootPatternPtr); + tsdPtr->initialized = 0; } /* *---------------------------------------------------------------------- * @@ -122,59 +145,63 @@ * Modifies the specified Tcl_DString. * *---------------------------------------------------------------------- */ -static char * +static CONST char * ExtractWinRoot(path, resultPtr, offset) - char *path; /* Path to parse. */ + CONST char *path; /* Path to parse. */ Tcl_DString *resultPtr; /* Buffer to hold result. */ int offset; /* Offset in buffer where result should be * stored. */ { int length; + Tcl_RegExp re; + char *dummy, *tail, *drive, *hostStart, *hostEnd, *shareStart, + *shareEnd, *lastSlash; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Initialize the path name parser for Windows path names. */ - if (winRootPatternPtr == NULL) { - winRootPatternPtr = TclRegComp(WIN_ROOT_PATTERN); - if (!initialized) { - Tcl_CreateExitHandler(FileNameCleanup, NULL); - initialized = 1; - } - } + FileNameInit(); + + re = Tcl_GetRegExpFromObj(NULL, tsdPtr->winRootPatternPtr, REG_ADVANCED); /* * Match the root portion of a Windows path name. */ - if (!TclRegExec(winRootPatternPtr, path, path)) { + if (!Tcl_RegExpExec(NULL, re, path, path)) { return path; } Tcl_DStringSetLength(resultPtr, offset); - if (winRootPatternPtr->startp[2] != NULL) { - Tcl_DStringAppend(resultPtr, winRootPatternPtr->startp[2], 2); - if (winRootPatternPtr->startp[6] != NULL) { + Tcl_RegExpRange(re, 0, &dummy, &tail); + Tcl_RegExpRange(re, 2, &drive, &dummy); + Tcl_RegExpRange(re, 3, &hostStart, &hostEnd); + Tcl_RegExpRange(re, 4, &shareStart, &shareEnd); + Tcl_RegExpRange(re, 6, &lastSlash, &dummy); + + if (drive != NULL) { + Tcl_DStringAppend(resultPtr, drive, 2); + if (lastSlash != NULL) { Tcl_DStringAppend(resultPtr, "/", 1); } - } else if (winRootPatternPtr->startp[4] != NULL) { + } else if (shareStart != NULL) { Tcl_DStringAppend(resultPtr, "//", 2); - length = winRootPatternPtr->endp[3] - - winRootPatternPtr->startp[3]; - Tcl_DStringAppend(resultPtr, winRootPatternPtr->startp[3], length); + length = hostEnd - hostStart; + Tcl_DStringAppend(resultPtr, hostStart, length); Tcl_DStringAppend(resultPtr, "/", 1); - length = winRootPatternPtr->endp[4] - - winRootPatternPtr->startp[4]; - Tcl_DStringAppend(resultPtr, winRootPatternPtr->startp[4], length); + length = shareEnd - shareStart; + Tcl_DStringAppend(resultPtr, shareStart, length); } else { Tcl_DStringAppend(resultPtr, "/", 1); } - return winRootPatternPtr->endp[0]; + return tail; } /* *---------------------------------------------------------------------- * @@ -195,11 +222,13 @@ Tcl_PathType Tcl_GetPathType(path) char *path; { + ThreadSpecificData *tsdPtr; Tcl_PathType type = TCL_PATH_ABSOLUTE; + Tcl_RegExp re; switch (tclPlatform) { case TCL_PLATFORM_UNIX: /* * Paths that begin with / or ~ are absolute. @@ -212,49 +241,55 @@ case TCL_PLATFORM_MAC: if (path[0] == ':') { type = TCL_PATH_RELATIVE; } else if (path[0] != '~') { + tsdPtr = TCL_TSD_INIT(&dataKey); /* * Since we have eliminated the easy cases, use the * root pattern to look for the other types. */ - if (!macRootPatternPtr) { - macRootPatternPtr = TclRegComp(MAC_ROOT_PATTERN); - if (!initialized) { - Tcl_CreateExitHandler(FileNameCleanup, NULL); - initialized = 1; - } - } - if (!TclRegExec(macRootPatternPtr, path, path) - || (macRootPatternPtr->startp[2] != NULL)) { + FileNameInit(); + re = Tcl_GetRegExpFromObj(NULL, tsdPtr->macRootPatternPtr, + REG_ADVANCED); + + if (!Tcl_RegExpExec(NULL, re, path, path)) { type = TCL_PATH_RELATIVE; + } else { + char *unixRoot, *dummy; + + Tcl_RegExpRange(re, 2, &unixRoot, &dummy); + if (unixRoot) { + type = TCL_PATH_RELATIVE; + } } } break; case TCL_PLATFORM_WINDOWS: if (path[0] != '~') { + tsdPtr = TCL_TSD_INIT(&dataKey); /* * Since we have eliminated the easy cases, check for * drive relative paths using the regular expression. */ - if (!winRootPatternPtr) { - winRootPatternPtr = TclRegComp(WIN_ROOT_PATTERN); - if (!initialized) { - Tcl_CreateExitHandler(FileNameCleanup, NULL); - initialized = 1; - } - } - if (TclRegExec(winRootPatternPtr, path, path)) { - if (winRootPatternPtr->startp[5] - || (winRootPatternPtr->startp[2] - && !(winRootPatternPtr->startp[6]))) { + FileNameInit(); + re = Tcl_GetRegExpFromObj(NULL, tsdPtr->winRootPatternPtr, + REG_ADVANCED); + + if (Tcl_RegExpExec(NULL, re, path, path)) { + char *drive, *dummy, *unixRoot, *lastSlash; + + Tcl_RegExpRange(re, 2, &drive, &dummy); + Tcl_RegExpRange(re, 5, &unixRoot, &dummy); + Tcl_RegExpRange(re, 6, &lastSlash, &dummy); + + if (unixRoot || (drive && !lastSlash)) { type = TCL_PATH_VOLUME_RELATIVE; } } else { type = TCL_PATH_RELATIVE; } @@ -290,19 +325,20 @@ *---------------------------------------------------------------------- */ void Tcl_SplitPath(path, argcPtr, argvPtr) - char *path; /* Pointer to string containing a path. */ + 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. */ char ***argvPtr; /* Pointer to place to store pointer to array * of pointers to path elements. */ { int i, size; char *p; Tcl_DString buffer; + Tcl_DStringInit(&buffer); /* * Perform platform specific splitting. These routines will leave the * result in the specified buffer. Individual elements are terminated @@ -383,15 +419,15 @@ *---------------------------------------------------------------------- */ static char * SplitUnixPath(path, bufPtr) - char *path; /* Pointer to string containing a path. */ + CONST char *path; /* Pointer to string containing a path. */ Tcl_DString *bufPtr; /* Pointer to DString to use for the result. */ { int length; - char *p, *elementStart; + CONST char *p, *elementStart; /* * Deal with the root directory as a special case. */ @@ -445,15 +481,15 @@ *---------------------------------------------------------------------- */ static char * SplitWinPath(path, bufPtr) - char *path; /* Pointer to string containing a path. */ + CONST char *path; /* Pointer to string containing a path. */ Tcl_DString *bufPtr; /* Pointer to DString to use for the result. */ { int length; - char *p, *elementStart; + CONST char *p, *elementStart; p = ExtractWinRoot(path, bufPtr, 0); /* * Terminate the root portion, if we matched something. @@ -503,92 +539,102 @@ *---------------------------------------------------------------------- */ static char * SplitMacPath(path, bufPtr) - char *path; /* Pointer to string containing a path. */ + CONST char *path; /* Pointer to string containing a path. */ Tcl_DString *bufPtr; /* Pointer to DString to use for the result. */ { int isMac = 0; /* 1 if is Mac-style, 0 if Unix-style path. */ int i, length; - char *p, *elementStart; + CONST char *p, *elementStart; + Tcl_RegExp re; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Initialize the path name parser for Macintosh path names. */ - if (macRootPatternPtr == NULL) { - macRootPatternPtr = TclRegComp(MAC_ROOT_PATTERN); - if (!initialized) { - Tcl_CreateExitHandler(FileNameCleanup, NULL); - initialized = 1; - } - } + FileNameInit(); /* * Match the root portion of a Mac path name. */ i = 0; /* Needed only to prevent gcc warnings. */ - if (TclRegExec(macRootPatternPtr, path, path) == 1) { + + re = Tcl_GetRegExpFromObj(NULL, tsdPtr->macRootPatternPtr, REG_ADVANCED); + + if (Tcl_RegExpExec(NULL, re, path, path) == 1) { + char *start, *end; + /* * Treat degenerate absolute paths like / and /../.. as * Mac relative file names for lack of anything else to do. */ - if (macRootPatternPtr->startp[2] != NULL) { + Tcl_RegExpRange(re, 2, &start, &end); + if (start) { Tcl_DStringAppend(bufPtr, ":", 1); - Tcl_DStringAppend(bufPtr, path, macRootPatternPtr->endp[0] - - macRootPatternPtr->startp[0] + 1); + Tcl_RegExpRange(re, 0, &start, &end); + Tcl_DStringAppend(bufPtr, path, end - start + 1); return Tcl_DStringValue(bufPtr); } - if (macRootPatternPtr->startp[5] != NULL) { - + Tcl_RegExpRange(re, 5, &start, &end); + if (start) { /* * Unix-style tilde prefixed paths. */ isMac = 0; i = 5; - } else if (macRootPatternPtr->startp[7] != NULL) { - - /* - * Mac-style tilde prefixed paths. - */ - - isMac = 1; - i = 7; - } else if (macRootPatternPtr->startp[10] != NULL) { - - /* - * Normal Unix style paths. - */ - - isMac = 0; - i = 10; - } else if (macRootPatternPtr->startp[12] != NULL) { - - /* - * Normal Mac style paths. - */ - - isMac = 1; - i = 12; - } - - length = macRootPatternPtr->endp[i] - - macRootPatternPtr->startp[i]; + } else { + Tcl_RegExpRange(re, 7, &start, &end); + if (start) { + /* + * Mac-style tilde prefixed paths. + */ + + isMac = 1; + i = 7; + } else { + Tcl_RegExpRange(re, 10, &start, &end); + if (start) { + + /* + * Normal Unix style paths. + */ + + isMac = 0; + i = 10; + } else { + Tcl_RegExpRange(re, 12, &start, &end); + if (start) { + + /* + * Normal Mac style paths. + */ + + isMac = 1; + i = 12; + } + } + } + } + + Tcl_RegExpRange(re, i, &start, &end); + length = end - start; /* * Append the element and terminate it with a : and a null. Note that * we are forcing the DString to contain an extra null at the end. */ - Tcl_DStringAppend(bufPtr, macRootPatternPtr->startp[i], length); + Tcl_DStringAppend(bufPtr, start, length); Tcl_DStringAppend(bufPtr, ":", 2); - p = macRootPatternPtr->endp[i]; + p = end; } else { isMac = (strchr(path, ':') != NULL); p = path; } @@ -688,11 +734,12 @@ char **argv; Tcl_DString *resultPtr; /* Pointer to previously initialized DString. */ { int oldLength, length, i, needsSep; Tcl_DString buffer; - char *p, c, *dest; + char c, *dest; + CONST char *p; Tcl_DStringInit(&buffer); oldLength = Tcl_DStringLength(resultPtr); switch (tclPlatform) { @@ -882,44 +929,45 @@ Tcl_DStringFree(&buffer); 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. + * 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 result is a pointer to a static string containing - * the new name. If there was an error in processing the - * name, then an error message is left in interp->result - * and the return value is NULL. The result will be stored - * in bufferPtr; the caller must call Tcl_DStringFree(bufferPtr) - * to free the name if the return value was not NULL. + * 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: - * Information may be left in bufferPtr. + * None. * *---------------------------------------------------------------------- */ char * Tcl_TranslateFileName(interp, name, bufferPtr) Tcl_Interp *interp; /* Interpreter in which to store error * message (if necessary). */ - 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; /* May be used to hold result. Must not hold - * anything at the time of the call, and need - * not even be initialized. */ + 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. */ { register char *p; /* * Handle tilde substitutions, if needed. @@ -931,12 +979,12 @@ Tcl_DString temp; Tcl_SplitPath(name, &argc, &argv); /* - * Strip the trailing ':' off of a Mac path - * before passing the user name to DoTildeSubst. + * Strip the trailing ':' off of a Mac path before passing the user + * name to DoTildeSubst. */ if (tclPlatform == TCL_PLATFORM_MAC) { length = strlen(argv[0]); argv[0][length-1] = '\0'; @@ -1029,19 +1077,16 @@ && (lastSep > p)) { p = NULL; } /* - * Back up to the first period in a series of contiguous dots. - * This is needed so foo..o will be split on the first dot. + * 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. */ - if (p != NULL) { - while ((p > name) && *(p-1) == '.') { - p--; - } - } return p; } /* *---------------------------------------------------------------------- @@ -1052,13 +1097,14 @@ * 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 interp->result - * and the return value is NULL. On success, the results are appended - * to resultPtr, and the contents of resultPtr are returned. + * 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. * *---------------------------------------------------------------------- @@ -1066,33 +1112,33 @@ static char * DoTildeSubst(interp, user, resultPtr) Tcl_Interp *interp; /* Interpreter in which to store error * message (if necessary). */ - char *user; /* Name of user whose home directory should be + CONST char *user; /* Name of user whose home directory should be * substituted, or "" for current user. */ - Tcl_DString *resultPtr; /* May be used to hold result. Must not hold - * anything at the time of the call, and need - * not even be initialized. */ + Tcl_DString *resultPtr; /* Initialized DString filled with name + * after tilde substitution. */ { char *dir; if (*user == '\0') { - dir = TclGetEnv("HOME"); + Tcl_DString dirString; + + dir = TclGetEnv("HOME", &dirString); if (dir == NULL) { if (interp) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "couldn't find HOME environment ", "variable to expand path", (char *) NULL); } return NULL; } Tcl_JoinPath(1, &dir, resultPtr); + Tcl_DStringFree(&dirString); } else { - - /* lint, TclGetuserHome() always NULL under windows. */ - if (TclGetUserHome(user, resultPtr) == NULL) { + if (TclpGetUserHome(user, resultPtr) == NULL) { if (interp) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "user \"", user, "\" doesn't exist", (char *) NULL); } @@ -1103,11 +1149,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_GlobCmd -- + * Tcl_GlobObjCmd -- * * This procedure is invoked to process the "glob" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -1119,149 +1165,193 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_GlobCmd(dummy, interp, argc, argv) - ClientData dummy; /* Not used. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ -{ - int i, noComplain, firstArg; - char c; - int result = TCL_OK; - Tcl_DString buffer; - char *separators, *head, *tail; - - noComplain = 0; - for (firstArg = 1; (firstArg < argc) && (argv[firstArg][0] == '-'); - firstArg++) { - if (strcmp(argv[firstArg], "-nocomplain") == 0) { - noComplain = 1; - } else if (strcmp(argv[firstArg], "--") == 0) { - firstArg++; - break; - } else { - Tcl_AppendResult(interp, "bad switch \"", argv[firstArg], - "\": must be -nocomplain or --", (char *) NULL); - return TCL_ERROR; - } - } - if (firstArg >= argc) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ?switches? name ?name ...?\"", (char *) NULL); - return TCL_ERROR; - } - - Tcl_DStringInit(&buffer); - separators = NULL; /* Needed only to prevent gcc warnings. */ - for (i = firstArg; i < argc; i++) { - switch (tclPlatform) { +Tcl_GlobObjCmd(dummy, interp, objc, objv) + ClientData dummy; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + int index, i, noComplain, skip, length; + char *string; + static char *options[] = {"-nocomplain", "--", NULL}; + enum options {GLOB_NOCOMPLAIN, GLOB_LAST}; + + noComplain = 0; + for (skip = 1; skip < objc; skip++) { + string = Tcl_GetString(objv[skip]); + if (string[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[skip], options, "switch", + TCL_EXACT, &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == GLOB_NOCOMPLAIN) { + noComplain = 1; + } else { + skip++; + break; + } + } + if (skip >= objc) { + Tcl_WrongNumArgs(interp, 1, objv, "?switches? name ?name ...?"); + return TCL_ERROR; + } + + for (i = skip; i < objc; i++) { + string = Tcl_GetString(objv[i]); + if (TclGlob(interp, string, noComplain) != TCL_OK) { + return TCL_ERROR; + } + } + if (noComplain == 0) { + Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length); + if (length == 0) { + char *sep = ""; + + Tcl_AppendResult(interp, "no files matched glob pattern", + (objc == 2) ? " \"" : "s \"", (char *) NULL); + for (i = skip; i < objc; i++) { + string = Tcl_GetString(objv[i]); + Tcl_AppendResult(interp, sep, string, (char *) NULL); + sep = " "; + } + Tcl_AppendResult(interp, "\"", (char *) NULL); + return TCL_ERROR; + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TclGlob -- + * + * This procedure prepares arguments for the TclDoGlob call. + * It sets the separator string based on the platform, performs + * tilde substitution, and calls TclDoGlob. + * + * 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 TclDoGlob) holds all of the file names + * given by the dir and rem arguments. After an error the + * result in interp will hold an error message. + * + * Side effects: + * The currentArgString is written to. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +TclGlob(interp, pattern, noComplain) + 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. */ + int noComplain; /* Flag to turn off storing error messages + * in interp. */ +{ + char *separators; + char *head, *tail; + char c; + int result; + Tcl_DString buffer; + + separators = NULL; /* lint. */ + switch (tclPlatform) { case TCL_PLATFORM_UNIX: separators = "/"; break; case TCL_PLATFORM_WINDOWS: separators = "/\\:"; break; case TCL_PLATFORM_MAC: - separators = (strchr(argv[i], ':') == NULL) ? "/" : ":"; - break; - } - - Tcl_DStringSetLength(&buffer, 0); - - /* - * Perform tilde substitution, if needed. - */ - - if (argv[i][0] == '~') { - char *p; - - /* - * Find the first path separator after the tilde. - */ - - for (tail = argv[i]; *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. Note that - * we don't allow special characters in the user name. - */ - - c = *tail; - *tail = '\0'; - p = strpbrk(argv[i]+1, "\\[]*?{}"); - if (p == NULL) { - head = DoTildeSubst(interp, argv[i]+1, &buffer); - } else { - if (!noComplain) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "globbing characters not ", - "supported in user names", (char *) NULL); - } - head = NULL; - } - *tail = c; - if (head == NULL) { - if (noComplain) { - Tcl_ResetResult(interp); - continue; - } else { - result = TCL_ERROR; - goto done; - } - } - if (head != Tcl_DStringValue(&buffer)) { - Tcl_DStringAppend(&buffer, head, -1); - } - } else { - tail = argv[i]; - } - - result = TclDoGlob(interp, separators, &buffer, tail); - if (result != TCL_OK) { + separators = (strchr(pattern, ':') == NULL) + ? "/" : ":"; + break; + } + + Tcl_DStringInit(&buffer); + + /* + * Perform tilde substitution, if needed. + */ + + if (pattern[0] == '~') { + char *p; + + /* + * Find the first path separator after the tilde. + */ + + for (tail = pattern; *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. Note that + * we don't allow special characters in the user name. + */ + + c = *tail; + *tail = '\0'; + p = strpbrk(pattern+1, "\\[]*?{}"); + if (p == NULL) { + head = DoTildeSubst(interp, pattern+1, &buffer); + } else { + if (!noComplain) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "globbing characters not ", + "supported in user names", (char *) NULL); + } + head = NULL; + } + *tail = c; + if (head == NULL) { if (noComplain) { /* * We should in fact pass down the nocomplain flag - * or save the interp result or use another mecanism + * or save the interp result or use another mechanism * so the interp result is not mangled on errors in that case. * but that would a bigger change than reasonable for a patch * release. * (see fileName.test 15.2-15.4 for expected behaviour) */ Tcl_ResetResult(interp); - result = TCL_OK; - continue; + return TCL_OK; } else { - goto done; - } - } - } - - if ((*interp->result == 0) && !noComplain) { - char *sep = ""; - - Tcl_AppendResult(interp, "no files matched glob pattern", - (argc == 2) ? " \"" : "s \"", (char *) NULL); - for (i = firstArg; i < argc; i++) { - Tcl_AppendResult(interp, sep, argv[i], (char *) NULL); - sep = " "; - } - Tcl_AppendResult(interp, "\"", (char *) NULL); - result = TCL_ERROR; - } -done: + return TCL_ERROR; + } + } + if (head != Tcl_DStringValue(&buffer)) { + Tcl_DStringAppend(&buffer, head, -1); + } + } else { + tail = pattern; + } + + result = TclDoGlob(interp, separators, &buffer, tail); Tcl_DStringFree(&buffer); + if (result != TCL_OK) { + if (noComplain) { + Tcl_ResetResult(interp); + return TCL_OK; + } + } return result; } /* *---------------------------------------------------------------------- @@ -1344,15 +1434,16 @@ * (e.g. unmatched brace). */ char *separators; /* String containing separator characters * that should be used to identify globbing * boundaries. */ Tcl_DString *headPtr; /* Completely expanded prefix. */ - char *tail; /* The unexpanded remainder of the path. */ + char *tail; /* The unexpanded remainder of the path. + * Must not be a pointer to a static string. */ { int baseLength, quoted, count; int result = TCL_OK; - char *p, *openBrace, *closeBrace, *name, *firstSpecialChar, savedChar; + char *name, *p, *openBrace, *closeBrace, *firstSpecialChar, savedChar; char lastChar = 0; int length = Tcl_DStringLength(headPtr); if (length > 0) { lastChar = Tcl_DStringValue(headPtr)[length-1]; @@ -1520,10 +1611,16 @@ * to check for special globbing characters in the current pattern. * We avoid modifying tail if p is pointing at the end of the string. */ if (*p != '\0') { + + /* + * Note that we are modifying the string in place. This won't work + * if the string is a static. + */ + savedChar = *p; *p = '\0'; firstSpecialChar = strpbrk(tail, "*[]?\\"); *p = savedChar; } else { @@ -1533,15 +1630,15 @@ if (firstSpecialChar != NULL) { /* * Look for matching files in the current directory. The * implementation of this function is platform specific, but may * recursively call TclDoGlob. For each file that matches, it will - * add the match onto the interp->result, or call TclDoGlob if there + * add the match onto the interp's result, or call TclDoGlob if there * are more characters to be processed. */ - return TclMatchFiles(interp, separators, headPtr, tail, p); + return TclpMatchFiles(interp, separators, headPtr, tail, p); } Tcl_DStringAppend(headPtr, tail, p-tail); if (*p != '\0') { return TclDoGlob(interp, separators, headPtr, p); } @@ -1551,25 +1648,27 @@ * characters in the tail, so now we can construct the path and verify * the existence of the file. */ switch (tclPlatform) { - case TCL_PLATFORM_MAC: + case TCL_PLATFORM_MAC: { if (strchr(Tcl_DStringValue(headPtr), ':') == NULL) { Tcl_DStringAppend(headPtr, ":", 1); } name = Tcl_DStringValue(headPtr); - if (access(name, F_OK) == 0) { + if (TclpAccess(name, F_OK) == 0) { if ((name[1] != '\0') && (strchr(name+1, ':') == NULL)) { - Tcl_AppendElement(interp, name+1); + Tcl_AppendElement(interp, name + 1); } else { Tcl_AppendElement(interp, name); } } break; + } case TCL_PLATFORM_WINDOWS: { int exists; + /* * We need to convert slashes to backslashes before checking * for the existence of the file. Once we are done, we need * to convert the slashes back. */ @@ -1587,11 +1686,12 @@ *p = '\\'; } } } name = Tcl_DStringValue(headPtr); - exists = (access(name, F_OK) == 0); + exists = (TclpAccess(name, F_OK) == 0); + for (p = name; *p != '\0'; p++) { if (*p == '\\') { *p = '/'; } } @@ -1598,22 +1698,23 @@ if (exists) { Tcl_AppendElement(interp, name); } break; } - case TCL_PLATFORM_UNIX: + case TCL_PLATFORM_UNIX: { if (Tcl_DStringLength(headPtr) == 0) { if ((*name == '\\' && name[1] == '/') || (*name == '/')) { Tcl_DStringAppend(headPtr, "/", 1); } else { Tcl_DStringAppend(headPtr, ".", 1); } } name = Tcl_DStringValue(headPtr); - if (access(name, F_OK) == 0) { + if (TclpAccess(name, F_OK) == 0) { Tcl_AppendElement(interp, name); } break; + } } return TCL_OK; } Index: generic/tclGet.c ================================================================== --- generic/tclGet.c +++ generic/tclGet.c @@ -4,16 +4,16 @@ * This file contains procedures 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-1995 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclGet.c 1.33 97/05/14 16:42:19 + * RCS: @(#) $Id: tclGet.c,v 1.1.2.2 1998/09/24 23:58:50 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" @@ -27,11 +27,11 @@ * * Results: * The return value is normally TCL_OK; in this case *intPtr * will be set to the integer value equivalent to string. If * string is improperly formed then TCL_ERROR is returned and - * an error message will be left in interp->result. + * an error message will be left in the interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -52,21 +52,21 @@ * to allow full-size unsigned numbers, but don't depend on strtoul * to handle sign characters; it won't in some implementations. */ errno = 0; - for (p = string; isspace(UCHAR(*p)); p++) { + for (p = string; isspace(UCHAR(*p)); p++) { /* INTL: ISO space. */ /* Empty loop body. */ } if (*p == '-') { p++; - i = -((long)strtoul(p, &end, 0)); + i = -((long)strtoul(p, &end, 0)); /* INTL: Tcl source. */ } else if (*p == '+') { p++; - i = strtoul(p, &end, 0); + i = strtoul(p, &end, 0); /* INTL: Tcl source. */ } else { - i = strtoul(p, &end, 0); + i = strtoul(p, &end, 0); /* INTL: Tcl source. */ } if (end == p) { badInteger: if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "expected integer but got \"", string, @@ -84,15 +84,15 @@ if ((errno == ERANGE) || (((long)(int) i) != i)) { if (interp != (Tcl_Interp *) NULL) { Tcl_SetResult(interp, "integer value too large to represent", TCL_STATIC); Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", - interp->result, (char *) NULL); + Tcl_GetStringResult(interp), (char *) NULL); } return TCL_ERROR; } - while ((*end != '\0') && isspace(UCHAR(*end))) { + while ((*end != '\0') && isspace(UCHAR(*end))) { /* INTL: ISO space. */ end++; } if (*end != 0) { goto badInteger; } @@ -111,21 +111,23 @@ * * Results: * The return value is normally TCL_OK; in this case *longPtr * will be set to the long integer value equivalent to string. If * string is improperly formed then TCL_ERROR is returned and - * an error message will be left in interp->result. + * an error message will be left in the interp's result if interp + * is non-NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclGetLong(interp, string, longPtr) - Tcl_Interp *interp; /* Interpreter used for error reporting. */ + Tcl_Interp *interp; /* Interpreter used for error reporting + * if not NULL. */ char *string; /* String containing a (possibly signed) * long integer in a form acceptable to * strtoul. */ long *longPtr; /* Place to store converted long result. */ { @@ -136,21 +138,21 @@ * Note: don't depend on strtoul to handle sign characters; it won't * in some implementations. */ errno = 0; - for (p = string; isspace(UCHAR(*p)); p++) { + for (p = string; isspace(UCHAR(*p)); p++) { /* INTL: ISO space. */ /* Empty loop body. */ } if (*p == '-') { p++; - i = -(int)strtoul(p, &end, 0); + i = -(int)strtoul(p, &end, 0); /* INTL: Tcl source. */ } else if (*p == '+') { p++; - i = strtoul(p, &end, 0); + i = strtoul(p, &end, 0); /* INTL: Tcl source. */ } else { - i = strtoul(p, &end, 0); + i = strtoul(p, &end, 0); /* INTL: Tcl source. */ } if (end == p) { badInteger: if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "expected integer but got \"", string, @@ -161,15 +163,15 @@ if (errno == ERANGE) { if (interp != (Tcl_Interp *) NULL) { Tcl_SetResult(interp, "integer value too large to represent", TCL_STATIC); Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", - interp->result, (char *) NULL); + Tcl_GetStringResult(interp), (char *) NULL); } return TCL_ERROR; } - while ((*end != '\0') && isspace(UCHAR(*end))) { + while ((*end != '\0') && isspace(UCHAR(*end))) { /* INTL: ISO space. */ end++; } if (*end != 0) { goto badInteger; } @@ -187,11 +189,11 @@ * * Results: * The return value is normally TCL_OK; in this case *doublePtr * will be set to the double-precision value equivalent to string. * If string is improperly formed then TCL_ERROR is returned and - * an error message will be left in interp->result. + * an error message will be left in the interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -206,11 +208,11 @@ { char *end; double d; errno = 0; - d = strtod(string, &end); + d = strtod(string, &end); /* INTL: Tcl source. */ if (end == string) { badDouble: if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "expected floating-point number but got \"", @@ -218,26 +220,15 @@ } return TCL_ERROR; } if (errno != 0) { if (interp != (Tcl_Interp *) NULL) { - TclExprFloatError(interp, d); /* sets interp->objResult */ - - /* - * Move the interpreter's object result to the string result, - * then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION HAS NULLS. - */ - - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), - (int *) NULL), - TCL_VOLATILE); + TclExprFloatError(interp, d); } return TCL_ERROR; } - while ((*end != 0) && isspace(UCHAR(*end))) { + while ((*end != 0) && isspace(UCHAR(*end))) { /* INTL: ISO space. */ end++; } if (*end != 0) { goto badDouble; } @@ -255,11 +246,11 @@ * * Results: * The return value is normally TCL_OK; in this case *boolPtr * will be set to the 0/1 value equivalent to string. If * string is improperly formed then TCL_ERROR is returned and - * an error message will be left in interp->result. + * an error message will be left in the interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -277,11 +268,12 @@ int i; char lowerCase[10], c; size_t length; /* - * Convert the input string to all lower-case. + * Convert the input string to all lower-case. + * INTL: This code will work on UTF strings. */ for (i = 0; i < 9; i++) { c = string[i]; if (c == 0) { Index: generic/tclGetDate.y ================================================================== --- generic/tclGetDate.y +++ generic/tclGetDate.y @@ -9,11 +9,11 @@ * 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. * - * SCCS: @(#) tclGetDate.y 1.34 97/02/03 14:53:54 + * RCS: @(#) $Id: tclGetDate.y,v 1.1.2.3 1999/03/10 06:49:16 stanton Exp $ */ %{ /* * tclDate.c -- @@ -594,11 +594,11 @@ Julian += yyTimezone * 60L; if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0) return -1; Julian += tod; if (DSTmode == DSTon - || (DSTmode == DSTmaybe && TclpGetDate(&Julian, 0)->tm_isdst)) + || (DSTmode == DSTmaybe && TclpGetDate((TclpTime_t)&Julian, 0)->tm_isdst)) Julian -= 60 * 60; *TimePtr = Julian; return 0; } @@ -609,12 +609,12 @@ time_t Future; { time_t StartDay; time_t FutureDay; - StartDay = (TclpGetDate(&Start, 0)->tm_hour + 1) % 24; - FutureDay = (TclpGetDate(&Future, 0)->tm_hour + 1) % 24; + StartDay = (TclpGetDate((TclpTime_t)&Start, 0)->tm_hour + 1) % 24; + FutureDay = (TclpGetDate((TclpTime_t)&Future, 0)->tm_hour + 1) % 24; return (Future - Start) + (StartDay - FutureDay) * 60L * 60L; } static time_t @@ -625,11 +625,11 @@ { struct tm *tm; time_t now; now = Start; - tm = TclpGetDate(&now, 0); + tm = TclpGetDate((TclpTime_t)&now, 0); now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7); now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1); return DSTcorrect(Start, now); } @@ -648,11 +648,11 @@ if (RelMonth == 0) { *TimePtr = 0; return 0; } - tm = TclpGetDate(&Start, 0); + tm = TclpGetDate((TclpTime_t)&Start, 0); Month = 12 * (tm->tm_year + TM_YEAR_BASE) + tm->tm_mon + RelMonth; Year = Month / 12; Month = Month % 12 + 1; result = Convert(Month, (time_t) tm->tm_mday, Year, (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec, @@ -690,15 +690,12 @@ int abbrev; /* * Make it lowercase. */ - for (p = buff; *p; p++) { - if (isupper(UCHAR(*p))) { - *p = (char) tolower(UCHAR(*p)); - } - } + + Tcl_UtfToLower(buff); if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) { yylval.Meridian = MERam; return tMERIDIAN; } @@ -767,11 +764,12 @@ } /* * Military timezones. */ - if (buff[1] == '\0' && isalpha(UCHAR(*buff))) { + if (buff[1] == '\0' && !(*buff & 0x80) + && isalpha(UCHAR(*buff))) { /* INTL: ISO only */ for (tp = MilitaryTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } @@ -813,33 +811,35 @@ for ( ; ; ) { while (isspace((unsigned char) (*yyInput))) { yyInput++; } - if (isdigit(c = *yyInput) || c == '-' || c == '+') { + if (isdigit(c = *yyInput) || c == '-' || c == '+') { /* INTL: digit */ if (c == '-' || c == '+') { sign = c == '-' ? -1 : 1; - if (!isdigit(*++yyInput)) { + if (!isdigit(*++yyInput)) { /* INTL: digit */ /* * skip the '-' sign */ continue; } } else { sign = 0; } - for (yylval.Number = 0; isdigit(c = *yyInput++); ) { + for (yylval.Number = 0; + isdigit(c = *yyInput++); ) { /* INTL: digit */ yylval.Number = 10 * yylval.Number + c - '0'; } yyInput--; if (sign < 0) { yylval.Number = -yylval.Number; } return sign ? tSNUMBER : tUNUMBER; } - if (isalpha(UCHAR(c))) { - for (p = buff; isalpha(c = *yyInput++) || c == '.'; ) { + if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */ + for (p = buff; isalpha(c = *yyInput++) /* INTL: ISO only. */ + || c == '.'; ) { if (p < &buff[sizeof buff - 1]) { *p++ = c; } } *p = '\0'; @@ -879,11 +879,11 @@ time_t Time; time_t tod; int thisyear; yyInput = p; - tm = TclpGetDate((time_t *) &now, 0); + tm = TclpGetDate((TclpTime_t) &now, 0); thisyear = tm->tm_year + TM_YEAR_BASE; yyYear = thisyear; yyMonth = tm->tm_mon + 1; yyDay = tm->tm_mday; yyTimezone = zone; Index: generic/tclHash.c ================================================================== --- generic/tclHash.c +++ generic/tclHash.c @@ -8,11 +8,11 @@ * 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. * - * SCCS: @(#) tclHash.c 1.16 96/04/29 10:30:49 + * RCS: @(#) $Id: tclHash.c,v 1.1.2.2 1998/09/24 23:58:50 stanton Exp $ */ #include "tclInt.h" /* @@ -81,10 +81,15 @@ * 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. */ { +#if (TCL_SMALL_HASH_TABLE != 4) + panic("Tcl_InitHashTable: TCL_SMALL_HASH_TABLE is %d, not 4\n", + 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; Index: generic/tclHistory.c ================================================================== --- generic/tclHistory.c +++ generic/tclHistory.c @@ -10,11 +10,11 @@ * 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. * - * SCCS: @(#) tclHistory.c 1.47 97/08/04 16:08:17 + * RCS: @(#) $Id: tclHistory.c,v 1.1.2.3 1999/02/01 21:29:51 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" @@ -55,24 +55,20 @@ if (length > 0) { /* * Call Tcl_RecordAndEvalObj to do the actual work. */ - TclNewObj(cmdPtr); - TclInitStringRep(cmdPtr, cmd, length); + 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. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS. */ - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL), + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), TCL_VOLATILE); /* * Discard the Tcl object created to hold the command. */ @@ -114,15 +110,14 @@ * 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 use - * Tcl_GlobalEvalObj instead of - * Tcl_EvalObj. */ + * TCL_EVAL_GLOBAL means evaluate the + * script in global variable context instead + * of the current procedure. */ { - Interp *iPtr = (Interp *) interp; int result; Tcl_Obj *list[3]; register Tcl_Obj *objPtr; /* @@ -133,23 +128,18 @@ list[1] = Tcl_NewStringObj("add", -1); list[2] = cmdPtr; objPtr = Tcl_NewListObj(3, list); Tcl_IncrRefCount(objPtr); - (void) Tcl_GlobalEvalObj(interp, objPtr); + (void) Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL); Tcl_DecrRefCount(objPtr); /* * Execute the command. */ result = TCL_OK; if (!(flags & TCL_NO_EVAL)) { - iPtr->evalFlags = (flags & ~TCL_EVAL_GLOBAL); - if (flags & TCL_EVAL_GLOBAL) { - result = Tcl_GlobalEvalObj(interp, cmdPtr); - } else { - result = Tcl_EvalObj(interp, cmdPtr); - } + result = Tcl_EvalObjEx(interp, cmdPtr, flags & TCL_EVAL_GLOBAL); } return result; } Index: generic/tclIO.c ================================================================== --- generic/tclIO.c +++ generic/tclIO.c @@ -2,20 +2,21 @@ * 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 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. * - * SCCS: @(#) tclIO.c 1.272 97/10/22 10:27:53 + * RCS: @(#) $Id: tclIO.c,v 1.1.2.7 1999/04/14 00:33:23 surles Exp $ */ -#include "tclInt.h" -#include "tclPort.h" +#include "tclInt.h" +#include "tclPort.h" /* * 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 @@ -62,11 +63,11 @@ typedef struct ChannelBuffer { 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 bufSize; /* How big is the buffer? */ + int bufLength; /* How big is the buffer? */ struct ChannelBuffer *nextPtr; /* Next buffer in chain. */ char buf[4]; /* Placeholder for real buffer. The real * buffer occuppies this space + bufSize-4 * bytes. This must be the last field in @@ -73,10 +74,18 @@ * the structure. */ } ChannelBuffer; #define CHANNELBUFFER_HEADER_SIZE (sizeof(ChannelBuffer) - 4) +/* + * 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) @@ -102,11 +111,11 @@ 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. */ - char *script; /* Script to invoke. */ + 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. */ @@ -125,10 +134,29 @@ 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. */ Tcl_EolTranslation inputTranslation; /* What translation to apply for end of line * sequences on input? */ Tcl_EolTranslation outputTranslation; /* What translation to use for generating @@ -139,16 +167,21 @@ * 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. */ - ClientData instanceData; /* Instance specific data. */ + ClientData instanceData; /* Instance-specific data provided by + * creator of channel. */ + Tcl_ChannelType *typePtr; /* Pointer to channel type structure. */ int refCount; /* How many interpreters hold references to * this IO channel? */ 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 @@ -207,22 +240,29 @@ * 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 INPUT_NEED_NL (1<<15) /* Saw a '\r' at end of last buffer, + * and there should be a '\n' at + * beginning of next buffer. */ #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_GETS_BLOCKED (1<<14) /* The last input operation was a gets - * that failed to get a comlete line. +#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 unless - * an EOL is present. */ + * delivered for buffered data until + * the state of the channel changes. */ /* * 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 @@ -261,27 +301,10 @@ struct NextChannelHandler *nestedHandlerPtr; /* Next nested invocation of * ChannelHandlerEventProc. */ } NextChannelHandler; -/* - * This variable holds the list of nested ChannelHandlerEventProc invocations. - */ - -static NextChannelHandler *nestedHandlerPtr = (NextChannelHandler *) NULL; - -/* - * List of all channels currently open. - */ - -static Channel *firstChanPtr = (Channel *) NULL; - -/* - * Has a channel exit handler been created yet? - */ - -static int channelExitHandlerCreated = 0; /* * The following structure describes the event that is added to the Tcl * event queue by the channel handler check procedure. */ @@ -291,43 +314,118 @@ Channel *chanPtr; /* The channel that is ready. */ int readyMask; /* Events that have occurred. */ } ChannelHandlerEvent; /* - * Static variables to hold channels for stdin, stdout and stderr. + * 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; + +/* + * 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. */ -static Tcl_Channel stdinChannel = NULL; -static int stdinInitialized = 0; -static Tcl_Channel stdoutChannel = NULL; -static int stdoutInitialized = 0; -static Tcl_Channel stderrChannel = NULL; -static int stderrInitialized = 0; +typedef struct ThreadSpecificData { + + /* + * This variable holds the list of nested ChannelHandlerEventProc + * invocations. + */ + NextChannelHandler *nestedHandlerPtr; + + /* + * List of all channels currently open. + */ + Channel *firstChanPtr; +#ifdef oldcode + /* + * Has a channel exit handler been created yet? + */ + int channelExitHandlerCreated; + + /* + * Has the channel event source been created and registered with the + * notifier? + */ + int channelEventSourceCreated; +#endif + /* + * Static variables to hold channels for stdin, stdout and stderr. + */ + Tcl_Channel stdinChannel; + int stdinInitialized; + Tcl_Channel stdoutChannel; + int stdoutInitialized; + Tcl_Channel stderrChannel; + int stderrInitialized; + +} ThreadSpecificData; + +static Tcl_ThreadDataKey dataKey; + /* * Static functions in this file: */ +static ChannelBuffer * AllocChannelBuffer _ANSI_ARGS_((int length)); static void ChannelEventScriptInvoker _ANSI_ARGS_(( ClientData clientData, int flags)); static void ChannelTimerProc _ANSI_ARGS_(( ClientData clientData)); +static int CheckChannelErrors _ANSI_ARGS_((Channel *chanPtr, + int direction)); +static int CheckFlush _ANSI_ARGS_((Channel *chanPtr, + ChannelBuffer *bufPtr, int newlineFlag)); +static int CheckForDeadChannel _ANSI_ARGS_((Tcl_Interp *interp, + Channel *chan)); static void CheckForStdChannelsBeingClosed _ANSI_ARGS_(( Tcl_Channel chan)); static void CleanupChannelHandlers _ANSI_ARGS_(( Tcl_Interp *interp, Channel *chanPtr)); static int CloseChannel _ANSI_ARGS_((Tcl_Interp *interp, Channel *chanPtr, int errorCode)); -static void CloseChannelsOnExit _ANSI_ARGS_((ClientData data)); +static void CommonGetsCleanup _ANSI_ARGS_((Channel *chanPtr, + Tcl_Encoding encoding)); static int CopyAndTranslateBuffer _ANSI_ARGS_(( Channel *chanPtr, char *result, int space)); static int CopyData _ANSI_ARGS_((CopyState *csPtr, int mask)); static void CopyEventProc _ANSI_ARGS_((ClientData clientData, int mask)); static void CreateScriptRecord _ANSI_ARGS_(( Tcl_Interp *interp, Channel *chanPtr, - int mask, char *script)); + int mask, Tcl_Obj *scriptPtr)); static void DeleteChannelTable _ANSI_ARGS_(( ClientData clientData, Tcl_Interp *interp)); static void DeleteScriptRecord _ANSI_ARGS_((Tcl_Interp *interp, Channel *chanPtr, int mask)); static void DiscardInputQueued _ANSI_ARGS_(( @@ -334,77 +432,166 @@ Channel *chanPtr, int discardSavedBuffers)); static void DiscardOutputQueued _ANSI_ARGS_(( Channel *chanPtr)); static int DoRead _ANSI_ARGS_((Channel *chanPtr, char *srcPtr, int slen)); -static int DoWrite _ANSI_ARGS_((Channel *chanPtr, char *srcPtr, - int slen)); +static int DoWrite _ANSI_ARGS_((Channel *chanPtr, char *src, + int srcLen)); +static int FilterInputBytes _ANSI_ARGS_((Channel *chanPtr, + GetsState *statePtr)); static int FlushChannel _ANSI_ARGS_((Tcl_Interp *interp, Channel *chanPtr, int calledFromAsyncFlush)); -static Tcl_HashTable *GetChannelTable _ANSI_ARGS_((Tcl_Interp *interp)); -static int GetEOL _ANSI_ARGS_((Channel *chanPtr)); +static Tcl_HashTable * GetChannelTable _ANSI_ARGS_((Tcl_Interp *interp)); static int GetInput _ANSI_ARGS_((Channel *chanPtr)); +static void PeekAhead _ANSI_ARGS_((Channel *chanPtr, + char **dstEndPtr, GetsState *gsPtr)); +static int ReadBytes _ANSI_ARGS_((Channel *chanPtr, + Tcl_Obj *objPtr, int charsLeft, int *offsetPtr)); +static int ReadChars _ANSI_ARGS_((Channel *chanPtr, + Tcl_Obj *objPtr, int charsLeft, int *offsetPtr, + int *factorPtr)); static void RecycleBuffer _ANSI_ARGS_((Channel *chanPtr, ChannelBuffer *bufPtr, int mustDiscard)); -static int ScanBufferForEOL _ANSI_ARGS_((Channel *chanPtr, - ChannelBuffer *bufPtr, - Tcl_EolTranslation translation, int eofChar, - int *bytesToEOLPtr, int *crSeenPtr)); -static int ScanInputForEOL _ANSI_ARGS_((Channel *chanPtr, - int *bytesQueuedPtr)); static int SetBlockMode _ANSI_ARGS_((Tcl_Interp *interp, Channel *chanPtr, int mode)); static void StopCopy _ANSI_ARGS_((CopyState *csPtr)); +static int TranslateInputEOL _ANSI_ARGS_((Channel *chanPtr, + char *dst, CONST char *src, int *dstLenPtr, + int *srcLenPtr)); +static int TranslateOutputEOL _ANSI_ARGS_((Channel *chanPtr, + char *dst, CONST char *src, int *dstLenPtr, + int *srcLenPtr)); static void UpdateInterest _ANSI_ARGS_((Channel *chanPtr)); -static int CheckForDeadChannel _ANSI_ARGS_((Tcl_Interp *interp, - Channel *chan)); - -/* - *---------------------------------------------------------------------- - * - * 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(interp, chanPtr, mode) - 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; - if (chanPtr->typePtr->blockModeProc != NULL) { - result = (chanPtr->typePtr->blockModeProc) (chanPtr->instanceData, - mode); - } - if (result != 0) { - Tcl_SetErrno(result); - if (interp != (Tcl_Interp *) NULL) { - Tcl_AppendResult(interp, "error setting blocking mode: ", - Tcl_PosixError(interp), (char *) NULL); - } - return TCL_ERROR; - } - if (mode == TCL_MODE_BLOCKING) { - chanPtr->flags &= (~(CHANNEL_NONBLOCKING | BG_FLUSH_SCHEDULED)); - } else { - chanPtr->flags |= CHANNEL_NONBLOCKING; - } - return TCL_OK; -} +static int WriteBytes _ANSI_ARGS_((Channel *chanPtr, + CONST char *src, int srcLen)); +static int WriteChars _ANSI_ARGS_((Channel *chanPtr, + CONST char *src, int srcLen)); + + +/* + *--------------------------------------------------------------------------- + * + * TclInitIOSubsystem -- + * + * Initialize all resources used by this subsystem on a per-process + * basis. + * + * Results: + * None. + * + * Side effects: + * Depends on the memory subsystems. + * + *--------------------------------------------------------------------------- + */ + +void +TclInitIOSubsystem() +{ + /* + * 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() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + Channel *chanPtr; /* Iterates over open channels. */ + Channel *nextChanPtr; /* Iterates over open channels. */ + + + for (chanPtr = tsdPtr->firstChanPtr; chanPtr != (Channel *) NULL; + chanPtr = nextChanPtr) { + nextChanPtr = chanPtr->nextChanPtr; + + /* + * 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. + */ + + chanPtr->refCount--; + } + + if (chanPtr->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((Tcl_Interp *) 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. + */ + + if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { + (chanPtr->typePtr->closeProc)(chanPtr->instanceData, + (Tcl_Interp *) NULL); + } else { + (chanPtr->typePtr->close2Proc)(chanPtr->instanceData, + (Tcl_Interp *) NULL, 0); + } + + /* + * 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 = (ClientData) NULL; + chanPtr->flags |= CHANNEL_DEAD; + } + } +} + + /* *---------------------------------------------------------------------- * * Tcl_SetStdChannel -- @@ -424,22 +611,23 @@ void Tcl_SetStdChannel(channel, type) Tcl_Channel channel; int type; /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */ { + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); switch (type) { case TCL_STDIN: - stdinInitialized = 1; - stdinChannel = channel; + tsdPtr->stdinInitialized = 1; + tsdPtr->stdinChannel = channel; break; case TCL_STDOUT: - stdoutInitialized = 1; - stdoutChannel = channel; + tsdPtr->stdoutInitialized = 1; + tsdPtr->stdoutChannel = channel; break; case TCL_STDERR: - stderrInitialized = 1; - stderrChannel = channel; + tsdPtr->stderrInitialized = 1; + tsdPtr->stderrChannel = channel; break; } } /* @@ -456,92 +644,70 @@ * May cause the creation of a standard channel and the underlying * file. * *---------------------------------------------------------------------- */ - Tcl_Channel Tcl_GetStdChannel(type) 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. Note that we need to set - * stdinInitialized before calling TclGetDefaultStdChannel in order - * to avoid recursive loops when TclGetDefaultStdChannel calls - * Tcl_CreateChannel. + * store them in the static variables. */ switch (type) { case TCL_STDIN: - if (!stdinInitialized) { - stdinChannel = TclGetDefaultStdChannel(TCL_STDIN); - stdinInitialized = 1; + 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 (stdinChannel != (Tcl_Channel) NULL) { + if (tsdPtr->stdinChannel != (Tcl_Channel) NULL) { (void) Tcl_RegisterChannel((Tcl_Interp *) NULL, - stdinChannel); + tsdPtr->stdinChannel); } } - channel = stdinChannel; + channel = tsdPtr->stdinChannel; break; case TCL_STDOUT: - if (!stdoutInitialized) { - stdoutChannel = TclGetDefaultStdChannel(TCL_STDOUT); - stdoutInitialized = 1; - - /* - * Artificially bump the refcount to ensure that the channel - * is only closed on exit. - * - * NOTE: Must only do this if stdoutChannel is not NULL. It - * can be NULL in situations where Tcl is unable to connect - * to the standard output. - */ - - if (stdoutChannel != (Tcl_Channel) NULL) { + if (!tsdPtr->stdoutInitialized) { + tsdPtr->stdoutChannel = TclpGetDefaultStdChannel(TCL_STDOUT); + tsdPtr->stdoutInitialized = 1; + if (tsdPtr->stdoutChannel != (Tcl_Channel) NULL) { (void) Tcl_RegisterChannel((Tcl_Interp *) NULL, - stdoutChannel); + tsdPtr->stdoutChannel); } } - channel = stdoutChannel; + channel = tsdPtr->stdoutChannel; break; case TCL_STDERR: - if (!stderrInitialized) { - stderrChannel = TclGetDefaultStdChannel(TCL_STDERR); - stderrInitialized = 1; - - /* - * Artificially bump the refcount to ensure that the channel - * is only closed on exit. - * - * NOTE: Must only do this if stderrChannel is not NULL. It - * can be NULL in situations where Tcl is unable to connect - * to the standard error. - */ - - if (stderrChannel != (Tcl_Channel) NULL) { + if (!tsdPtr->stderrInitialized) { + tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR); + tsdPtr->stderrInitialized = 1; + if (tsdPtr->stderrChannel != (Tcl_Channel) NULL) { (void) Tcl_RegisterChannel((Tcl_Interp *) NULL, - stderrChannel); + tsdPtr->stderrChannel); } } - channel = stderrChannel; + channel = tsdPtr->stderrChannel; break; } return channel; } + /* *---------------------------------------------------------------------- * * Tcl_CreateCloseHandler @@ -625,113 +791,10 @@ } else { cbPrevPtr = cbPtr; } } } - -/* - *---------------------------------------------------------------------- - * - * CloseChannelsOnExit -- - * - * Closes all the existing channels, on exit. This routine is called - * during exit processing. - * - * Results: - * None. - * - * Side effects: - * Closes all channels. - * - *---------------------------------------------------------------------- - */ - - /* ARGSUSED */ -static void -CloseChannelsOnExit(clientData) - ClientData clientData; /* NULL - unused. */ -{ - Channel *chanPtr; /* Iterates over open channels. */ - Channel *nextChanPtr; /* Iterates over open channels. */ - - - for (chanPtr = firstChanPtr; chanPtr != (Channel *) NULL; - chanPtr = nextChanPtr) { - nextChanPtr = chanPtr->nextChanPtr; - - /* - * 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 *) stdinChannel) || - (chanPtr == (Channel *) stdoutChannel) || - (chanPtr == (Channel *) stderrChannel)) { - - /* - * Decrement the refcount which was earlier artificially bumped - * up to keep the channel from being closed. - */ - - chanPtr->refCount--; - } - - if (chanPtr->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((Tcl_Interp *) 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. - */ - - (chanPtr->typePtr->closeProc) (chanPtr->instanceData, - (Tcl_Interp *) 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 = (ClientData) NULL; - chanPtr->flags |= CHANNEL_DEAD; - } - } - - /* - * Reinitialize all the variables to the initial state: - */ - - firstChanPtr = (Channel *) NULL; - nestedHandlerPtr = (NextChannelHandler *) NULL; - channelExitHandlerCreated = 0; - stdinChannel = NULL; - stdinInitialized = 0; - stdoutChannel = NULL; - stdoutInitialized = 0; - stderrChannel = NULL; - stderrInitialized = 0; -} /* *---------------------------------------------------------------------- * * GetChannelTable -- @@ -856,11 +919,11 @@ } Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, ChannelEventScriptInvoker, (ClientData) sPtr); - ckfree(sPtr->script); + Tcl_DecrRefCount(sPtr->scriptPtr); ckfree((char *) sPtr); } else { prevPtr = sPtr; } } @@ -909,31 +972,80 @@ static void CheckForStdChannelsBeingClosed(chan) Tcl_Channel chan; { Channel *chanPtr = (Channel *) chan; - - if ((chan == stdinChannel) && (stdinInitialized)) { - if (chanPtr->refCount < 2) { - chanPtr->refCount = 0; - stdinChannel = NULL; - return; - } - } else if ((chan == stdoutChannel) && (stdoutInitialized)) { - if (chanPtr->refCount < 2) { - chanPtr->refCount = 0; - stdoutChannel = NULL; - return; - } - } else if ((chan == stderrChannel) && (stderrInitialized)) { - if (chanPtr->refCount < 2) { - chanPtr->refCount = 0; - stderrChannel = NULL; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if ((chan == tsdPtr->stdinChannel) && (tsdPtr->stdinInitialized)) { + if (chanPtr->refCount < 2) { + chanPtr->refCount = 0; + tsdPtr->stdinChannel = NULL; + return; + } + } else if ((chan == tsdPtr->stdoutChannel) && (tsdPtr->stdoutInitialized)) { + if (chanPtr->refCount < 2) { + chanPtr->refCount = 0; + tsdPtr->stdoutChannel = NULL; + return; + } + } else if ((chan == tsdPtr->stderrChannel) && (tsdPtr->stderrInitialized)) { + if (chanPtr->refCount < 2) { + chanPtr->refCount = 0; + tsdPtr->stderrChannel = NULL; return; } } } + +/* + *---------------------------------------------------------------------- + * + * 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(interp, chan) + 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 new; /* Is the hash entry new or does it exist? */ + Channel *chanPtr; /* The actual channel. */ + + chanPtr = (Channel *) chan; + + if (chanPtr->channelName == (char *) NULL) { + panic("Tcl_RegisterChannel: channel without name"); + } + if (interp != (Tcl_Interp *) NULL) { + hTblPtr = GetChannelTable(interp); + hPtr = Tcl_CreateHashEntry(hTblPtr, chanPtr->channelName, &new); + if (new == 0) { + if (chan == (Tcl_Channel) Tcl_GetHashValue(hPtr)) { + return; + } + panic("Tcl_RegisterChannel: duplicate channel names"); + } + Tcl_SetHashValue(hPtr, (ClientData) chanPtr); + } + chanPtr->refCount++; +} /* *---------------------------------------------------------------------- * * Tcl_UnregisterChannel -- @@ -1024,75 +1136,27 @@ } return TCL_OK; } /* - *---------------------------------------------------------------------- - * - * 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(interp, chan) - 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 new; /* Is the hash entry new or does it exist? */ - Channel *chanPtr; /* The actual channel. */ - - chanPtr = (Channel *) chan; - - if (chanPtr->channelName == (char *) NULL) { - panic("Tcl_RegisterChannel: channel without name"); - } - if (interp != (Tcl_Interp *) NULL) { - hTblPtr = GetChannelTable(interp); - hPtr = Tcl_CreateHashEntry(hTblPtr, chanPtr->channelName, &new); - if (new == 0) { - if (chan == (Tcl_Channel) Tcl_GetHashValue(hPtr)) { - return; - } - panic("Tcl_RegisterChannel: duplicate channel names"); - } - Tcl_SetHashValue(hPtr, (ClientData) chanPtr); - } - chanPtr->refCount++; -} - -/* - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- * * 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->result - * contains an error message. It also returns, in modePtr, the - * modes in which the channel is opened. + * 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(interp, chanName, modePtr) Tcl_Interp *interp; /* Interpreter in which to find or create @@ -1172,10 +1236,12 @@ 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. */ + CONST char *name; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); chanPtr = (Channel *) ckalloc((unsigned) sizeof(Channel)); if (chanName != (char *) NULL) { chanPtr->channelName = ckalloc((unsigned) (strlen(chanName) + 1)); @@ -1184,10 +1250,24 @@ panic("Tcl_CreateChannel: NULL channel name"); } chanPtr->flags = mask; + /* + * Set the channel to system default encoding. + */ + + chanPtr->encoding = NULL; + name = Tcl_GetEncodingName(NULL); + if (strcmp(name, "binary") != 0) { + chanPtr->encoding = Tcl_GetEncoding(NULL, name); + } + chanPtr->inputEncodingState = NULL; + chanPtr->inputEncodingFlags = TCL_ENCODING_START; + chanPtr->outputEncodingState = NULL; + chanPtr->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 @@ -1214,37 +1294,38 @@ chanPtr->interestMask = 0; chanPtr->scriptRecordPtr = (EventScriptRecord *) NULL; chanPtr->bufSize = CHANNELBUFFER_DEFAULT_SIZE; chanPtr->timer = NULL; chanPtr->csPtr = NULL; + + chanPtr->outputStage = NULL; + if ((chanPtr->encoding != NULL) && (chanPtr->flags & TCL_WRITABLE)) { + chanPtr->outputStage = (char *) + ckalloc((unsigned) (chanPtr->bufSize + 2)); + } /* * 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. */ - chanPtr->nextChanPtr = firstChanPtr; - firstChanPtr = chanPtr; - - if (!channelExitHandlerCreated) { - channelExitHandlerCreated = 1; - Tcl_CreateExitHandler(CloseChannelsOnExit, (ClientData) NULL); - } - + chanPtr->nextChanPtr = tsdPtr->firstChanPtr; + tsdPtr->firstChanPtr = chanPtr; + /* * Install this channel in the first empty standard channel slot, if * the channel was previously closed explicitly. */ - if ((stdinChannel == NULL) && (stdinInitialized == 1)) { + if ((tsdPtr->stdinChannel == NULL) && (tsdPtr->stdinInitialized == 1)) { Tcl_SetStdChannel((Tcl_Channel)chanPtr, TCL_STDIN); Tcl_RegisterChannel((Tcl_Interp *) NULL, (Tcl_Channel) chanPtr); - } else if ((stdoutChannel == NULL) && (stdoutInitialized == 1)) { + } else if ((tsdPtr->stdoutChannel == NULL) && (tsdPtr->stdoutInitialized == 1)) { Tcl_SetStdChannel((Tcl_Channel)chanPtr, TCL_STDOUT); Tcl_RegisterChannel((Tcl_Interp *) NULL, (Tcl_Channel) chanPtr); - } else if ((stderrChannel == NULL) && (stderrInitialized == 1)) { + } else if ((tsdPtr->stderrChannel == NULL) && (tsdPtr->stderrInitialized == 1)) { Tcl_SetStdChannel((Tcl_Channel)chanPtr, TCL_STDERR); Tcl_RegisterChannel((Tcl_Interp *) NULL, (Tcl_Channel) chanPtr); } return (Tcl_Channel) chanPtr; } @@ -1390,10 +1471,51 @@ Channel *chanPtr; /* The actual channel. */ chanPtr = (Channel *) chan; return chanPtr->instanceData; } + +/* + *--------------------------------------------------------------------------- + * + * 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(length) + int length; /* Desired length of channel buffer. */ +{ + ChannelBuffer *bufPtr; + int n; + + n = length + CHANNELBUFFER_HEADER_SIZE + BUFFER_PADDING + BUFFER_PADDING; + bufPtr = (ChannelBuffer *) ckalloc((unsigned) n); + bufPtr->nextAdded = BUFFER_PADDING; + bufPtr->nextRemoved = BUFFER_PADDING; + bufPtr->bufLength = length + BUFFER_PADDING; + bufPtr->nextPtr = (ChannelBuffer *) NULL; + return bufPtr; +} /* *---------------------------------------------------------------------- * * RecycleBuffer -- @@ -1462,12 +1584,12 @@ ckfree((char *) bufPtr); return; keepit: - bufPtr->nextRemoved = 0; - bufPtr->nextAdded = 0; + bufPtr->nextRemoved = BUFFER_PADDING; + bufPtr->nextAdded = BUFFER_PADDING; bufPtr->nextPtr = (ChannelBuffer *) NULL; } /* *---------------------------------------------------------------------- @@ -1567,13 +1689,14 @@ * queue. */ int toWrite; /* Amount of output data in current * buffer available to be written. */ int written; /* Amount of output data actually * written in current round. */ - int errorCode; /* Stores POSIX error codes from + int errorCode = 0; /* Stores POSIX error codes from * channel driver operations. */ - errorCode = 0; + 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 @@ -1594,11 +1717,11 @@ * the current buffer is full, then move the current buffer to the * queue. */ if (((chanPtr->curOutPtr != (ChannelBuffer *) NULL) && - (chanPtr->curOutPtr->nextAdded == chanPtr->curOutPtr->bufSize)) + (chanPtr->curOutPtr->nextAdded == chanPtr->curOutPtr->bufLength)) || ((chanPtr->flags & BUFFER_READY) && (chanPtr->outQueueHead == (ChannelBuffer *) NULL))) { chanPtr->flags &= (~(BUFFER_READY)); chanPtr->curOutPtr->nextPtr = (ChannelBuffer *) NULL; if (chanPtr->outQueueHead == (ChannelBuffer *) NULL) { @@ -1633,11 +1756,12 @@ * Produce the output on the channel. */ toWrite = bufPtr->nextAdded - bufPtr->nextRemoved; written = (chanPtr->typePtr->outputProc) (chanPtr->instanceData, - bufPtr->buf + bufPtr->nextRemoved, toWrite, &errorCode); + (char *) bufPtr->buf + bufPtr->nextRemoved, toWrite, + &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. @@ -1693,11 +1817,13 @@ * currently queued. */ DiscardOutputQueued(chanPtr); continue; - } + } else { + wroteSome = 1; + } bufPtr->nextRemoved += written; /* * If this buffer is now empty, recycle it. @@ -1709,21 +1835,26 @@ chanPtr->outQueueTail = (ChannelBuffer *) NULL; } RecycleBuffer(chanPtr, bufPtr, 0); } } /* Closes "while (1)". */ - + /* - * If the queue became empty and we have the asynchronous flushing - * mechanism active, cancel the asynchronous flushing. + * 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 ((chanPtr->outQueueHead == (ChannelBuffer *) NULL) && - (chanPtr->flags & BG_FLUSH_SCHEDULED)) { - chanPtr->flags &= (~(BG_FLUSH_SCHEDULED)); - (chanPtr->typePtr->watchProc)(chanPtr->instanceData, - chanPtr->interestMask); + if (chanPtr->flags & BG_FLUSH_SCHEDULED) { + if (wroteSome) { + return errorCode; + } else if (chanPtr->outQueueHead == (ChannelBuffer *) NULL) { + chanPtr->flags &= (~(BG_FLUSH_SCHEDULED)); + (chanPtr->typePtr->watchProc)(chanPtr->instanceData, + chanPtr->interestMask); + } } /* * 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 @@ -1766,11 +1897,12 @@ int result = 0; /* Of calling driver close * operation. */ Channel *prevChanPtr; /* Preceding channel in list of * all channels - used to splice a * channel out of the list on close. */ - + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + if (chanPtr == NULL) { return result; } /* @@ -1822,14 +1954,14 @@ /* * Splice this channel out of the list of all channels. */ - if (chanPtr == firstChanPtr) { - firstChanPtr = chanPtr->nextChanPtr; + if (chanPtr == tsdPtr->firstChanPtr) { + tsdPtr->firstChanPtr = chanPtr->nextChanPtr; } else { - for (prevChanPtr = firstChanPtr; + for (prevChanPtr = tsdPtr->firstChanPtr; (prevChanPtr != (Channel *) NULL) && (prevChanPtr->nextChanPtr != chanPtr); prevChanPtr = prevChanPtr->nextChanPtr) { /* Empty loop body. */ } @@ -1838,17 +1970,26 @@ } prevChanPtr->nextChanPtr = chanPtr->nextChanPtr; } /* - * OK, close the channel itself. + * Close and free the channel driver state. */ - - result = (chanPtr->typePtr->closeProc) (chanPtr->instanceData, interp); + + if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { + result = (chanPtr->typePtr->closeProc)(chanPtr->instanceData, interp); + } else { + result = (chanPtr->typePtr->close2Proc)(chanPtr->instanceData, interp, + 0); + } if (chanPtr->channelName != (char *) NULL) { ckfree(chanPtr->channelName); + } + Tcl_FreeEncoding(chanPtr->encoding); + if (chanPtr->outputStage != NULL) { + ckfree((char *) chanPtr->outputStage); } /* * If we are being called synchronously, report either * any latent error on the channel or the current error. @@ -1915,10 +2056,11 @@ CloseCallback *cbPtr; /* Iterate over close callbacks * for this channel. */ EventScriptRecord *ePtr, *eNextPtr; /* Iterate over eventscript records. */ Channel *chanPtr; /* The real IO channel. */ int result; /* Of calling FlushChannel. */ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); NextChannelHandler *nhPtr; if (chan == (Tcl_Channel) NULL) { return TCL_OK; } @@ -1941,11 +2083,11 @@ /* * Remove any references to channel handlers for this channel that * may be about to be invoked. */ - for (nhPtr = nestedHandlerPtr; + for (nhPtr = tsdPtr->nestedHandlerPtr; nhPtr != (NextChannelHandler *) NULL; nhPtr = nhPtr->nestedHandlerPtr) { if (nhPtr->nextHandlerPtr && (nhPtr->nextHandlerPtr->chanPtr == chanPtr)) { nhPtr->nextHandlerPtr = NULL; @@ -1987,11 +2129,11 @@ for (ePtr = chanPtr->scriptRecordPtr; ePtr != (EventScriptRecord *) NULL; ePtr = eNextPtr) { eNextPtr = ePtr->nextPtr; - ckfree(ePtr->script); + Tcl_DecrRefCount(ePtr->scriptPtr); ckfree((char *) ePtr); } chanPtr->scriptRecordPtr = (EventScriptRecord *) NULL; /* @@ -2011,32 +2153,185 @@ if ((chanPtr->curOutPtr != (ChannelBuffer *) NULL) && (chanPtr->curOutPtr->nextAdded > chanPtr->curOutPtr->nextRemoved)) { chanPtr->flags |= BUFFER_READY; } + + /* + * 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. */ - + chanPtr->flags |= CHANNEL_CLOSED; - result = FlushChannel(interp, chanPtr, 0); - if (result != 0) { + if ((FlushChannel(interp, chanPtr, 0) != 0) || (result != 0)) { return TCL_ERROR; } - return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_Write -- * - * Puts a sequence of characters into an output buffer, may queue the + * 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. + * + * 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(chan, src, srcLen) + Tcl_Channel chan; /* The channel to buffer output for. */ + char *src; /* Data to queue in output buffer. */ + int srcLen; /* Length of data in bytes, or < 0 for + * strlen(). */ +{ + Channel *chanPtr; + + chanPtr = (Channel *) chan; + if (CheckChannelErrors(chanPtr, TCL_WRITABLE) != 0) { + return -1; + } + if (srcLen < 0) { + srcLen = strlen(src); + } + return DoWrite(chanPtr, src, srcLen); +} + +/* + *--------------------------------------------------------------------------- + * + * 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. + * + * 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(chan, src, len) + 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; + + chanPtr = (Channel *) chan; + if (CheckChannelErrors(chanPtr, TCL_WRITABLE) != 0) { + return -1; + } + if (len < 0) { + len = strlen(src); + } + if (chanPtr->encoding == NULL) { + /* + * Inefficient way to convert UTF-8 to byte-array, but the + * code parallels the way it is done for objects. + */ + + Tcl_Obj *objPtr; + int result; + + objPtr = Tcl_NewStringObj(src, len); + src = (char *) Tcl_GetByteArrayFromObj(objPtr, &len); + result = WriteBytes(chanPtr, src, len); + Tcl_DecrRefCount(objPtr); + return result; + } + return WriteChars(chanPtr, src, len); +} + +/* + *--------------------------------------------------------------------------- + * + * 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(chan, objPtr) + Tcl_Channel chan; /* The channel to buffer output for. */ + Tcl_Obj *objPtr; /* The object to write. */ +{ + Channel *chanPtr; + char *src; + int srcLen; + + chanPtr = (Channel *) chan; + if (CheckChannelErrors(chanPtr, TCL_WRITABLE) != 0) { + return -1; + } + if (chanPtr->encoding == NULL) { + src = (char *) Tcl_GetByteArrayFromObj(objPtr, &srcLen); + return WriteBytes(chanPtr, src, srcLen); + } else { + src = Tcl_GetStringFromObj(objPtr, &srcLen); + return WriteChars(chanPtr, src, srcLen); + } +} + +/* + *---------------------------------------------------------------------- + * + * WriteBytes -- + * + * Write 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. * * Results: @@ -2048,66 +2343,82 @@ * channel. * *---------------------------------------------------------------------- */ -int -Tcl_Write(chan, srcPtr, slen) - Tcl_Channel chan; /* The channel to buffer output for. */ - char *srcPtr; /* Output to buffer. */ - int slen; /* Its length. Negative means - * the output is null terminated - * and we must compute its length. */ -{ - Channel *chanPtr = (Channel *) chan; - - /* - * Check for unreported error. - */ - - if (chanPtr->unreportedError != 0) { - Tcl_SetErrno(chanPtr->unreportedError); - chanPtr->unreportedError = 0; - return -1; - } - - /* - * If the channel is not open for writing punt. - */ - - if (!(chanPtr->flags & TCL_WRITABLE)) { - Tcl_SetErrno(EACCES); - return -1; - } - - /* - * If the channel is in the middle of a background copy, fail. - */ - - if (chanPtr->csPtr) { - Tcl_SetErrno(EBUSY); - return -1; - } - - /* - * If length passed is negative, assume that the output is null terminated - * and compute its length. - */ - - if (slen < 0) { - slen = strlen(srcPtr); - } - - return DoWrite(chanPtr, srcPtr, slen); +static int +WriteBytes(chanPtr, src, srcLen) + Channel *chanPtr; /* The channel to buffer output for. */ + CONST char *src; /* Bytes to write. */ + int srcLen; /* Number of bytes to write. */ +{ + ChannelBuffer *bufPtr; + char *dst; + int dstLen, dstMax, sawLF, savedLF, total, toWrite; + + total = 0; + sawLF = 0; + savedLF = 0; + + /* + * Loop over all bytes in src, storing them in output buffer with + * proper EOL translation. + */ + + while (srcLen + savedLF > 0) { + bufPtr = chanPtr->curOutPtr; + if (bufPtr == NULL) { + bufPtr = AllocChannelBuffer(chanPtr->bufSize); + chanPtr->curOutPtr = bufPtr; + } + dst = bufPtr->buf + bufPtr->nextAdded; + dstMax = bufPtr->bufLength - bufPtr->nextAdded; + dstLen = dstMax; + + toWrite = dstLen; + if (toWrite > srcLen) { + toWrite = srcLen; + } + + if (savedLF) { + /* + * A '\n' was left over from last call to TranslateOutputEOL() + * and we need to store it in this buffer. If the channel is + * line-based, we will need to flush it. + */ + + *dst++ = '\n'; + dstLen--; + sawLF++; + } + sawLF += TranslateOutputEOL(chanPtr, dst, src, &dstLen, &toWrite); + dstLen += savedLF; + savedLF = 0; + + if (dstLen > dstMax) { + savedLF = 1; + dstLen = dstMax; + } + bufPtr->nextAdded += dstLen; + if (CheckFlush(chanPtr, bufPtr, sawLF) != 0) { + return -1; + } + total += dstLen; + src += toWrite; + srcLen -= toWrite; + sawLF = 0; + } + return total; } /* *---------------------------------------------------------------------- * - * DoWrite -- + * WriteChars -- * - * Puts a sequence of characters into an output buffer, may queue the + * Convert UTF-8 bytes to the channel's external encoding and + * write the 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: @@ -2120,147 +2431,1750 @@ * *---------------------------------------------------------------------- */ static int -DoWrite(chanPtr, srcPtr, slen) - Channel *chanPtr; /* The channel to buffer output for. */ - char *srcPtr; /* Data to write. */ - int slen; /* Number of bytes to write. */ -{ - ChannelBuffer *outBufPtr; /* Current output buffer. */ - int foundNewline; /* Did we find a newline in output? */ - char *dPtr, *sPtr; /* Search variables for newline. */ - int crsent; /* In CRLF eol translation mode, - * remember the fact that a CR was - * output to the channel without - * its following NL. */ - int i; /* Loop index for newline search. */ - int destCopied; /* How many bytes were used in this - * destination buffer to hold the - * output? */ - int totalDestCopied; /* How many bytes total were - * copied to the channel buffer? */ - int srcCopied; /* How many bytes were copied from - * the source string? */ - char *destPtr; /* Where in line to copy to? */ - - /* - * If we are in network (or windows) translation mode, record the fact - * that we have not yet sent a CR to the channel. - */ - - crsent = 0; - - /* - * Loop filling buffers and flushing them until all output has been - * consumed. - */ - - srcCopied = 0; - totalDestCopied = 0; - - while (slen > 0) { - - /* - * Make sure there is a current output buffer to accept output. - */ - - if (chanPtr->curOutPtr == (ChannelBuffer *) NULL) { - chanPtr->curOutPtr = (ChannelBuffer *) ckalloc((unsigned) - (CHANNELBUFFER_HEADER_SIZE + chanPtr->bufSize)); - chanPtr->curOutPtr->nextAdded = 0; - chanPtr->curOutPtr->nextRemoved = 0; - chanPtr->curOutPtr->bufSize = chanPtr->bufSize; - chanPtr->curOutPtr->nextPtr = (ChannelBuffer *) NULL; - } - - outBufPtr = chanPtr->curOutPtr; - - destCopied = outBufPtr->bufSize - outBufPtr->nextAdded; - if (destCopied > slen) { - destCopied = slen; - } - - destPtr = outBufPtr->buf + outBufPtr->nextAdded; - switch (chanPtr->outputTranslation) { - case TCL_TRANSLATE_LF: - srcCopied = destCopied; - memcpy((VOID *) destPtr, (VOID *) srcPtr, (size_t) destCopied); - break; - case TCL_TRANSLATE_CR: - srcCopied = destCopied; - memcpy((VOID *) destPtr, (VOID *) srcPtr, (size_t) destCopied); - for (dPtr = destPtr; dPtr < destPtr + destCopied; dPtr++) { - if (*dPtr == '\n') { - *dPtr = '\r'; - } - } - break; - case TCL_TRANSLATE_CRLF: - for (srcCopied = 0, dPtr = destPtr, sPtr = srcPtr; - dPtr < destPtr + destCopied; - dPtr++, sPtr++, srcCopied++) { - if (*sPtr == '\n') { - if (crsent) { - *dPtr = '\n'; - crsent = 0; - } else { - *dPtr = '\r'; - crsent = 1; - sPtr--, srcCopied--; - } - } else { - *dPtr = *sPtr; - } - } - break; - case TCL_TRANSLATE_AUTO: - panic("Tcl_Write: AUTO output translation mode not supported"); - default: - panic("Tcl_Write: unknown output translation mode"); - } - - /* - * The current buffer is ready for output if it is full, or if it - * contains a newline and this channel is line-buffered, or if it - * contains any output and this channel is unbuffered. - */ - - outBufPtr->nextAdded += destCopied; - if (!(chanPtr->flags & BUFFER_READY)) { - if (outBufPtr->nextAdded == outBufPtr->bufSize) { - chanPtr->flags |= BUFFER_READY; - } else if (chanPtr->flags & CHANNEL_LINEBUFFERED) { - for (sPtr = srcPtr, i = 0, foundNewline = 0; - (i < srcCopied) && (!foundNewline); - i++, sPtr++) { - if (*sPtr == '\n') { - foundNewline = 1; - break; - } - } - if (foundNewline) { - chanPtr->flags |= BUFFER_READY; - } - } else if (chanPtr->flags & CHANNEL_UNBUFFERED) { - chanPtr->flags |= BUFFER_READY; - } - } - - totalDestCopied += srcCopied; - srcPtr += srcCopied; - slen -= srcCopied; - - if (chanPtr->flags & BUFFER_READY) { - if (FlushChannel(NULL, chanPtr, 0) != 0) { - return -1; - } - } - } /* Closes "while" */ - - return totalDestCopied; +WriteChars(chanPtr, src, srcLen) + 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. */ +{ + ChannelBuffer *bufPtr; + char *dst, *stage; + int saved, savedLF, sawLF, total, toWrite, flags; + int dstWrote, dstLen, stageLen, stageMax, stageRead; + Tcl_Encoding encoding; + char safe[BUFFER_PADDING]; + + total = 0; + sawLF = 0; + savedLF = 0; + saved = 0; + encoding = chanPtr->encoding; + + /* + * Loop over all UTF-8 characters in src, storing them in staging buffer + * with proper EOL translation. + */ + + while (srcLen + savedLF > 0) { + stage = chanPtr->outputStage; + stageMax = chanPtr->bufSize; + stageLen = stageMax; + + toWrite = stageLen; + if (toWrite > srcLen) { + toWrite = srcLen; + } + + if (savedLF) { + /* + * A '\n' was left over from last call to TranslateOutputEOL() + * and we need to store it in the staging buffer. If the + * channel is line-based, we will need to flush the output + * buffer (after translating the staging buffer). + */ + + *stage++ = '\n'; + stageLen--; + sawLF++; + } + sawLF += TranslateOutputEOL(chanPtr, stage, src, &stageLen, &toWrite); + + stage -= savedLF; + stageLen += savedLF; + savedLF = 0; + + if (stageLen > stageMax) { + savedLF = 1; + stageLen = stageMax; + } + src += toWrite; + srcLen -= toWrite; + + flags = chanPtr->outputEncodingFlags; + if (srcLen == 0) { + flags |= TCL_ENCODING_END; + } + + /* + * Loop over all UTF-8 characters in staging buffer, converting them + * to external encoding, storing them in output buffer. + */ + + while (stageLen + saved > 0) { + bufPtr = chanPtr->curOutPtr; + if (bufPtr == NULL) { + bufPtr = AllocChannelBuffer(chanPtr->bufSize); + chanPtr->curOutPtr = bufPtr; + } + dst = bufPtr->buf + bufPtr->nextAdded; + dstLen = bufPtr->bufLength - bufPtr->nextAdded; + + if (saved != 0) { + /* + * Here's some translated bytes left over from the last + * buffer that we need to stick at the beginning of this + * buffer. + */ + + memcpy((VOID *) dst, (VOID *) safe, (size_t) saved); + bufPtr->nextAdded += saved; + dst += saved; + dstLen -= saved; + saved = 0; + } + + Tcl_UtfToExternal(NULL, encoding, stage, stageLen, flags, + &chanPtr->outputEncodingState, dst, + dstLen + BUFFER_PADDING, &stageRead, &dstWrote, NULL); + if (stageRead + dstWrote == 0) { + /* + * We have an incomplete UTF-8 character at the end of the + * staging buffer. It will get moved to the beginning of the + * staging buffer followed by more bytes from src. + */ + + src -= stageLen; + srcLen += stageLen; + stageLen = 0; + savedLF = 0; + break; + } + bufPtr->nextAdded += dstWrote; + if (bufPtr->nextAdded > bufPtr->bufLength) { + /* + * 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 = bufPtr->nextAdded - bufPtr->bufLength; + memcpy((VOID *) safe, (VOID *) (dst + dstLen), (size_t) saved); + bufPtr->nextAdded = bufPtr->bufLength; + } + if (CheckFlush(chanPtr, bufPtr, sawLF) != 0) { + return -1; + } + + total += dstWrote; + stage += stageRead; + stageLen -= stageRead; + sawLF = 0; + } + } + return total; +} + +/* + *--------------------------------------------------------------------------- + * + * TranslateOutputEOL -- + * + * Helper function for WriteBytes() and WriteChars(). Converts the + * '\n' characters in the source buffer into the appropriate EOL + * form specified by the output translation mode. + * + * EOL translation stops either when the source buffer is empty + * or the output buffer is full. + * + * When converting to CRLF mode and there is only 1 byte left in + * the output buffer, this routine stores the '\r' in the last + * byte and then stores the '\n' in the byte just past the end of the + * buffer. The caller is responsible for passing in a buffer that + * is large enough to hold the extra byte. + * + * Results: + * The return value is 1 if a '\n' was translated from the source + * buffer, or 0 otherwise -- this can be used by the caller to + * decide to flush a line-based channel even though the channel + * buffer is not full. + * + * *dstLenPtr is filled with how many bytes of the output buffer + * were used. As mentioned above, this can be one more that + * the output buffer's specified length if a CRLF was stored. + * + * *srcLenPtr is filled with how many bytes of the source buffer + * were consumed. + * + * Side effects: + * It may be obvious, but bears mentioning that when converting + * in CRLF mode (which requires two bytes of storage in the output + * buffer), the number of bytes consumed from the source buffer + * will be less than the number of bytes stored in the output buffer. + * + *--------------------------------------------------------------------------- + */ + +static int +TranslateOutputEOL(chanPtr, dst, src, dstLenPtr, srcLenPtr) + Channel *chanPtr; /* Channel being read, for translation and + * buffering modes. */ + char *dst; /* Output buffer filled with UTF-8 chars by + * applying appropriate EOL translation to + * source characters. */ + CONST char *src; /* Source UTF-8 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. */ +{ + char *dstEnd; + int srcLen, newlineFound; + + newlineFound = 0; + srcLen = *srcLenPtr; + + switch (chanPtr->outputTranslation) { + case TCL_TRANSLATE_LF: { + for (dstEnd = dst + srcLen; dst < dstEnd; ) { + if (*src == '\n') { + newlineFound = 1; + } + *dst++ = *src++; + } + *dstLenPtr = srcLen; + break; + } + case TCL_TRANSLATE_CR: { + for (dstEnd = dst + srcLen; dst < dstEnd;) { + if (*src == '\n') { + *dst++ = '\r'; + newlineFound = 1; + src++; + } else { + *dst++ = *src++; + } + } + *dstLenPtr = srcLen; + break; + } + case TCL_TRANSLATE_CRLF: { + /* + * Since this causes the number of bytes to grow, we + * start off trying to put 'srcLen' bytes into the + * output buffer, but allow it to store more bytes, as + * long as there's still source bytes and room in the + * output buffer. + */ + + char *dstStart, *dstMax; + CONST char *srcStart; + + dstStart = dst; + dstMax = dst + *dstLenPtr; + + srcStart = src; + + if (srcLen < *dstLenPtr) { + dstEnd = dst + srcLen; + } else { + dstEnd = dst + *dstLenPtr; + } + while (dst < dstEnd) { + if (*src == '\n') { + if (dstEnd < dstMax) { + dstEnd++; + } + *dst++ = '\r'; + newlineFound = 1; + } + *dst++ = *src++; + } + *srcLenPtr = src - srcStart; + *dstLenPtr = dst - dstStart; + break; + } + default: { + break; + } + } + return newlineFound; +} + +/* + *--------------------------------------------------------------------------- + * + * CheckFlush -- + * + * Helper function for WriteBytes() and WriteChars(). If the + * channel buffer is ready to be flushed, flush it. + * + * Results: + * The return value is -1 if there was a problem flushing the + * channel buffer, or 0 otherwise. + * + * Side effects: + * The buffer will be recycled if it is flushed. + * + *--------------------------------------------------------------------------- + */ + +static int +CheckFlush(chanPtr, bufPtr, newlineFlag) + Channel *chanPtr; /* Channel being read, for buffering mode. */ + ChannelBuffer *bufPtr; /* Channel buffer to possibly flush. */ + int newlineFlag; /* Non-zero if a the channel buffer + * contains a newline. */ +{ + /* + * The current buffer is ready for output: + * 1. if it is full. + * 2. if it contains a newline and this channel is line-buffered. + * 3. if it contains any output and this channel is unbuffered. + */ + + if ((chanPtr->flags & BUFFER_READY) == 0) { + if (bufPtr->nextAdded == bufPtr->bufLength) { + chanPtr->flags |= BUFFER_READY; + } else if (chanPtr->flags & CHANNEL_LINEBUFFERED) { + if (newlineFlag != 0) { + chanPtr->flags |= BUFFER_READY; + } + } else if (chanPtr->flags & CHANNEL_UNBUFFERED) { + chanPtr->flags |= BUFFER_READY; + } + } + if (chanPtr->flags & BUFFER_READY) { + if (FlushChannel(NULL, chanPtr, 0) != 0) { + return -1; + } + } + return 0; +} + +/* + *--------------------------------------------------------------------------- + * + * 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(chan, lineRead) + 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, length; + char *string; + + objPtr = Tcl_NewObj(); + charsStored = Tcl_GetsObj(chan, objPtr); + if (charsStored > 0) { + string = Tcl_GetStringFromObj(objPtr, &length); + Tcl_DStringAppend(lineRead, string, length); + } + Tcl_DecrRefCount(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(chan, objPtr) + 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; + int inEofChar, skip, copiedTotal; + ChannelBuffer *bufPtr; + Tcl_Encoding encoding; + char *dst, *dstEnd, *eol, *eof; + Tcl_EncodingState oldState; + int oldLength, oldFlags, oldRemoved; + + chanPtr = (Channel *) chan; + if (CheckChannelErrors(chanPtr, TCL_READABLE) != 0) { + copiedTotal = -1; + goto done; + } + + bufPtr = chanPtr->inQueueHead; + encoding = chanPtr->encoding; + + /* + * Preserved so we can restore the channel's state in case we don't + * find a newline in the available input. + */ + + Tcl_GetStringFromObj(objPtr, &oldLength); + oldFlags = chanPtr->inputEncodingFlags; + oldState = chanPtr->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. To avoid circularity problems, + * "iso8859-1" is builtin to Tcl. + */ + + if (encoding == NULL) { + encoding = Tcl_GetEncoding(NULL, "iso8859-1"); + } + + /* + * 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 = chanPtr->inEofChar; + + 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. + */ + + eol = dst; + switch (chanPtr->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 (eol >= dstEnd) { + int offset; + + 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: { + skip = 1; + if (chanPtr->flags & INPUT_SAW_CR) { + chanPtr->flags &= ~INPUT_SAW_CR; + if (*eol == '\n') { + /* + * Skip the raw bytes that make up the '\n'. + */ + + char tmp[1 + TCL_UTF_MAX]; + int rawRead; + + bufPtr = gs.bufPtr; + Tcl_ExternalToUtf(NULL, gs.encoding, + bufPtr->buf + bufPtr->nextRemoved, + gs.rawRead, chanPtr->inputEncodingFlags, + &gs.state, tmp, 1 + 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. + */ + + int offset; + + offset = eol - objPtr->bytes; + dst = dstEnd; + PeekAhead(chanPtr, &dstEnd, &gs); + eol = objPtr->bytes + offset; + if (eol >= dstEnd) { + eol--; + chanPtr->flags |= 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; + chanPtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF); + chanPtr->inputEncodingFlags |= TCL_ENCODING_END; + } + if (chanPtr->flags & CHANNEL_EOF) { + skip = 0; + eol = dstEnd; + if (eol == objPtr->bytes) { + /* + * If we didn't produce any bytes before encountering EOF, + * caller needs to see -1. + */ + + Tcl_SetObjLength(objPtr, 0); + CommonGetsCleanup(chanPtr, encoding); + copiedTotal = -1; + 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: + bufPtr = gs.bufPtr; + chanPtr->inputEncodingState = gs.state; + Tcl_ExternalToUtf(NULL, gs.encoding, bufPtr->buf + bufPtr->nextRemoved, + gs.rawRead, chanPtr->inputEncodingFlags, + &chanPtr->inputEncodingState, dst, eol - dst + skip + TCL_UTF_MAX, + &gs.rawRead, NULL, &gs.charsWrote); + bufPtr->nextRemoved += gs.rawRead; + + /* + * Recycle all the emptied buffers. + */ + + Tcl_SetObjLength(objPtr, eol - objPtr->bytes); + CommonGetsCleanup(chanPtr, encoding); + chanPtr->flags &= ~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: + bufPtr = chanPtr->inQueueHead; + bufPtr->nextRemoved = oldRemoved; + + for (bufPtr = bufPtr->nextPtr; bufPtr != NULL; bufPtr = bufPtr->nextPtr) { + bufPtr->nextRemoved = BUFFER_PADDING; + } + CommonGetsCleanup(chanPtr, encoding); + + chanPtr->inputEncodingState = oldState; + chanPtr->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. + */ + + chanPtr->flags |= CHANNEL_NEED_MORE_DATA; + copiedTotal = -1; + + done: + /* + * Update the notifier state so we don't block while there is still + * data in the buffers. + */ + + UpdateInterest(chanPtr); + return copiedTotal; +} + +/* + *--------------------------------------------------------------------------- + * + * 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(chanPtr, gsPtr) + Channel *chanPtr; /* Channel to read. */ + GetsState *gsPtr; /* Current state of gets operation. */ +{ + ChannelBuffer *bufPtr; + char *raw, *rawStart, *rawEnd; + char *dst; + int offset, toRead, dstNeeded, spaceLeft, result, rawLen, length; + Tcl_Obj *objPtr; +#define ENCODING_LINESIZE 30 /* 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 (bufPtr->nextRemoved >= bufPtr->nextAdded) { + 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 (chanPtr->flags & CHANNEL_BLOCKED) { + if (chanPtr->flags & CHANNEL_NONBLOCKING) { + gsPtr->charsWrote = 0; + gsPtr->rawRead = 0; + return -1; + } + chanPtr->flags &= ~CHANNEL_BLOCKED; + } + if (GetInput(chanPtr) != 0) { + gsPtr->charsWrote = 0; + gsPtr->rawRead = 0; + return -1; + } + bufPtr = chanPtr->inQueueTail; + gsPtr->bufPtr = bufPtr; + } + + /* + * 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. + */ + + rawStart = bufPtr->buf + bufPtr->nextRemoved; + raw = rawStart; + rawEnd = bufPtr->buf + bufPtr->nextAdded; + rawLen = rawEnd - rawStart; + + dst = *gsPtr->dstPtr; + offset = dst - objPtr->bytes; + toRead = ENCODING_LINESIZE; + if (toRead > rawLen) { + toRead = rawLen; + } + dstNeeded = toRead * TCL_UTF_MAX + 1; + spaceLeft = objPtr->length - offset - TCL_UTF_MAX - 1; + if (dstNeeded > spaceLeft) { + length = offset * 2; + if (offset < dstNeeded) { + length = offset + dstNeeded; + } + length += TCL_UTF_MAX + 1; + Tcl_SetObjLength(objPtr, length); + spaceLeft = length - offset; + dst = objPtr->bytes + offset; + *gsPtr->dstPtr = dst; + } + gsPtr->state = chanPtr->inputEncodingState; + result = Tcl_ExternalToUtf(NULL, gsPtr->encoding, raw, rawLen, + chanPtr->inputEncodingFlags, &chanPtr->inputEncodingState, + dst, spaceLeft, &gsPtr->rawRead, &gsPtr->bytesWrote, + &gsPtr->charsWrote); + 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 (bufPtr->nextAdded < bufPtr->bufLength) { + 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 (chanPtr->flags & 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. + */ + + goto read; + } + } else { + if (nextPtr == NULL) { + nextPtr = AllocChannelBuffer(chanPtr->bufSize); + bufPtr->nextPtr = nextPtr; + chanPtr->inQueueTail = nextPtr; + } + extra = rawLen - gsPtr->rawRead; + memcpy((VOID *) (nextPtr->buf + BUFFER_PADDING - extra), + (VOID *) (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(chanPtr, dstEndPtr, gsPtr) + 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. */ +{ + 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 = bufPtr->nextAdded - (bufPtr->nextRemoved + gsPtr->rawRead); + if (bytesLeft == 0) { + if (bufPtr->nextAdded < bufPtr->bufLength) { + /* + * Don't peek ahead if last read was short read. + */ + + goto cleanup; + } + if ((chanPtr->flags & CHANNEL_NONBLOCKING) == 0) { + blockModeProc = chanPtr->typePtr->blockModeProc; + if (blockModeProc == NULL) { + /* + * Don't peek ahead if cannot set non-blocking mode. + */ + + goto cleanup; + } + (*blockModeProc)(chanPtr->instanceData, TCL_MODE_NONBLOCKING); + } + } + } + if (FilterInputBytes(chanPtr, gsPtr) == 0) { + *dstEndPtr = *gsPtr->dstPtr + gsPtr->bytesWrote; + } + if (blockModeProc != NULL) { + (*blockModeProc)(chanPtr->instanceData, 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(chanPtr, encoding) + Channel *chanPtr; + Tcl_Encoding encoding; +{ + ChannelBuffer *bufPtr, *nextPtr; + + bufPtr = chanPtr->inQueueHead; + for ( ; bufPtr != NULL; bufPtr = nextPtr) { + nextPtr = bufPtr->nextPtr; + if (bufPtr->nextRemoved < bufPtr->nextAdded) { + break; + } + RecycleBuffer(chanPtr, bufPtr, 0); + } + chanPtr->inQueueHead = bufPtr; + if (bufPtr == NULL) { + chanPtr->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 = bufPtr->bufLength - bufPtr->nextAdded; + if (extra > 0) { + memcpy((VOID *) (bufPtr->buf + bufPtr->nextAdded), + (VOID *) (nextPtr->buf + BUFFER_PADDING - extra), + (size_t) extra); + bufPtr->nextAdded += extra; + nextPtr->nextRemoved = BUFFER_PADDING; + } + bufPtr = nextPtr; + } + } + if (chanPtr->encoding == NULL) { + Tcl_FreeEncoding(encoding); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_Read -- + * + * Reads a given number of bytes from a channel. EOL and EOF + * translation is done on the bytes being read, so the 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(chan, dst, bytesToRead) + 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; + + chanPtr = (Channel *) chan; + if (CheckChannelErrors(chanPtr, TCL_READABLE) != 0) { + return -1; + } + + return DoRead(chanPtr, dst, bytesToRead); +} + +/* + *--------------------------------------------------------------------------- + * + * 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(chan, objPtr, toRead, appendFlag) + 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; + int offset, factor, copied, copiedNow, result; + ChannelBuffer *bufPtr; + Tcl_Encoding encoding; +#define UTF_EXPANSION_FACTOR 1024 + + chanPtr = (Channel *) chan; + if (CheckChannelErrors(chanPtr, TCL_READABLE) != 0) { + copied = -1; + goto done; + } + + encoding = chanPtr->encoding; + factor = UTF_EXPANSION_FACTOR; + + if (appendFlag == 0) { + if (encoding == NULL) { + Tcl_SetByteArrayLength(objPtr, 0); + } else { + Tcl_SetObjLength(objPtr, 0); + } + offset = 0; + } else { + if (encoding == NULL) { + Tcl_GetByteArrayFromObj(objPtr, &offset); + } else { + Tcl_GetStringFromObj(objPtr, &offset); + } + } + + for (copied = 0; (unsigned) toRead > 0; ) { + copiedNow = -1; + if (chanPtr->inQueueHead != NULL) { + if (encoding == NULL) { + copiedNow = ReadBytes(chanPtr, objPtr, toRead, &offset); + } else { + copiedNow = ReadChars(chanPtr, objPtr, toRead, &offset, + &factor); + } + + /* + * If the current buffer is empty recycle it. + */ + + bufPtr = chanPtr->inQueueHead; + if (bufPtr->nextRemoved == bufPtr->nextAdded) { + ChannelBuffer *nextPtr; + + nextPtr = bufPtr->nextPtr; + RecycleBuffer(chanPtr, bufPtr, 0); + chanPtr->inQueueHead = nextPtr; + if (nextPtr == NULL) { + chanPtr->inQueueTail = nextPtr; + } + } + } + if (copiedNow < 0) { + if (chanPtr->flags & CHANNEL_EOF) { + break; + } + if (chanPtr->flags & CHANNEL_BLOCKED) { + if (chanPtr->flags & CHANNEL_NONBLOCKING) { + break; + } + chanPtr->flags &= ~CHANNEL_BLOCKED; + } + result = GetInput(chanPtr); + if (result != 0) { + if (result == EAGAIN) { + break; + } + copied = -1; + goto done; + } + } else { + copied += copiedNow; + toRead -= copiedNow; + } + } + chanPtr->flags &= ~CHANNEL_BLOCKED; + if (encoding == NULL) { + Tcl_SetByteArrayLength(objPtr, offset); + } else { + Tcl_SetObjLength(objPtr, offset); + } + + done: + /* + * Update the notifier state so we don't block while there is still + * data in the buffers. + */ + + UpdateInterest(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 + * and *offsetPtr is filled with the total number of bytes in the + * object (greater than the return value if there were already bytes + * in the object). + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +static int +ReadBytes(chanPtr, objPtr, bytesToRead, offsetPtr) + Channel *chanPtr; /* The channel to read. */ + int bytesToRead; /* Maximum number of characters to store, + * or < 0 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. */ + 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 *offsetPtr; /* On input, contains how many bytes of + * objPtr have been used to hold data. On + * output, filled with how many bytes are now + * being used. */ +{ + int toRead, srcLen, srcRead, dstWrote, offset, length; + ChannelBuffer *bufPtr; + char *src, *dst; + + offset = *offsetPtr; + + bufPtr = chanPtr->inQueueHead; + src = bufPtr->buf + bufPtr->nextRemoved; + srcLen = bufPtr->nextAdded - bufPtr->nextRemoved; + + toRead = bytesToRead; + if ((unsigned) toRead > (unsigned) srcLen) { + toRead = srcLen; + } + + dst = (char *) Tcl_GetByteArrayFromObj(objPtr, &length); + if (toRead > length - offset - 1) { + /* + * Double the existing size of the object or make enough room to + * hold all the characters we may get from the source buffer, + * whichever is larger. + */ + + length = offset * 2; + if (offset < toRead) { + length = offset + toRead + 1; + } + dst = (char *) Tcl_SetByteArrayLength(objPtr, length); + } + dst += offset; + + if (chanPtr->flags & INPUT_NEED_NL) { + chanPtr->flags &= ~INPUT_NEED_NL; + if ((srcLen == 0) || (*src != '\n')) { + *dst = '\r'; + *offsetPtr += 1; + return 1; + } + *dst++ = '\n'; + src++; + srcLen--; + toRead--; + } + + srcRead = srcLen; + dstWrote = toRead; + if (TranslateInputEOL(chanPtr, dst, src, &dstWrote, &srcRead) != 0) { + if (dstWrote == 0) { + return -1; + } + } + bufPtr->nextRemoved += srcRead; + *offsetPtr += dstWrote; + return dstWrote; +} + +/* + *--------------------------------------------------------------------------- + * + * 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. + * + * 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(chanPtr, objPtr, charsToRead, offsetPtr, factorPtr) + Channel *chanPtr; /* The channel to read. */ + 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. */ + 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 *offsetPtr; /* On input, contains how many bytes of + * objPtr have been used to hold data. On + * output, filled with how many bytes are now + * being used. */ + 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. */ +{ + int toRead, factor, offset, spaceLeft, length; + int srcLen, srcRead, dstNeeded, dstRead, dstWrote, numChars; + ChannelBuffer *bufPtr; + char *src, *dst; + Tcl_EncodingState oldState; + + factor = *factorPtr; + offset = *offsetPtr; + + bufPtr = chanPtr->inQueueHead; + src = bufPtr->buf + bufPtr->nextRemoved; + srcLen = bufPtr->nextAdded - bufPtr->nextRemoved; + + toRead = charsToRead; + if ((unsigned) toRead > (unsigned) srcLen) { + toRead = srcLen; + } + + /* + * '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. + */ + + dstNeeded = toRead * factor / UTF_EXPANSION_FACTOR; + spaceLeft = objPtr->length - offset - TCL_UTF_MAX - 1; + + if (dstNeeded > spaceLeft) { + /* + * Double the existing size of the object or make enough room to + * hold all the characters we want from the source buffer, + * whichever is larger. + */ + + length = offset * 2; + if (offset < dstNeeded) { + length = offset + dstNeeded; + } + spaceLeft = length - offset; + length += TCL_UTF_MAX + 1; + Tcl_SetObjLength(objPtr, length); + } + if (toRead == srcLen) { + /* + * Want to convert the whole buffer in one pass. If we have + * enough space, convert it using all available space in object + * rather than using the factor. + */ + + dstNeeded = spaceLeft; + } + dst = objPtr->bytes + offset; + + oldState = chanPtr->inputEncodingState; + if (chanPtr->flags & INPUT_NEED_NL) { + /* + * We want a '\n' because the last character we saw was '\r'. + */ + + chanPtr->flags &= ~INPUT_NEED_NL; + Tcl_ExternalToUtf(NULL, chanPtr->encoding, src, srcLen, + chanPtr->inputEncodingFlags, &chanPtr->inputEncodingState, + dst, TCL_UTF_MAX + 1, &srcRead, &dstWrote, &numChars); + if ((dstWrote > 0) && (*dst == '\n')) { + /* + * The next char was a '\n'. Consume it and produce a '\n'. + */ + + bufPtr->nextRemoved += srcRead; + } else { + /* + * The next char was not a '\n'. Produce a '\r'. + */ + + *dst = '\r'; + } + chanPtr->inputEncodingFlags &= ~TCL_ENCODING_START; + *offsetPtr += 1; + return 1; + } + + Tcl_ExternalToUtf(NULL, chanPtr->encoding, src, srcLen, + chanPtr->inputEncodingFlags, &chanPtr->inputEncodingState, dst, + dstNeeded + TCL_UTF_MAX, &srcRead, &dstWrote, &numChars); + if (srcRead == 0) { + /* + * Not enough bytes in src buffer to make a complete char. Copy + * the bytes to the next buffer to make a new contiguous string, + * then tell the caller to fill the buffer with more bytes. + */ + + ChannelBuffer *nextPtr; + + nextPtr = bufPtr->nextPtr; + if (nextPtr == NULL) { + /* + * There isn't enough data in the buffers to complete the next + * character, so we need to wait for more data before the next + * file event can be delivered. + */ + + chanPtr->flags |= CHANNEL_NEED_MORE_DATA; + return -1; + } + nextPtr->nextRemoved -= srcLen; + memcpy((VOID *) (nextPtr->buf + nextPtr->nextRemoved), (VOID *) src, + (size_t) srcLen); + RecycleBuffer(chanPtr, bufPtr, 0); + chanPtr->inQueueHead = nextPtr; + return ReadChars(chanPtr, objPtr, charsToRead, offsetPtr, factorPtr); + } + + dstRead = dstWrote; + if (TranslateInputEOL(chanPtr, dst, dst, &dstWrote, &dstRead) != 0) { + /* + * Hit EOF char. How many bytes of src correspond to where the + * EOF was located in dst? + */ + + if (dstWrote == 0) { + return -1; + } + chanPtr->inputEncodingState = oldState; + Tcl_ExternalToUtf(NULL, chanPtr->encoding, src, srcLen, + chanPtr->inputEncodingFlags, &chanPtr->inputEncodingState, + dst, dstRead + TCL_UTF_MAX, &srcRead, &dstWrote, &numChars); + TranslateInputEOL(chanPtr, dst, dst, &dstWrote, &dstRead); + } + + /* + * The number of characters that we got may be less than the number + * that we started with because "\r\n" sequences may have been + * turned into just '\n' in dst. + */ + + numChars -= (dstRead - dstWrote); + + if ((unsigned) numChars > (unsigned) toRead) { + /* + * Got too many chars. + */ + + char *eof; + + eof = Tcl_UtfAtIndex(dst, toRead); + chanPtr->inputEncodingState = oldState; + Tcl_ExternalToUtf(NULL, chanPtr->encoding, src, srcLen, + chanPtr->inputEncodingFlags, &chanPtr->inputEncodingState, + dst, eof - dst + TCL_UTF_MAX, &srcRead, &dstWrote, &numChars); + dstRead = dstWrote; + TranslateInputEOL(chanPtr, dst, dst, &dstWrote, &dstRead); + numChars -= (dstRead - dstWrote); + } + chanPtr->inputEncodingFlags &= ~TCL_ENCODING_START; + + bufPtr->nextRemoved += srcRead; + if (dstWrote > srcRead + 1) { + *factorPtr = dstWrote * UTF_EXPANSION_FACTOR / srcRead; + } + *offsetPtr += 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 int +TranslateInputEOL(chanPtr, dstStart, srcStart, dstLenPtr, srcLenPtr) + Channel *chanPtr; /* 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; must be <= *srcLenPtr. 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. */ +{ + int dstLen, srcLen, inEofChar; + CONST char *eof; + + dstLen = *dstLenPtr; + + eof = NULL; + inEofChar = chanPtr->inEofChar; + if (inEofChar != '\0') { + /* + * Find EOF in translated buffer then compress out the EOL. The + * source buffer may be much longer than the destination buffer -- + * we only want to return EOF if the EOF has been copied to the + * destination buffer. + */ + + CONST char *src, *srcMax; + + srcMax = srcStart + *srcLenPtr; + for (src = srcStart; src < srcMax; src++) { + if (*src == inEofChar) { + eof = src; + srcLen = src - srcStart; + if (srcLen < dstLen) { + dstLen = srcLen; + } + *srcLenPtr = srcLen; + break; + } + } + } + switch (chanPtr->inputTranslation) { + case TCL_TRANSLATE_LF: { + if (dstStart != srcStart) { + memcpy((VOID *) dstStart, (VOID *) srcStart, (size_t) dstLen); + } + srcLen = dstLen; + break; + } + case TCL_TRANSLATE_CR: { + char *dst, *dstEnd; + + if (dstStart != srcStart) { + memcpy((VOID *) dstStart, (VOID *) srcStart, (size_t) dstLen); + } + dstEnd = dstStart + dstLen; + for (dst = dstStart; dst < dstEnd; dst++) { + if (*dst == '\r') { + *dst = '\n'; + } + } + srcLen = dstLen; + break; + } + case TCL_TRANSLATE_CRLF: { + char *dst; + CONST char *src, *srcEnd, *srcMax; + + dst = dstStart; + src = srcStart; + srcEnd = srcStart + dstLen; + srcMax = srcStart + *srcLenPtr; + + for ( ; src < srcEnd; ) { + if (*src == '\r') { + src++; + if (src >= srcMax) { + chanPtr->flags |= INPUT_NEED_NL; + } else if (*src == '\n') { + *dst++ = *src++; + } else { + *dst++ = '\r'; + } + } else { + *dst++ = *src++; + } + } + srcLen = src - srcStart; + dstLen = dst - dstStart; + break; + } + case TCL_TRANSLATE_AUTO: { + char *dst; + CONST char *src, *srcEnd, *srcMax; + + dst = dstStart; + src = srcStart; + srcEnd = srcStart + dstLen; + srcMax = srcStart + *srcLenPtr; + + if ((chanPtr->flags & INPUT_SAW_CR) && (src < srcMax)) { + if (*src == '\n') { + src++; + } + chanPtr->flags &= ~INPUT_SAW_CR; + } + for ( ; src < srcEnd; ) { + if (*src == '\r') { + src++; + if (src >= srcMax) { + chanPtr->flags |= INPUT_SAW_CR; + } else if (*src == '\n') { + if (srcEnd < srcMax) { + srcEnd++; + } + src++; + } + *dst++ = '\n'; + } else { + *dst++ = *src++; + } + } + srcLen = src - srcStart; + dstLen = dst - dstStart; + break; + } + default: { /* lint. */ + return 0; + } + } + *dstLenPtr = dstLen; + + if ((eof != NULL) && (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. + */ + + chanPtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF); + chanPtr->inputEncodingFlags |= TCL_ENCODING_END; + chanPtr->flags &= ~(INPUT_SAW_CR | INPUT_NEED_NL); + return 1; + } + + *srcLenPtr = srcLen; + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * 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(chan, str, len, atEnd) + Tcl_Channel chan; /* The channel for which to add the input. */ + 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. */ + ChannelBuffer *bufPtr; /* Buffer to contain the data. */ + int i, flags; + + chanPtr = (Channel *) chan; + + /* + * CheckChannelErrors clears too many flag bits in this one case. + */ + + flags = chanPtr->flags; + if (CheckChannelErrors(chanPtr, TCL_READABLE) != 0) { + len = -1; + goto done; + } + chanPtr->flags = flags; + + /* + * If we have encountered a sticky EOF, just punt without storing. + * (sticky EOF is set if we have seen the input eofChar, to prevent + * reading beyond the eofChar). Otherwise, clear the EOF flags, and + * clear the BLOCKED bit. We want to discover these conditions anew + * in each operation. + */ + + if (chanPtr->flags & CHANNEL_STICKY_EOF) { + goto done; + } + chanPtr->flags &= (~(CHANNEL_BLOCKED | CHANNEL_EOF)); + + bufPtr = AllocChannelBuffer(len); + for (i = 0; i < len; i++) { + bufPtr->buf[i] = str[i]; + } + bufPtr->nextAdded += len; + + if (chanPtr->inQueueHead == (ChannelBuffer *) NULL) { + bufPtr->nextPtr = (ChannelBuffer *) NULL; + chanPtr->inQueueHead = bufPtr; + chanPtr->inQueueTail = bufPtr; + } else if (atEnd) { + bufPtr->nextPtr = (ChannelBuffer *) NULL; + chanPtr->inQueueTail->nextPtr = bufPtr; + chanPtr->inQueueTail = bufPtr; + } else { + bufPtr->nextPtr = chanPtr->inQueueHead; + chanPtr->inQueueHead = bufPtr; + } + + done: + /* + * Update the notifier state so we don't block while there is still + * data in the buffers. + */ + + UpdateInterest(chanPtr); + return len; } /* *---------------------------------------------------------------------- * @@ -2283,45 +4197,20 @@ { int result; /* Of calling FlushChannel. */ Channel *chanPtr; /* The actual channel. */ chanPtr = (Channel *) chan; - - /* - * Check for unreported error. - */ - - if (chanPtr->unreportedError != 0) { - Tcl_SetErrno(chanPtr->unreportedError); - chanPtr->unreportedError = 0; - return TCL_ERROR; - } - - /* - * If the channel is not open for writing punt. - */ - - if (!(chanPtr->flags & TCL_WRITABLE)) { - Tcl_SetErrno(EACCES); - return TCL_ERROR; - } - - /* - * If the channel is in the middle of a background copy, fail. - */ - - if (chanPtr->csPtr) { - Tcl_SetErrno(EBUSY); + if (CheckChannelErrors(chanPtr, TCL_WRITABLE) != 0) { return -1; } /* * Force current output buffer to be output also. */ - if ((chanPtr->curOutPtr != (ChannelBuffer *) NULL) && - (chanPtr->curOutPtr->nextAdded > 0)) { + if ((chanPtr->curOutPtr != NULL) + && (chanPtr->curOutPtr->nextAdded > 0)) { chanPtr->flags |= BUFFER_READY; } result = FlushChannel(NULL, chanPtr, 0); if (result != 0) { @@ -2378,72 +4267,70 @@ } } } /* - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- * * GetInput -- * - * Reads input data from a device or file into an input buffer. + * Reads input data from a device into a channel buffer. * * Results: - * A Posix error code or 0. + * 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(chanPtr) - Channel *chanPtr; /* Channel to read input from. */ + 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. */ + 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. */ /* * 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,chanPtr)) return EINVAL; + if (CheckForDeadChannel(NULL, chanPtr)) { + return EINVAL; + } /* * 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. */ - if ((chanPtr->inQueueTail != (ChannelBuffer *) NULL) && - (chanPtr->inQueueTail->nextAdded < chanPtr->inQueueTail->bufSize)) { - bufPtr = chanPtr->inQueueTail; - toRead = bufPtr->bufSize - bufPtr->nextAdded; - } else { - if (chanPtr->saveInBufPtr != (ChannelBuffer *) NULL) { - bufPtr = chanPtr->saveInBufPtr; - chanPtr->saveInBufPtr = (ChannelBuffer *) NULL; - } else { - bufPtr = (ChannelBuffer *) ckalloc( - ((unsigned) CHANNELBUFFER_HEADER_SIZE + chanPtr->bufSize)); - bufPtr->bufSize = chanPtr->bufSize; - } - bufPtr->nextRemoved = 0; - bufPtr->nextAdded = 0; - toRead = bufPtr->bufSize; - if (chanPtr->inQueueTail == (ChannelBuffer *) NULL) { + bufPtr = chanPtr->inQueueTail; + if ((bufPtr != NULL) && (bufPtr->nextAdded < bufPtr->bufLength)) { + toRead = bufPtr->bufLength - bufPtr->nextAdded; + } else { + bufPtr = chanPtr->saveInBufPtr; + chanPtr->saveInBufPtr = NULL; + if (bufPtr == NULL) { + bufPtr = AllocChannelBuffer(chanPtr->bufSize); + } + bufPtr->nextPtr = (ChannelBuffer *) NULL; + + toRead = chanPtr->bufSize; + if (chanPtr->inQueueTail == NULL) { chanPtr->inQueueHead = bufPtr; } else { chanPtr->inQueueTail->nextPtr = bufPtr; } chanPtr->inQueueTail = bufPtr; - bufPtr->nextPtr = (ChannelBuffer *) NULL; } /* * If EOF is set, we should avoid calling the driver because on some * platforms it is impossible to read from a device after EOF. @@ -2451,29 +4338,14 @@ if (chanPtr->flags & CHANNEL_EOF) { return 0; } - nread = (chanPtr->typePtr->inputProc) (chanPtr->instanceData, + nread = (*chanPtr->typePtr->inputProc)(chanPtr->instanceData, bufPtr->buf + bufPtr->nextAdded, toRead, &result); - if (nread == 0) { - chanPtr->flags |= CHANNEL_EOF; - } else if (nread < 0) { - if ((result == EWOULDBLOCK) || (result == EAGAIN)) { - chanPtr->flags |= CHANNEL_BLOCKED; - result = EAGAIN; - if (chanPtr->flags & CHANNEL_NONBLOCKING) { - Tcl_SetErrno(result); - } else { - panic("Blocking channel driver did not block on input"); - } - } else { - Tcl_SetErrno(result); - } - return result; - } else { + if (nread > 0) { bufPtr->nextAdded += nread; /* * If we get a short read, signal up that we may be BLOCKED. We * should avoid calling the driver because on some platforms we @@ -2482,910 +4354,22 @@ */ if (nread < toRead) { chanPtr->flags |= CHANNEL_BLOCKED; } - } - return 0; -} - -/* - *---------------------------------------------------------------------- - * - * CopyAndTranslateBuffer -- - * - * Copy at most one buffer of input to the result space, doing - * eol translations according to mode in effect currently. - * - * Results: - * Number of characters (as opposed to bytes) copied. May return - * zero if no input is available to be translated. - * - * Side effects: - * Consumes buffered input. May deallocate one buffer. - * - *---------------------------------------------------------------------- - */ - -static int -CopyAndTranslateBuffer(chanPtr, result, space) - Channel *chanPtr; /* The channel from which to read input. */ - char *result; /* Where to store the copied input. */ - int space; /* How many bytes are available in result - * to store the copied input? */ -{ - int bytesInBuffer; /* How many bytes are available to be - * copied in the current input buffer? */ - int copied; /* How many characters were already copied - * into the destination space? */ - ChannelBuffer *bufPtr; /* The buffer from which to copy bytes. */ - char curByte; /* The byte we are currently translating. */ - int i; /* Iterates over the copied input looking - * for the input eofChar. */ - - /* - * If there is no input at all, return zero. The invariant is that either - * there is no buffer in the queue, or if the first buffer is empty, it - * is also the last buffer (and thus there is no input in the queue). - * Note also that if the buffer is empty, we leave it in the queue. - */ - - if (chanPtr->inQueueHead == (ChannelBuffer *) NULL) { - return 0; - } - bufPtr = chanPtr->inQueueHead; - bytesInBuffer = bufPtr->nextAdded - bufPtr->nextRemoved; - if (bytesInBuffer < space) { - space = bytesInBuffer; - } - copied = 0; - switch (chanPtr->inputTranslation) { - case TCL_TRANSLATE_LF: - - if (space == 0) { - return 0; - } - - /* - * Copy the current chunk into the result buffer. - */ - - memcpy((VOID *) result, - (VOID *)(bufPtr->buf + bufPtr->nextRemoved), - (size_t) space); - bufPtr->nextRemoved += space; - copied = space; - break; - - case TCL_TRANSLATE_CR: - - if (space == 0) { - return 0; - } - - /* - * Copy the current chunk into the result buffer, then - * replace all \r with \n. - */ - - memcpy((VOID *) result, - (VOID *)(bufPtr->buf + bufPtr->nextRemoved), - (size_t) space); - bufPtr->nextRemoved += space; - for (copied = 0; copied < space; copied++) { - if (result[copied] == '\r') { - result[copied] = '\n'; - } - } - break; - - case TCL_TRANSLATE_CRLF: - - /* - * If there is a held-back "\r" at EOF, produce it now. - */ - - if (space == 0) { - if ((chanPtr->flags & (INPUT_SAW_CR | CHANNEL_EOF)) == - (INPUT_SAW_CR | CHANNEL_EOF)) { - result[0] = '\r'; - chanPtr->flags &= (~(INPUT_SAW_CR)); - return 1; - } - return 0; - } - - /* - * Copy the current chunk and replace "\r\n" with "\n" - * (but not standalone "\r"!). - */ - - for (copied = 0; - (copied < space) && - (bufPtr->nextRemoved < bufPtr->nextAdded); - copied++) { - curByte = bufPtr->buf[bufPtr->nextRemoved]; - bufPtr->nextRemoved++; - if (curByte == '\r') { - if (chanPtr->flags & INPUT_SAW_CR) { - result[copied] = '\r'; - } else { - chanPtr->flags |= INPUT_SAW_CR; - copied--; - } - } else if (curByte == '\n') { - chanPtr->flags &= (~(INPUT_SAW_CR)); - result[copied] = '\n'; - } else { - if (chanPtr->flags & INPUT_SAW_CR) { - chanPtr->flags &= (~(INPUT_SAW_CR)); - result[copied] = '\r'; - bufPtr->nextRemoved--; - } else { - result[copied] = curByte; - } - } - } - break; - - case TCL_TRANSLATE_AUTO: - - if (space == 0) { - return 0; - } - - /* - * Loop over the current buffer, converting "\r" and "\r\n" - * to "\n". - */ - - for (copied = 0; - (copied < space) && - (bufPtr->nextRemoved < bufPtr->nextAdded); ) { - curByte = bufPtr->buf[bufPtr->nextRemoved]; - bufPtr->nextRemoved++; - if (curByte == '\r') { - result[copied] = '\n'; - copied++; - if (bufPtr->nextRemoved < bufPtr->nextAdded) { - if (bufPtr->buf[bufPtr->nextRemoved] == '\n') { - bufPtr->nextRemoved++; - } - chanPtr->flags &= (~(INPUT_SAW_CR)); - } else { - chanPtr->flags |= INPUT_SAW_CR; - } - } else { - if (curByte == '\n') { - if (!(chanPtr->flags & INPUT_SAW_CR)) { - result[copied] = '\n'; - copied++; - } - } else { - result[copied] = curByte; - copied++; - } - chanPtr->flags &= (~(INPUT_SAW_CR)); - } - } - break; - - default: - panic("unknown eol translation mode"); - } - - /* - * If an in-stream EOF character is set for this channel,, check that - * the input we copied so far does not contain the EOF char. If it does, - * copy only up to and excluding that character. - */ - - if (chanPtr->inEofChar != 0) { - for (i = 0; i < copied; i++) { - if (result[i] == (char) chanPtr->inEofChar) { - break; - } - } - if (i < copied) { - - /* - * Set sticky EOF so that no further input is presented - * to the caller. - */ - - chanPtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF); - - /* - * Reset the start of valid data in the input buffer to the - * position of the eofChar, so that subsequent reads will - * encounter it immediately. First we set it to the position - * of the last byte consumed if all result bytes were the - * product of one input byte; since it is possible that "\r\n" - * contracted to "\n" in the result, we have to search back - * from that position until we find the eofChar, because it - * is possible that its actual position in the buffer is n - * bytes further back (n is the number of "\r\n" sequences - * that were contracted to "\n" in the result). - */ - - bufPtr->nextRemoved -= (copied - i); - while ((bufPtr->nextRemoved > 0) && - (bufPtr->buf[bufPtr->nextRemoved] != - (char) chanPtr->inEofChar)) { - bufPtr->nextRemoved--; - } - copied = i; - } - } - - /* - * If the current buffer is empty recycle it. - */ - - if (bufPtr->nextRemoved == bufPtr->nextAdded) { - chanPtr->inQueueHead = bufPtr->nextPtr; - if (chanPtr->inQueueHead == (ChannelBuffer *) NULL) { - chanPtr->inQueueTail = (ChannelBuffer *) NULL; - } - RecycleBuffer(chanPtr, bufPtr, 0); - } - - /* - * Return the number of characters copied into the result buffer. - * This may be different from the number of bytes consumed, because - * of EOL translations. - */ - - return copied; -} - -/* - *---------------------------------------------------------------------- - * - * ScanBufferForEOL -- - * - * Scans one buffer for EOL according to the specified EOL - * translation mode. If it sees the input eofChar for the channel - * it stops also. - * - * Results: - * TRUE if EOL is found, FALSE otherwise. Also sets output parameter - * bytesToEOLPtr to the number of bytes so far to EOL, and crSeenPtr - * to whether a "\r" was seen. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -ScanBufferForEOL(chanPtr, bufPtr, translation, eofChar, bytesToEOLPtr, - crSeenPtr) - Channel *chanPtr; - ChannelBuffer *bufPtr; /* Buffer to scan for EOL. */ - Tcl_EolTranslation translation; /* Translation mode to use. */ - int eofChar; /* EOF char to look for. */ - int *bytesToEOLPtr; /* Running counter. */ - int *crSeenPtr; /* Has "\r" been seen? */ -{ - char *rPtr; /* Iterates over input string. */ - char *sPtr; /* Where to stop search? */ - int EOLFound; - int bytesToEOL; - - for (EOLFound = 0, rPtr = bufPtr->buf + bufPtr->nextRemoved, - sPtr = bufPtr->buf + bufPtr->nextAdded, - bytesToEOL = *bytesToEOLPtr; - (!EOLFound) && (rPtr < sPtr); - rPtr++) { - switch (translation) { - case TCL_TRANSLATE_AUTO: - if ((*rPtr == (char) eofChar) && (eofChar != 0)) { - chanPtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF); - EOLFound = 1; - } else if (*rPtr == '\n') { - - /* - * CopyAndTranslateBuffer wants to know the length - * of the result, not the input. The input is one - * larger because "\r\n" shrinks to "\n". - */ - - if (!(*crSeenPtr)) { - bytesToEOL++; - EOLFound = 1; - } else { - - /* - * This is a lf at the begining of a buffer - * where the previous buffer ended in a cr. - * Consume this lf because we've already emitted - * the newline for this crlf sequence. ALSO, if - * bytesToEOL is 0 (which means that we are at the - * first character of the scan), unset the - * INPUT_SAW_CR flag in the channel, because we - * already handled it; leaving it set would cause - * CopyAndTranslateBuffer to potentially consume - * another lf if one follows the current byte. - */ - - bufPtr->nextRemoved++; - *crSeenPtr = 0; - chanPtr->flags &= (~(INPUT_SAW_CR)); - } - } else if (*rPtr == '\r') { - bytesToEOL++; - EOLFound = 1; - } else { - *crSeenPtr = 0; - bytesToEOL++; - } - break; - case TCL_TRANSLATE_LF: - if ((*rPtr == (char) eofChar) && (eofChar != 0)) { - chanPtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF); - EOLFound = 1; - } else { - if (*rPtr == '\n') { - EOLFound = 1; - } - bytesToEOL++; - } - break; - case TCL_TRANSLATE_CR: - if ((*rPtr == (char) eofChar) && (eofChar != 0)) { - chanPtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF); - EOLFound = 1; - } else { - if (*rPtr == '\r') { - EOLFound = 1; - } - bytesToEOL++; - } - break; - case TCL_TRANSLATE_CRLF: - if ((*rPtr == (char) eofChar) && (eofChar != 0)) { - chanPtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF); - EOLFound = 1; - } else if (*rPtr == '\n') { - - /* - * CopyAndTranslateBuffer wants to know the length - * of the result, not the input. The input is one - * larger because crlf shrinks to lf. - */ - - if (*crSeenPtr) { - EOLFound = 1; - } else { - bytesToEOL++; - } - } else { - if (*rPtr == '\r') { - *crSeenPtr = 1; - } else { - *crSeenPtr = 0; - } - bytesToEOL++; - } - break; - default: - panic("unknown eol translation mode"); - } - } - - *bytesToEOLPtr = bytesToEOL; - return EOLFound; -} - -/* - *---------------------------------------------------------------------- - * - * ScanInputForEOL -- - * - * Scans queued input for chanPtr for an end of line (according to the - * current EOL translation mode) and returns the number of bytes - * upto and including the end of line, or -1 if none was found. - * - * Results: - * Count of bytes upto and including the end of line if one is present - * or -1 if none was found. Also returns in an output parameter the - * number of bytes queued if no end of line was found. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -ScanInputForEOL(chanPtr, bytesQueuedPtr) - Channel *chanPtr; /* Channel for which to scan queued - * input for end of line. */ - int *bytesQueuedPtr; /* Where to store the number of bytes - * currently queued if no end of line - * was found. */ -{ - ChannelBuffer *bufPtr; /* Iterates over queued buffers. */ - int bytesToEOL; /* How many bytes to end of line? */ - int EOLFound; /* Did we find an end of line? */ - int crSeen; /* Did we see a "\r" in CRLF mode? */ - - *bytesQueuedPtr = 0; - bytesToEOL = 0; - EOLFound = 0; - for (bufPtr = chanPtr->inQueueHead, - crSeen = (chanPtr->flags & INPUT_SAW_CR) ? 1 : 0; - (!EOLFound) && (bufPtr != (ChannelBuffer *) NULL); - bufPtr = bufPtr->nextPtr) { - EOLFound = ScanBufferForEOL(chanPtr, bufPtr, chanPtr->inputTranslation, - chanPtr->inEofChar, &bytesToEOL, &crSeen); - } - - if (EOLFound == 0) { - *bytesQueuedPtr = bytesToEOL; - return -1; - } - return bytesToEOL; -} - -/* - *---------------------------------------------------------------------- - * - * GetEOL -- - * - * Accumulate input into the channel input buffer queue until an - * end of line has been seen. - * - * Results: - * Number of bytes buffered (at least 1) or -1 on failure. - * - * Side effects: - * Consumes input from the channel. - * - *---------------------------------------------------------------------- - */ - -static int -GetEOL(chanPtr) - Channel *chanPtr; /* Channel to queue input on. */ -{ - int bytesToEOL; /* How many bytes in buffer up to and - * including the end of line? */ - int bytesQueued; /* How many bytes are queued currently - * in the input chain of the channel? */ - - /* - * Check for unreported error. - */ - - if (chanPtr->unreportedError != 0) { - Tcl_SetErrno(chanPtr->unreportedError); - chanPtr->unreportedError = 0; - return -1; - } - - /* - * Punt if the channel is not opened for reading. - */ - - if (!(chanPtr->flags & TCL_READABLE)) { - Tcl_SetErrno(EACCES); - return -1; - } - - /* - * If the channel is in the middle of a background copy, fail. - */ - - if (chanPtr->csPtr) { - Tcl_SetErrno(EBUSY); - return -1; - } - - /* - * If we have not encountered a sticky EOF, clear the EOF bit - * (sticky EOF is set if we have seen the input eofChar, to prevent - * reading beyond the eofChar). Also, always clear the BLOCKED bit. - * We want to discover these conditions anew in each operation. - */ - - if (!(chanPtr->flags & CHANNEL_STICKY_EOF)) { - chanPtr->flags &= (~(CHANNEL_EOF)); - } - chanPtr->flags &= (~(CHANNEL_BLOCKED | CHANNEL_GETS_BLOCKED)); - - while (1) { - bytesToEOL = ScanInputForEOL(chanPtr, &bytesQueued); - if (bytesToEOL > 0) { - chanPtr->flags &= (~(CHANNEL_BLOCKED)); - return bytesToEOL; - } - if (chanPtr->flags & CHANNEL_EOF) { - /* - * Boundary case where cr was at the end of the previous buffer - * and this buffer just has a newline. At EOF our caller wants - * to see -1 for the line length. - */ - return (bytesQueued == 0) ? -1 : bytesQueued ; - } - if (chanPtr->flags & CHANNEL_BLOCKED) { - if (chanPtr->flags & CHANNEL_NONBLOCKING) { - goto blocked; - } - chanPtr->flags &= (~(CHANNEL_BLOCKED)); - } - if (GetInput(chanPtr) != 0) { - goto blocked; - } - } - - blocked: - - /* - * 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. - */ - - chanPtr->flags |= CHANNEL_GETS_BLOCKED; - return -1; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_Read -- - * - * Reads a given number of characters from a channel. - * - * 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_Read(chan, bufPtr, toRead) - Tcl_Channel chan; /* The channel from which to read. */ - char *bufPtr; /* Where to store input read. */ - int toRead; /* Maximum number of characters to read. */ -{ - Channel *chanPtr; /* The real IO channel. */ - - chanPtr = (Channel *) chan; - - /* - * Check for unreported error. - */ - - if (chanPtr->unreportedError != 0) { - Tcl_SetErrno(chanPtr->unreportedError); - chanPtr->unreportedError = 0; - return -1; - } - - /* - * Punt if the channel is not opened for reading. - */ - - if (!(chanPtr->flags & TCL_READABLE)) { - Tcl_SetErrno(EACCES); - return -1; - } - - /* - * If the channel is in the middle of a background copy, fail. - */ - - if (chanPtr->csPtr) { - Tcl_SetErrno(EBUSY); - return -1; - } - - return DoRead(chanPtr, bufPtr, toRead); -} - -/* - *---------------------------------------------------------------------- - * - * DoRead -- - * - * Reads a given number of characters from a channel. - * - * 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 -DoRead(chanPtr, bufPtr, toRead) - Channel *chanPtr; /* The channel from which to read. */ - char *bufPtr; /* Where to store input read. */ - int toRead; /* Maximum number of characters to read. */ -{ - int copied; /* How many characters were copied into - * the result string? */ - int copiedNow; /* How many characters were copied from - * the current input buffer? */ - int result; /* Of calling GetInput. */ - - /* - * If we have not encountered a sticky EOF, clear the EOF bit. Either - * way clear the BLOCKED bit. We want to discover these anew during - * each operation. - */ - - if (!(chanPtr->flags & CHANNEL_STICKY_EOF)) { - chanPtr->flags &= (~(CHANNEL_EOF)); - } - chanPtr->flags &= (~(CHANNEL_BLOCKED | CHANNEL_GETS_BLOCKED)); - - for (copied = 0; copied < toRead; copied += copiedNow) { - copiedNow = CopyAndTranslateBuffer(chanPtr, bufPtr + copied, - toRead - copied); - if (copiedNow == 0) { - if (chanPtr->flags & CHANNEL_EOF) { - return copied; - } - if (chanPtr->flags & CHANNEL_BLOCKED) { - if (chanPtr->flags & CHANNEL_NONBLOCKING) { - return copied; - } - chanPtr->flags &= (~(CHANNEL_BLOCKED)); - } - result = GetInput(chanPtr); - if (result != 0) { - if (result == EAGAIN) { - return copied; - } - return -1; - } - } - } - chanPtr->flags &= (~(CHANNEL_BLOCKED)); - return copied; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_Gets -- - * - * Reads a complete line of input from the channel into a - * Tcl_DString. - * - * Results: - * Length of line read 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(chan, lineRead) - Tcl_Channel chan; /* Channel from which to read. */ - Tcl_DString *lineRead; /* The characters of the line read - * (excluding the terminating newline if - * present) will be appended to this - * DString. The caller must have initialized - * it and is responsible for managing the - * storage. */ -{ - Channel *chanPtr; /* The channel to read from. */ - char *buf; /* Points into DString where data - * will be stored. */ - int offset; /* Offset from start of DString at - * which to append the line just read. */ - int copiedTotal; /* Accumulates total length of input copied. */ - int copiedNow; /* How many bytes were copied from the - * current input buffer? */ - int lineLen; /* Length of line read, including the - * translated newline. If this is zero - * and neither EOF nor BLOCKED is set, - * the current line is empty. */ - - chanPtr = (Channel *) chan; - - lineLen = GetEOL(chanPtr); - if (lineLen < 0) { - return -1; - } - offset = Tcl_DStringLength(lineRead); - Tcl_DStringSetLength(lineRead, lineLen + offset); - buf = Tcl_DStringValue(lineRead) + offset; - - for (copiedTotal = 0; copiedTotal < lineLen; copiedTotal += copiedNow) { - copiedNow = CopyAndTranslateBuffer(chanPtr, buf + copiedTotal, - lineLen - copiedTotal); - } - if ((copiedTotal > 0) && (buf[copiedTotal - 1] == '\n')) { - copiedTotal--; - } - Tcl_DStringSetLength(lineRead, copiedTotal + offset); - return copiedTotal; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_GetsObj -- - * - * Reads a complete line of input from the channel into a - * string object. - * - * Results: - * Length of line read 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_GetsObj(chan, objPtr) - Tcl_Channel chan; /* Channel from which to read. */ - Tcl_Obj *objPtr; /* The characters of the line read - * (excluding the terminating newline if - * present) will be appended to this - * object. The caller must have initialized - * it and is responsible for managing the - * storage. */ -{ - Channel *chanPtr; /* The channel to read from. */ - char *buf; /* Points into DString where data - * will be stored. */ - int offset; /* Offset from start of DString at - * which to append the line just read. */ - int copiedTotal; /* Accumulates total length of input copied. */ - int copiedNow; /* How many bytes were copied from the - * current input buffer? */ - int lineLen; /* Length of line read, including the - * translated newline. If this is zero - * and neither EOF nor BLOCKED is set, - * the current line is empty. */ - - chanPtr = (Channel *) chan; - - lineLen = GetEOL(chanPtr); - if (lineLen < 0) { - return -1; - } - (void) Tcl_GetStringFromObj(objPtr, &offset); - Tcl_SetObjLength(objPtr, lineLen + offset); - buf = Tcl_GetStringFromObj(objPtr, NULL) + offset; - - for (copiedTotal = 0; copiedTotal < lineLen; copiedTotal += copiedNow) { - copiedNow = CopyAndTranslateBuffer(chanPtr, buf + copiedTotal, - lineLen - copiedTotal); - } - if ((copiedTotal > 0) && (buf[copiedTotal - 1] == '\n')) { - copiedTotal--; - } - Tcl_SetObjLength(objPtr, copiedTotal + offset); - return copiedTotal; -} - -/* - *---------------------------------------------------------------------- - * - * 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(chan, str, len, atEnd) - Tcl_Channel chan; /* The channel for which to add the input. */ - 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. */ - ChannelBuffer *bufPtr; /* Buffer to contain the data. */ - int i; - - chanPtr = (Channel *) chan; - - /* - * Check for unreported error. - */ - - if (chanPtr->unreportedError != 0) { - Tcl_SetErrno(chanPtr->unreportedError); - chanPtr->unreportedError = 0; - return -1; - } - - /* - * Punt if the channel is not opened for reading. - */ - - if (!(chanPtr->flags & TCL_READABLE)) { - Tcl_SetErrno(EACCES); - return -1; - } - - /* - * If the channel is in the middle of a background copy, fail. - */ - - if (chanPtr->csPtr) { - Tcl_SetErrno(EBUSY); - return -1; - } - - /* - * If we have encountered a sticky EOF, just punt without storing. - * (sticky EOF is set if we have seen the input eofChar, to prevent - * reading beyond the eofChar). Otherwise, clear the EOF flags, and - * clear the BLOCKED bit. We want to discover these conditions anew - * in each operation. - */ - - if (chanPtr->flags & CHANNEL_STICKY_EOF) { - return len; - } - chanPtr->flags &= (~(CHANNEL_BLOCKED | CHANNEL_EOF)); - - bufPtr = (ChannelBuffer *) ckalloc((unsigned) - (CHANNELBUFFER_HEADER_SIZE + len)); - for (i = 0; i < len; i++) { - bufPtr->buf[i] = str[i]; - } - bufPtr->bufSize = len; - bufPtr->nextAdded = len; - bufPtr->nextRemoved = 0; - - if (chanPtr->inQueueHead == (ChannelBuffer *) NULL) { - bufPtr->nextPtr = (ChannelBuffer *) NULL; - chanPtr->inQueueHead = bufPtr; - chanPtr->inQueueTail = bufPtr; - } else if (atEnd) { - bufPtr->nextPtr = (ChannelBuffer *) NULL; - chanPtr->inQueueTail->nextPtr = bufPtr; - chanPtr->inQueueTail = bufPtr; - } else { - bufPtr->nextPtr = chanPtr->inQueueHead; - chanPtr->inQueueHead = bufPtr; - } - - return len; + } else if (nread == 0) { + chanPtr->flags |= CHANNEL_EOF; + chanPtr->inputEncodingFlags |= TCL_ENCODING_END; + } else if (nread < 0) { + if ((result == EWOULDBLOCK) || (result == EAGAIN)) { + chanPtr->flags |= CHANNEL_BLOCKED; + result = EAGAIN; + } + Tcl_SetErrno(result); + return result; + } + return 0; } /* *---------------------------------------------------------------------- * @@ -3418,37 +4402,11 @@ int wasAsync; /* Was the channel nonblocking before the * seek operation? If so, must restore to * nonblocking mode after the seek. */ chanPtr = (Channel *) chan; - - /* - * Check for unreported error. - */ - - if (chanPtr->unreportedError != 0) { - Tcl_SetErrno(chanPtr->unreportedError); - chanPtr->unreportedError = 0; - return -1; - } - - /* - * Disallow seek on channels that are open for neither writing nor - * reading (e.g. socket server channels). - */ - - if (!(chanPtr->flags & (TCL_WRITABLE|TCL_READABLE))) { - Tcl_SetErrno(EACCES); - return -1; - } - - /* - * If the channel is in the middle of a background copy, fail. - */ - - if (chanPtr->csPtr) { - Tcl_SetErrno(EBUSY); + if (CheckChannelErrors(chanPtr, TCL_WRITABLE | TCL_READABLE) != 0) { return -1; } /* * Disallow seek on dead channels -- channels that have been closed but @@ -3620,46 +4578,22 @@ int inputBuffered, outputBuffered; int result; /* Of calling device driver. */ int curPos; /* Position on device. */ chanPtr = (Channel *) chan; - - /* - * Check for unreported error. - */ - - if (chanPtr->unreportedError != 0) { - Tcl_SetErrno(chanPtr->unreportedError); - chanPtr->unreportedError = 0; - return -1; + if (CheckChannelErrors(chanPtr, TCL_WRITABLE | TCL_READABLE) != 0) { + return -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,chanPtr)) return -1; - - /* - * Disallow tell on channels that are open for neither - * writing nor reading (e.g. socket server channels). - */ - - if (!(chanPtr->flags & (TCL_WRITABLE|TCL_READABLE))) { - Tcl_SetErrno(EACCES); - return -1; - } - - /* - * If the channel is in the middle of a background copy, fail. - */ - - if (chanPtr->csPtr) { - Tcl_SetErrno(EBUSY); + if (CheckForDeadChannel(NULL,chanPtr)) { return -1; } /* * Disallow tell on channels whose type does not have a seek procedure @@ -3712,10 +4646,79 @@ if (inputBuffered != 0) { return (curPos - inputBuffered); } return (curPos + outputBuffered); } + +/* + *--------------------------------------------------------------------------- + * + * 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(chanPtr, direction) + Channel *chanPtr; /* Channel to check. */ + int direction; /* Test if channel supports desired operation: + * TCL_READABLE, TCL_WRITABLE. */ +{ + /* + * Check for unreported error. + */ + + if (chanPtr->unreportedError != 0) { + Tcl_SetErrno(chanPtr->unreportedError); + chanPtr->unreportedError = 0; + return -1; + } + + /* + * Fail if the channel is not opened for desired operation. + */ + + if ((chanPtr->flags & direction) == 0) { + Tcl_SetErrno(EACCES); + return -1; + } + + /* + * Fail if the channel is in the middle of a background copy. + */ + + if (chanPtr->csPtr != NULL) { + Tcl_SetErrno(EBUSY); + return -1; + } + + if (direction == TCL_READABLE) { + /* + * If we have not encountered a sticky EOF, clear the EOF bit + * (sticky EOF is set if we have seen the input eofChar, to prevent + * reading beyond the eofChar). Also, always clear the BLOCKED bit. + * We want to discover these conditions anew in each operation. + */ + + if ((chanPtr->flags & CHANNEL_STICKY_EOF) == 0) { + chanPtr->flags &= ~CHANNEL_EOF; + } + chanPtr->flags &= ~(CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA); + } + + return 0; +} /* *---------------------------------------------------------------------- * * Tcl_Eof -- @@ -3841,10 +4844,19 @@ return; } chanPtr = (Channel *) chan; chanPtr->bufSize = sz; + + if (chanPtr->outputStage != NULL) { + ckfree((char *) chanPtr->outputStage); + chanPtr->outputStage = NULL; + } + if ((chanPtr->encoding != NULL) && (chanPtr->flags & TCL_WRITABLE)) { + chanPtr->outputStage = (char *) + ckalloc((unsigned) (chanPtr->bufSize + 2)); + } } /* *---------------------------------------------------------------------- * @@ -4045,11 +5057,27 @@ if (len > 0) { return TCL_OK; } } if ((len == 0) || - ((len > 1) && (optionName[1] == 'e') && + ((len > 2) && (optionName[1] == 'e') && + (strncmp(optionName, "-encoding", len) == 0))) { + if (len == 0) { + Tcl_DStringAppendElement(dsPtr, "-encoding"); + } + if (chanPtr->encoding == NULL) { + Tcl_DStringAppendElement(dsPtr, "binary"); + } else { + Tcl_DStringAppendElement(dsPtr, + Tcl_GetEncodingName(chanPtr->encoding)); + } + if (len > 0) { + return TCL_OK; + } + } + if ((len == 0) || + ((len > 2) && (optionName[1] == 'e') && (strncmp(optionName, "-eofchar", len) == 0))) { if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-eofchar"); } if (((flags & (TCL_READABLE|TCL_WRITABLE)) == @@ -4143,24 +5171,24 @@ return Tcl_BadChannelOption(interp, optionName, NULL); } } /* - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- * * Tcl_SetChannelOption -- * * Sets an option on a channel. * * Results: - * A standard Tcl result. Also sets interp->result on error if - * interp is not NULL. + * 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(interp, chan, optionName, newValue) Tcl_Interp *interp; /* For error reporting - can be NULL. */ @@ -4210,13 +5238,11 @@ newMode = TCL_MODE_BLOCKING; } else { newMode = TCL_MODE_NONBLOCKING; } return SetBlockMode(interp, chanPtr, newMode); - } - - if ((len > 7) && (optionName[1] == 'b') && + } else if ((len > 7) && (optionName[1] == 'b') && (strncmp(optionName, "-buffering", len) == 0)) { len = strlen(newValue); if ((newValue[0] == 'f') && (strncmp(newValue, "full", len) == 0)) { chanPtr->flags &= (~(CHANNEL_UNBUFFERED|CHANNEL_LINEBUFFERED)); @@ -4234,23 +5260,38 @@ "must be one of full, line, or none", (char *) NULL); return TCL_ERROR; } } - return TCL_OK; - } - - if ((len > 7) && (optionName[1] == 'b') && + return TCL_OK; + } else if ((len > 7) && (optionName[1] == 'b') && (strncmp(optionName, "-buffersize", len) == 0)) { - chanPtr->bufSize = atoi(newValue); + chanPtr->bufSize = atoi(newValue); /* INTL: "C", UTF safe. */ if ((chanPtr->bufSize < 10) || (chanPtr->bufSize > (1024 * 1024))) { chanPtr->bufSize = CHANNELBUFFER_DEFAULT_SIZE; } - return TCL_OK; - } - - if ((len > 1) && (optionName[1] == 'e') && + } else if ((len > 2) && (optionName[1] == 'e') && + (strncmp(optionName, "-encoding", len) == 0)) { + 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; + } + } + Tcl_FreeEncoding(chanPtr->encoding); + chanPtr->encoding = encoding; + chanPtr->inputEncodingState = NULL; + chanPtr->inputEncodingFlags = TCL_ENCODING_START; + chanPtr->outputEncodingState = NULL; + chanPtr->outputEncodingFlags = TCL_ENCODING_START; + chanPtr->flags &= ~CHANNEL_NEED_MORE_DATA; + UpdateInterest(chanPtr); + } else if ((len > 2) && (optionName[1] == 'e') && (strncmp(optionName, "-eofchar", len) == 0)) { if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } if (argc == 0) { @@ -4280,14 +5321,12 @@ } } if (argv != (char **) NULL) { ckfree((char *) argv); } - return TCL_OK; - } - - if ((len > 1) && (optionName[1] == 't') && + return TCL_OK; + } else if ((len > 1) && (optionName[1] == 't') && (strncmp(optionName, "-translation", len) == 0)) { char *readMode, *writeMode; if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; @@ -4313,12 +5352,14 @@ if (*readMode == '\0') { newMode = chanPtr->inputTranslation; } else if (strcmp(readMode, "auto") == 0) { newMode = TCL_TRANSLATE_AUTO; } else if (strcmp(readMode, "binary") == 0) { - chanPtr->inEofChar = 0; newMode = TCL_TRANSLATE_LF; + chanPtr->inEofChar = 0; + Tcl_FreeEncoding(chanPtr->encoding); + chanPtr->encoding = NULL; } else if (strcmp(readMode, "lf") == 0) { newMode = TCL_TRANSLATE_LF; } else if (strcmp(readMode, "cr") == 0) { newMode = TCL_TRANSLATE_CR; } else if (strcmp(readMode, "crlf") == 0) { @@ -4343,11 +5384,11 @@ */ if (newMode != chanPtr->inputTranslation) { chanPtr->inputTranslation = (Tcl_EolTranslation) newMode; chanPtr->flags &= ~(INPUT_SAW_CR); - chanPtr->flags &= ~(CHANNEL_GETS_BLOCKED); + chanPtr->flags &= ~(CHANNEL_NEED_MORE_DATA); UpdateInterest(chanPtr); } } if (writeMode) { if (*writeMode == '\0') { @@ -4366,10 +5407,12 @@ chanPtr->outputTranslation = TCL_PLATFORM_TRANSLATION; } } else if (strcmp(writeMode, "binary") == 0) { chanPtr->outEofChar = 0; chanPtr->outputTranslation = TCL_TRANSLATE_LF; + Tcl_FreeEncoding(chanPtr->encoding); + chanPtr->encoding = NULL; } else if (strcmp(writeMode, "lf") == 0) { chanPtr->outputTranslation = TCL_TRANSLATE_LF; } else if (strcmp(writeMode, "cr") == 0) { chanPtr->outputTranslation = TCL_TRANSLATE_CR; } else if (strcmp(writeMode, "crlf") == 0) { @@ -4387,18 +5430,48 @@ return TCL_ERROR; } } ckfree((char *) argv); return TCL_OK; - } - - if (chanPtr->typePtr->setOptionProc != (Tcl_DriverSetOptionProc *) NULL) { - return (chanPtr->typePtr->setOptionProc) (chanPtr->instanceData, + } else if (chanPtr->typePtr->setOptionProc != NULL) { + return (*chanPtr->typePtr->setOptionProc)(chanPtr->instanceData, interp, optionName, newValue); + } else { + return Tcl_BadChannelOption(interp, optionName, (char *) NULL); + } + + /* + * If bufsize changes, need to get rid of old utility buffer. + */ + + if (chanPtr->saveInBufPtr != NULL) { + RecycleBuffer(chanPtr, chanPtr->saveInBufPtr, 1); + chanPtr->saveInBufPtr = NULL; + } + if (chanPtr->inQueueHead != NULL) { + if ((chanPtr->inQueueHead->nextPtr == NULL) + && (chanPtr->inQueueHead->nextAdded == + chanPtr->inQueueHead->nextRemoved)) { + RecycleBuffer(chanPtr, chanPtr->inQueueHead, 1); + chanPtr->inQueueHead = NULL; + chanPtr->inQueueTail = NULL; + } + } + + /* + * If encoding or bufsize changes, need to update output staging buffer. + */ + + if (chanPtr->outputStage != NULL) { + ckfree((char *) chanPtr->outputStage); + chanPtr->outputStage = NULL; + } + if ((chanPtr->encoding != NULL) && (chanPtr->flags & TCL_WRITABLE)) { + chanPtr->outputStage = (char *) + ckalloc((unsigned) (chanPtr->bufSize + 2)); } - - return Tcl_BadChannelOption(interp, optionName, (char *) NULL); + return TCL_OK; } /* *---------------------------------------------------------------------- * @@ -4444,11 +5517,11 @@ } Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, ChannelEventScriptInvoker, (ClientData) sPtr); - ckfree(sPtr->script); + Tcl_DecrRefCount(sPtr->scriptPtr); ckfree((char *) sPtr); } else { prevPtr = sPtr; } } @@ -4480,13 +5553,18 @@ * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which events were detected. */ { Channel *chanPtr = (Channel *) channel; ChannelHandler *chPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); NextChannelHandler nh; - Tcl_Preserve((ClientData)chanPtr); + /* + * Preserve the channel struct in case the script closes it. + */ + + Tcl_Preserve((ClientData) channel); /* * 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 @@ -4502,12 +5580,12 @@ * Add this invocation to the list of recursive invocations of * ChannelHandlerEventProc. */ nh.nextHandlerPtr = (ChannelHandler *) NULL; - nh.nestedHandlerPtr = nestedHandlerPtr; - nestedHandlerPtr = &nh; + nh.nestedHandlerPtr = tsdPtr->nestedHandlerPtr; + tsdPtr->nestedHandlerPtr = &nh; for (chPtr = chanPtr->chPtr; chPtr != (ChannelHandler *) NULL; ) { /* * If this channel handler is interested in any of the events that @@ -4529,13 +5607,14 @@ */ if (chanPtr->typePtr != NULL) { UpdateInterest(chanPtr); } - Tcl_Release((ClientData)chanPtr); - nestedHandlerPtr = nh.nestedHandlerPtr; + Tcl_Release((ClientData) channel); + + tsdPtr->nestedHandlerPtr = nh.nestedHandlerPtr; } /* *---------------------------------------------------------------------- * @@ -4567,18 +5646,18 @@ if (chanPtr->flags & BG_FLUSH_SCHEDULED) { mask |= TCL_WRITABLE; } /* - * If there is data in the input queue, and we aren't blocked waiting for - * an EOL, then we need to schedule a timer so we don't block in the + * 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 (!(chanPtr->flags & CHANNEL_GETS_BLOCKED) + if (!(chanPtr->flags & CHANNEL_NEED_MORE_DATA) && (chanPtr->inQueueHead != (ChannelBuffer *) NULL) && (chanPtr->inQueueHead->nextRemoved < chanPtr->inQueueHead->nextAdded)) { mask &= ~TCL_READABLE; if (!chanPtr->timer) { @@ -4611,11 +5690,11 @@ ChannelTimerProc(clientData) ClientData clientData; { Channel *chanPtr = (Channel *) clientData; - if (!(chanPtr->flags & CHANNEL_GETS_BLOCKED) + if (!(chanPtr->flags & CHANNEL_NEED_MORE_DATA) && (chanPtr->interestMask & TCL_READABLE) && (chanPtr->inQueueHead != (ChannelBuffer *) NULL) && (chanPtr->inQueueHead->nextRemoved < chanPtr->inQueueHead->nextAdded)) { /* @@ -4747,10 +5826,11 @@ * to delete. */ { ChannelHandler *chPtr, *prevChPtr; Channel *chanPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); NextChannelHandler *nhPtr; chanPtr = (Channel *) chan; /* @@ -4778,11 +5858,11 @@ /* * If ChannelHandlerEventProc is about to process this handler, tell it to * process the next one instead - we are going to delete *this* one. */ - for (nhPtr = nestedHandlerPtr; + for (nhPtr = tsdPtr->nestedHandlerPtr; nhPtr != (NextChannelHandler *) NULL; nhPtr = nhPtr->nestedHandlerPtr) { if (nhPtr->nextHandlerPtr == chPtr) { nhPtr->nextHandlerPtr = chPtr->nextPtr; } @@ -4799,11 +5879,12 @@ } ckfree((char *) chPtr); /* * Recompute the interest list for the channel, so that infinite loops - * will not result if Tcl_DeleteChanelHandler is called inside an event. + * will not result if Tcl_DeleteChannelHandler is called inside an + * event. */ chanPtr->interestMask = 0; for (chPtr = chanPtr->chPtr; chPtr != (ChannelHandler *) NULL; @@ -4854,11 +5935,11 @@ } Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, ChannelEventScriptInvoker, (ClientData) esPtr); - ckfree(esPtr->script); + Tcl_DecrRefCount(esPtr->scriptPtr); ckfree((char *) esPtr); break; } } @@ -4880,28 +5961,27 @@ * *---------------------------------------------------------------------- */ static void -CreateScriptRecord(interp, chanPtr, mask, script) +CreateScriptRecord(interp, chanPtr, mask, scriptPtr) 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. */ - char *script; /* A copy of this script is stored - * in the newly created record. */ + Tcl_Obj *scriptPtr; /* Pointer to script object. */ { EventScriptRecord *esPtr; for (esPtr = chanPtr->scriptRecordPtr; esPtr != (EventScriptRecord *) NULL; esPtr = esPtr->nextPtr) { if ((esPtr->interp == interp) && (esPtr->mask == mask)) { - ckfree(esPtr->script); - esPtr->script = (char *) NULL; + Tcl_DecrRefCount(esPtr->scriptPtr); + esPtr->scriptPtr = (Tcl_Obj *) NULL; break; } } if (esPtr == (EventScriptRecord *) NULL) { esPtr = (EventScriptRecord *) ckalloc((unsigned) @@ -4912,12 +5992,12 @@ chanPtr->scriptRecordPtr = esPtr; } esPtr->chanPtr = chanPtr; esPtr->interp = interp; esPtr->mask = mask; - esPtr->script = ckalloc((unsigned) (strlen(script) + 1)); - strcpy(esPtr->script, script); + Tcl_IncrRefCount(scriptPtr); + esPtr->scriptPtr = scriptPtr; } /* *---------------------------------------------------------------------- * @@ -4942,30 +6022,28 @@ int mask; /* Not used. */ { Tcl_Interp *interp; /* Interpreter in which to eval the script. */ Channel *chanPtr; /* The channel for which this handler is * registered. */ - char *script; /* Script to eval. */ EventScriptRecord *esPtr; /* The event script + interpreter to eval it * in. */ int result; /* Result of call to eval script. */ esPtr = (EventScriptRecord *) clientData; chanPtr = esPtr->chanPtr; mask = esPtr->mask; interp = esPtr->interp; - script = esPtr->script; - + /* * 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((ClientData) interp); - result = Tcl_GlobalEval(interp, script); + result = Tcl_EvalObjEx(interp, esPtr->scriptPtr, TCL_EVAL_GLOBAL); /* * On error, cause a background error and remove the channel handler * and the script record. * @@ -4983,11 +6061,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_FileEventCmd -- + * 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. @@ -5001,50 +6079,42 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_FileEventCmd(clientData, interp, argc, argv) +Tcl_FileEventObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Interpreter in which the channel * for which to create the handler * is found. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { Channel *chanPtr; /* The channel to create * the handler for. */ Tcl_Channel chan; /* The opaque type for the channel. */ - int c; /* First char of mode argument. */ - int mask; /* Mask for events of interest. */ - size_t length; /* Length of mode argument. */ - - /* - * Parse arguments. - */ - - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # args: must be \"", argv[0], - " channelId event ?script?", (char *) NULL); - return TCL_ERROR; - } - c = argv[2][0]; - length = strlen(argv[2]); - if ((c == 'r') && (strncmp(argv[2], "readable", length) == 0)) { - mask = TCL_READABLE; - } else if ((c == 'w') && (strncmp(argv[2], "writable", length) == 0)) { - mask = TCL_WRITABLE; - } else { - Tcl_AppendResult(interp, "bad event name \"", argv[2], - "\": must be readable or writable", (char *) NULL); - return TCL_ERROR; - } - chan = Tcl_GetChannel(interp, argv[1], NULL); - if (chan == (Tcl_Channel) NULL) { - return TCL_ERROR; - } - + char *chanName; + int modeIndex; /* Index of mode argument. */ + int mask; + static char *modeOptions[] = {"readable", "writable", NULL}; + static 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 = Tcl_GetString(objv[1]); + chan = Tcl_GetChannel(interp, chanName, NULL); + if (chan == (Tcl_Channel) NULL) { + return TCL_ERROR; + } chanPtr = (Channel *) chan; if ((chanPtr->flags & mask) == 0) { Tcl_AppendResult(interp, "channel is not ", (mask == TCL_READABLE) ? "readable" : "writable", (char *) NULL); @@ -5053,17 +6123,17 @@ /* * If we are supposed to return the script, do so. */ - if (argc == 3) { + if (objc == 3) { EventScriptRecord *esPtr; for (esPtr = chanPtr->scriptRecordPtr; esPtr != (EventScriptRecord *) NULL; esPtr = esPtr->nextPtr) { if ((esPtr->interp == interp) && (esPtr->mask == mask)) { - Tcl_SetResult(interp, esPtr->script, TCL_STATIC); + Tcl_SetObjResult(interp, esPtr->scriptPtr); break; } } return TCL_OK; } @@ -5070,11 +6140,11 @@ /* * If we are supposed to delete a stored script, do so. */ - if (argv[3][0] == 0) { + if (*(Tcl_GetString(objv[3])) == '\0') { DeleteScriptRecord(interp, chanPtr, mask); return TCL_OK; } /* @@ -5081,11 +6151,11 @@ * 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, argv[3]); + CreateScriptRecord(interp, chanPtr, mask, objv[3]); return TCL_OK; } /* @@ -5122,11 +6192,11 @@ Channel *chanPtr; /* The actual channel. */ Tcl_Channel chan; /* The opaque type. */ size_t len; /* Length of subcommand string. */ int IOQueued; /* How much IO is queued inside channel? */ ChannelBuffer *bufPtr; /* For iterating over queued IO. */ - char buf[128]; /* For sprintf. */ + char buf[TCL_INTEGER_SPACE];/* For sprintf. */ if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " subcommand ?additional args..?\"", (char *) NULL); return TCL_ERROR; @@ -5133,18 +6203,20 @@ } cmdName = argv[1]; len = strlen(cmdName); chanPtr = (Channel *) NULL; + if (argc > 2) { chan = Tcl_GetChannel(interp, argv[2], NULL); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } chanPtr = (Channel *) chan; } - + + if ((cmdName[0] == 'i') && (strncmp(cmdName, "info", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " info channelName\"", (char *) NULL); return TCL_ERROR; @@ -5259,11 +6331,11 @@ for (IOQueued = 0, bufPtr = chanPtr->inQueueHead; bufPtr != (ChannelBuffer *) NULL; bufPtr = bufPtr->nextPtr) { IOQueued += bufPtr->nextAdded - bufPtr->nextRemoved; } - sprintf(buf, "%d", IOQueued); + TclFormatInt(buf, IOQueued); Tcl_AppendResult(interp, buf, (char *) NULL); return TCL_OK; } if ((cmdName[0] == 'm') && (strncmp(cmdName, "mode", len) == 0)) { @@ -5325,11 +6397,11 @@ for (bufPtr = chanPtr->outQueueHead; bufPtr != (ChannelBuffer *) NULL; bufPtr = bufPtr->nextPtr) { IOQueued += (bufPtr->nextAdded - bufPtr->nextRemoved); } - sprintf(buf, "%d", IOQueued); + TclFormatInt(buf, IOQueued); Tcl_AppendResult(interp, buf, (char *) NULL); return TCL_OK; } if ((cmdName[0] == 'q') && @@ -5367,11 +6439,11 @@ Tcl_AppendResult(interp, "channel name required", (char *) NULL); return TCL_ERROR; } - sprintf(buf, "%d", chanPtr->refCount); + TclFormatInt(buf, chanPtr->refCount); Tcl_AppendResult(interp, buf, (char *) NULL); return TCL_OK; } if ((cmdName[0] == 't') && (strncmp(cmdName, "type", len) == 0)) { @@ -5431,10 +6503,11 @@ ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */ { + Tcl_Obj *resultListPtr; Channel *chanPtr; EventScriptRecord *esPtr, *prevEsPtr, *nextEsPtr; char *cmd; int index, i, mask, len; @@ -5473,12 +6546,12 @@ chanPtr->scriptRecordPtr = esPtr; esPtr->chanPtr = chanPtr; esPtr->interp = interp; esPtr->mask = mask; - esPtr->script = ckalloc((unsigned) (strlen(argv[4]) + 1)); - strcpy(esPtr->script, argv[4]); + esPtr->scriptPtr = Tcl_NewStringObj(argv[4], -1); + Tcl_IncrRefCount(esPtr->scriptPtr); Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask, ChannelEventScriptInvoker, (ClientData) esPtr); return TCL_OK; @@ -5522,11 +6595,11 @@ } prevEsPtr->nextPtr = esPtr->nextPtr; } Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, ChannelEventScriptInvoker, (ClientData) esPtr); - ckfree(esPtr->script); + Tcl_DecrRefCount(esPtr->scriptPtr); ckfree((char *) esPtr); return TCL_OK; } @@ -5534,23 +6607,24 @@ if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " channelName list\"", (char *) NULL); return TCL_ERROR; } + resultListPtr = Tcl_GetObjResult(interp); for (esPtr = chanPtr->scriptRecordPtr; esPtr != (EventScriptRecord *) NULL; esPtr = esPtr->nextPtr) { - char *event; if (esPtr->mask) { - event = ((esPtr->mask == TCL_READABLE) - ? "readable" : "writable"); - } else { - event = "none"; - } - Tcl_AppendElement(interp, event); - Tcl_AppendElement(interp, esPtr->script); - } + 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) { @@ -5562,11 +6636,11 @@ esPtr != (EventScriptRecord *) NULL; esPtr = nextEsPtr) { nextEsPtr = esPtr->nextPtr; Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, ChannelEventScriptInvoker, (ClientData) esPtr); - ckfree(esPtr->script); + Tcl_DecrRefCount(esPtr->scriptPtr); ckfree((char *) esPtr); } chanPtr->scriptRecordPtr = (EventScriptRecord *) NULL; return TCL_OK; } @@ -5613,11 +6687,10 @@ return TCL_OK; } Tcl_AppendResult(interp, "bad command ", cmd, ", must be one of ", "add, delete, list, set, or removeall", (char *) NULL); return TCL_ERROR; - } /* *---------------------------------------------------------------------- * @@ -5904,11 +6977,11 @@ Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewIntObj(total)); if (errObj) { Tcl_ListObjAppendElement(interp, cmdPtr, errObj); } - if (Tcl_GlobalEvalObj(interp, cmdPtr) != TCL_OK) { + if (Tcl_EvalObjEx(interp, cmdPtr, TCL_EVAL_GLOBAL) != TCL_OK) { Tcl_BackgroundError(interp); result = TCL_ERROR; } Tcl_DecrRefCount(cmdPtr); Tcl_Release((ClientData) interp); @@ -5922,10 +6995,481 @@ Tcl_SetIntObj(Tcl_GetObjResult(interp), total); } } return result; } + +/* + *---------------------------------------------------------------------- + * + * DoRead -- + * + * Reads a given number of bytes from a channel. + * + * 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 +DoRead(chanPtr, bufPtr, toRead) + Channel *chanPtr; /* The channel from which to read. */ + char *bufPtr; /* Where to store input read. */ + int toRead; /* Maximum number of bytes to read. */ +{ + int copied; /* How many characters were copied into + * the result string? */ + int copiedNow; /* How many characters were copied from + * the current input buffer? */ + int result; /* Of calling GetInput. */ + + /* + * If we have not encountered a sticky EOF, clear the EOF bit. Either + * way clear the BLOCKED bit. We want to discover these anew during + * each operation. + */ + + if (!(chanPtr->flags & CHANNEL_STICKY_EOF)) { + chanPtr->flags &= ~CHANNEL_EOF; + } + chanPtr->flags &= ~(CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA); + + for (copied = 0; copied < toRead; copied += copiedNow) { + copiedNow = CopyAndTranslateBuffer(chanPtr, bufPtr + copied, + toRead - copied); + if (copiedNow == 0) { + if (chanPtr->flags & CHANNEL_EOF) { + goto done; + } + if (chanPtr->flags & CHANNEL_BLOCKED) { + if (chanPtr->flags & CHANNEL_NONBLOCKING) { + goto done; + } + chanPtr->flags &= (~(CHANNEL_BLOCKED)); + } + result = GetInput(chanPtr); + if (result != 0) { + if (result != EAGAIN) { + copied = -1; + } + goto done; + } + } + } + + chanPtr->flags &= (~(CHANNEL_BLOCKED)); + + done: + /* + * Update the notifier state so we don't block while there is still + * data in the buffers. + */ + + UpdateInterest(chanPtr); + return copied; +} + +/* + *---------------------------------------------------------------------- + * + * CopyAndTranslateBuffer -- + * + * Copy at most one buffer of input to the result space, doing + * eol translations according to mode in effect currently. + * + * Results: + * Number of bytes stored in the result buffer (as opposed to the + * number of bytes read from the channel). May return + * zero if no input is available to be translated. + * + * Side effects: + * Consumes buffered input. May deallocate one buffer. + * + *---------------------------------------------------------------------- + */ + +static int +CopyAndTranslateBuffer(chanPtr, result, space) + Channel *chanPtr; /* The channel from which to read input. */ + char *result; /* Where to store the copied input. */ + int space; /* How many bytes are available in result + * to store the copied input? */ +{ + int bytesInBuffer; /* How many bytes are available to be + * copied in the current input buffer? */ + int copied; /* How many characters were already copied + * into the destination space? */ + ChannelBuffer *bufPtr; /* The buffer from which to copy bytes. */ + int i; /* Iterates over the copied input looking + * for the input eofChar. */ + + /* + * If there is no input at all, return zero. The invariant is that either + * there is no buffer in the queue, or if the first buffer is empty, it + * is also the last buffer (and thus there is no input in the queue). + * Note also that if the buffer is empty, we leave it in the queue. + */ + + if (chanPtr->inQueueHead == (ChannelBuffer *) NULL) { + return 0; + } + bufPtr = chanPtr->inQueueHead; + bytesInBuffer = bufPtr->nextAdded - bufPtr->nextRemoved; + + copied = 0; + switch (chanPtr->inputTranslation) { + case TCL_TRANSLATE_LF: { + if (bytesInBuffer == 0) { + return 0; + } + + /* + * Copy the current chunk into the result buffer. + */ + + if (bytesInBuffer < space) { + space = bytesInBuffer; + } + memcpy((VOID *) result, + (VOID *) (bufPtr->buf + bufPtr->nextRemoved), + (size_t) space); + bufPtr->nextRemoved += space; + copied = space; + break; + } + case TCL_TRANSLATE_CR: { + char *end; + + if (bytesInBuffer == 0) { + return 0; + } + + /* + * Copy the current chunk into the result buffer, then + * replace all \r with \n. + */ + + if (bytesInBuffer < space) { + space = bytesInBuffer; + } + memcpy((VOID *) result, + (VOID *) (bufPtr->buf + bufPtr->nextRemoved), + (size_t) space); + bufPtr->nextRemoved += space; + copied = space; + + for (end = result + copied; result < end; result++) { + if (*result == '\r') { + *result = '\n'; + } + } + break; + } + case TCL_TRANSLATE_CRLF: { + char *src, *end, *dst; + int curByte; + + /* + * If there is a held-back "\r" at EOF, produce it now. + */ + + if (bytesInBuffer == 0) { + if ((chanPtr->flags & (INPUT_SAW_CR | CHANNEL_EOF)) == + (INPUT_SAW_CR | CHANNEL_EOF)) { + result[0] = '\r'; + chanPtr->flags &= ~INPUT_SAW_CR; + return 1; + } + return 0; + } + + /* + * Copy the current chunk and replace "\r\n" with "\n" + * (but not standalone "\r"!). + */ + + if (bytesInBuffer < space) { + space = bytesInBuffer; + } + memcpy((VOID *) result, + (VOID *) (bufPtr->buf + bufPtr->nextRemoved), + (size_t) space); + bufPtr->nextRemoved += space; + copied = space; + + end = result + copied; + dst = result; + for (src = result; src < end; src++) { + curByte = *src; + if (curByte == '\n') { + chanPtr->flags &= ~INPUT_SAW_CR; + } else if (chanPtr->flags & INPUT_SAW_CR) { + chanPtr->flags &= ~INPUT_SAW_CR; + *dst = '\r'; + dst++; + } + if (curByte == '\r') { + chanPtr->flags |= INPUT_SAW_CR; + } else { + *dst = (char) curByte; + dst++; + } + } + copied = dst - result; + break; + } + case TCL_TRANSLATE_AUTO: { + char *src, *end, *dst; + int curByte; + + if (bytesInBuffer == 0) { + return 0; + } + + /* + * Loop over the current buffer, converting "\r" and "\r\n" + * to "\n". + */ + + if (bytesInBuffer < space) { + space = bytesInBuffer; + } + memcpy((VOID *) result, + (VOID *) (bufPtr->buf + bufPtr->nextRemoved), + (size_t) space); + bufPtr->nextRemoved += space; + copied = space; + + end = result + copied; + dst = result; + for (src = result; src < end; src++) { + curByte = *src; + if (curByte == '\r') { + chanPtr->flags |= INPUT_SAW_CR; + *dst = '\n'; + dst++; + } else { + if ((curByte != '\n') || + !(chanPtr->flags & INPUT_SAW_CR)) { + *dst = (char) curByte; + dst++; + } + chanPtr->flags &= ~INPUT_SAW_CR; + } + } + copied = dst - result; + break; + } + default: { + panic("unknown eol translation mode"); + } + } + + /* + * If an in-stream EOF character is set for this channel, check that + * the input we copied so far does not contain the EOF char. If it does, + * copy only up to and excluding that character. + */ + + if (chanPtr->inEofChar != 0) { + for (i = 0; i < copied; i++) { + if (result[i] == (char) chanPtr->inEofChar) { + /* + * Set sticky EOF so that no further input is presented + * to the caller. + */ + + chanPtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF); + chanPtr->inputEncodingFlags |= TCL_ENCODING_END; + copied = i; + break; + } + } + } + + /* + * If the current buffer is empty recycle it. + */ + + if (bufPtr->nextRemoved == bufPtr->nextAdded) { + chanPtr->inQueueHead = bufPtr->nextPtr; + if (chanPtr->inQueueHead == (ChannelBuffer *) NULL) { + chanPtr->inQueueTail = (ChannelBuffer *) NULL; + } + RecycleBuffer(chanPtr, bufPtr, 0); + } + + /* + * Return the number of characters copied into the result buffer. + * This may be different from the number of bytes consumed, because + * of EOL translations. + */ + + return copied; +} + +/* + *---------------------------------------------------------------------- + * + * DoWrite -- + * + * Puts a sequence of characters 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 +DoWrite(chanPtr, src, srcLen) + Channel *chanPtr; /* The channel to buffer output for. */ + char *src; /* Data to write. */ + int srcLen; /* Number of bytes to write. */ +{ + ChannelBuffer *outBufPtr; /* Current output buffer. */ + int foundNewline; /* Did we find a newline in output? */ + char *dPtr; + char *sPtr; /* Search variables for newline. */ + int crsent; /* In CRLF eol translation mode, + * remember the fact that a CR was + * output to the channel without + * its following NL. */ + int i; /* Loop index for newline search. */ + int destCopied; /* How many bytes were used in this + * destination buffer to hold the + * output? */ + int totalDestCopied; /* How many bytes total were + * copied to the channel buffer? */ + int srcCopied; /* How many bytes were copied from + * the source string? */ + char *destPtr; /* Where in line to copy to? */ + + /* + * If we are in network (or windows) translation mode, record the fact + * that we have not yet sent a CR to the channel. + */ + + crsent = 0; + + /* + * Loop filling buffers and flushing them until all output has been + * consumed. + */ + + srcCopied = 0; + totalDestCopied = 0; + + while (srcLen > 0) { + + /* + * Make sure there is a current output buffer to accept output. + */ + + if (chanPtr->curOutPtr == (ChannelBuffer *) NULL) { + chanPtr->curOutPtr = AllocChannelBuffer(chanPtr->bufSize); + } + + outBufPtr = chanPtr->curOutPtr; + + destCopied = outBufPtr->bufLength - outBufPtr->nextAdded; + if (destCopied > srcLen) { + destCopied = srcLen; + } + + destPtr = outBufPtr->buf + outBufPtr->nextAdded; + switch (chanPtr->outputTranslation) { + case TCL_TRANSLATE_LF: + srcCopied = destCopied; + memcpy((VOID *) destPtr, (VOID *) src, (size_t) destCopied); + break; + case TCL_TRANSLATE_CR: + srcCopied = destCopied; + memcpy((VOID *) destPtr, (VOID *) src, (size_t) destCopied); + for (dPtr = destPtr; dPtr < destPtr + destCopied; dPtr++) { + if (*dPtr == '\n') { + *dPtr = '\r'; + } + } + break; + case TCL_TRANSLATE_CRLF: + for (srcCopied = 0, dPtr = destPtr, sPtr = src; + dPtr < destPtr + destCopied; + dPtr++, sPtr++, srcCopied++) { + if (*sPtr == '\n') { + if (crsent) { + *dPtr = '\n'; + crsent = 0; + } else { + *dPtr = '\r'; + crsent = 1; + sPtr--, srcCopied--; + } + } else { + *dPtr = *sPtr; + } + } + break; + case TCL_TRANSLATE_AUTO: + panic("Tcl_Write: AUTO output translation mode not supported"); + default: + panic("Tcl_Write: unknown output translation mode"); + } + + /* + * The current buffer is ready for output if it is full, or if it + * contains a newline and this channel is line-buffered, or if it + * contains any output and this channel is unbuffered. + */ + + outBufPtr->nextAdded += destCopied; + if (!(chanPtr->flags & BUFFER_READY)) { + if (outBufPtr->nextAdded == outBufPtr->bufLength) { + chanPtr->flags |= BUFFER_READY; + } else if (chanPtr->flags & CHANNEL_LINEBUFFERED) { + for (sPtr = src, i = 0, foundNewline = 0; + (i < srcCopied) && (!foundNewline); + i++, sPtr++) { + if (*sPtr == '\n') { + foundNewline = 1; + break; + } + } + if (foundNewline) { + chanPtr->flags |= BUFFER_READY; + } + } else if (chanPtr->flags & CHANNEL_UNBUFFERED) { + chanPtr->flags |= BUFFER_READY; + } + } + + totalDestCopied += srcCopied; + src += srcCopied; + srcLen -= srcCopied; + + if (chanPtr->flags & BUFFER_READY) { + if (FlushChannel(NULL, chanPtr, 0) != 0) { + return -1; + } + } + } /* Closes "while" */ + + return totalDestCopied; +} /* *---------------------------------------------------------------------- * * CopyEventProc -- @@ -6009,5 +7553,51 @@ } csPtr->readPtr->csPtr = NULL; csPtr->writePtr->csPtr = NULL; ckfree((char*) csPtr); } + +/* + *---------------------------------------------------------------------- + * + * 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(interp, chanPtr, mode) + 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; + if (chanPtr->typePtr->blockModeProc != NULL) { + result = (chanPtr->typePtr->blockModeProc) (chanPtr->instanceData, + mode); + } + if (result != 0) { + Tcl_SetErrno(result); + if (interp != (Tcl_Interp *) NULL) { + Tcl_AppendResult(interp, "error setting blocking mode: ", + Tcl_PosixError(interp), (char *) NULL); + } + return TCL_ERROR; + } + if (mode == TCL_MODE_BLOCKING) { + chanPtr->flags &= (~(CHANNEL_NONBLOCKING | BG_FLUSH_SCHEDULED)); + } else { + chanPtr->flags |= CHANNEL_NONBLOCKING; + } + return TCL_OK; +} Index: generic/tclIOCmd.c ================================================================== --- generic/tclIOCmd.c +++ generic/tclIOCmd.c @@ -1,26 +1,20 @@ /* * tclIOCmd.c -- * * Contains the definitions of most of the Tcl commands relating to IO. * - * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclIOCmd.c 1.119 97/07/25 20:49:23 + * RCS: @(#) $Id: tclIOCmd.c,v 1.1.2.5 1999/03/26 22:39:53 rjohnson Exp $ */ -#include "tclInt.h" -#include "tclPort.h" - -/* - * Return at most this number of bytes in one call to Tcl_Read: - */ - -#define TCL_READ_CHUNK_SIZE 4096 +#include "tclInt.h" +#include "tclPort.h" /* * Callback structure for accept callback in a TCP server. */ @@ -74,16 +68,14 @@ char *channelId; /* Name of channel for puts. */ int result; /* Result of puts operation. */ int mode; /* Mode in which channel is opened. */ char *arg; int length; - Tcl_Obj *resultPtr; i = 1; newline = 1; - if ((objc >= 2) && (strcmp(Tcl_GetStringFromObj(objv[1], NULL), - "-nonewline") == 0)) { + if ((objc >= 2) && (strcmp(Tcl_GetString(objv[1]), "-nonewline") == 0)) { newline = 0; i++; } if ((i < (objc-3)) || (i >= objc)) { Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? ?channelId? string"); @@ -93,57 +85,50 @@ /* * The code below provides backwards compatibility with an old * form of the command that is no longer recommended or documented. */ - resultPtr = Tcl_NewObj(); if (i == (objc-3)) { - arg = Tcl_GetStringFromObj(objv[i+2], &length); + arg = Tcl_GetStringFromObj(objv[i + 2], &length); if (strncmp(arg, "nonewline", (size_t) length) != 0) { - Tcl_AppendStringsToObj(resultPtr, "bad argument \"", arg, + Tcl_AppendResult(interp, "bad argument \"", arg, "\": should be \"nonewline\"", (char *) NULL); - Tcl_SetObjResult(interp, resultPtr); return TCL_ERROR; } newline = 0; } - if (i == (objc-1)) { + if (i == (objc - 1)) { channelId = "stdout"; } else { - channelId = Tcl_GetStringFromObj(objv[i], NULL); + channelId = Tcl_GetString(objv[i]); i++; } chan = Tcl_GetChannel(interp, channelId, &mode); if (chan == (Tcl_Channel) NULL) { - Tcl_DecrRefCount(resultPtr); return TCL_ERROR; } if ((mode & TCL_WRITABLE) == 0) { - Tcl_AppendStringsToObj(resultPtr, "channel \"", channelId, + Tcl_AppendResult(interp, "channel \"", channelId, "\" wasn't opened for writing", (char *) NULL); - Tcl_SetObjResult(interp, resultPtr); return TCL_ERROR; } - arg = Tcl_GetStringFromObj(objv[i], &length); - result = Tcl_Write(chan, arg, length); + result = Tcl_WriteObj(chan, objv[i]); if (result < 0) { goto error; } if (newline != 0) { - result = Tcl_Write(chan, "\n", 1); + result = Tcl_WriteChars(chan, "\n", 1); if (result < 0) { goto error; } } - Tcl_SetObjResult(interp, resultPtr); return TCL_OK; -error: - Tcl_AppendStringsToObj(resultPtr, "error writing \"", - Tcl_GetChannelName(chan), "\": ", Tcl_PosixError(interp), - (char *) NULL); - Tcl_SetObjResult(interp, resultPtr); + + error: + Tcl_AppendResult(interp, "error writing \"", channelId, "\": ", + Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -169,35 +154,31 @@ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { Tcl_Channel chan; /* The channel to flush on. */ - char *arg; - Tcl_Obj *resultPtr; + char *channelId; int mode; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channelId"); return TCL_ERROR; } - arg = Tcl_GetStringFromObj(objv[1], NULL); - chan = Tcl_GetChannel(interp, arg, &mode); + channelId = Tcl_GetString(objv[1]); + chan = Tcl_GetChannel(interp, channelId, &mode); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } - resultPtr = Tcl_GetObjResult(interp); if ((mode & TCL_WRITABLE) == 0) { - Tcl_AppendStringsToObj(resultPtr, "channel \"", - Tcl_GetStringFromObj(objv[1], NULL), - "\" wasn't opened for writing", (char *) NULL); + Tcl_AppendResult(interp, "channel \"", channelId, + "\" wasn't opened for writing", (char *) NULL); return TCL_ERROR; } if (Tcl_Flush(chan) != TCL_OK) { - Tcl_AppendStringsToObj(resultPtr, "error flushing \"", - Tcl_GetChannelName(chan), "\": ", Tcl_PosixError(interp), - (char *) NULL); + Tcl_AppendResult(interp, "error flushing \"", channelId, "\": ", + Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } return TCL_OK; } @@ -227,55 +208,60 @@ 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. */ - char *arg; - Tcl_Obj *resultPtr, *objPtr; + char *name; + Tcl_Obj *resultPtr, *linePtr; if ((objc != 2) && (objc != 3)) { Tcl_WrongNumArgs(interp, 1, objv, "channelId ?varName?"); return TCL_ERROR; } - arg = Tcl_GetStringFromObj(objv[1], NULL); - chan = Tcl_GetChannel(interp, arg, &mode); + name = Tcl_GetString(objv[1]); + chan = Tcl_GetChannel(interp, name, &mode); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } - resultPtr = Tcl_NewObj(); if ((mode & TCL_READABLE) == 0) { - Tcl_AppendStringsToObj(resultPtr, "channel \"", arg, - "\" wasn't opened for reading", (char *) NULL); - Tcl_SetObjResult(interp, resultPtr); + Tcl_AppendResult(interp, "channel \"", name, + "\" wasn't opened for reading", (char *) NULL); return TCL_ERROR; } - lineLen = Tcl_GetsObj(chan, resultPtr); + resultPtr = Tcl_GetObjResult(interp); + linePtr = resultPtr; + if (objc == 3) { + /* + * Variable gets line, interp get bytecount. + */ + + linePtr = Tcl_NewObj(); + } + + lineLen = Tcl_GetsObj(chan, linePtr); if (lineLen < 0) { if (!Tcl_Eof(chan) && !Tcl_InputBlocked(chan)) { - Tcl_SetObjLength(resultPtr, 0); - Tcl_AppendStringsToObj(resultPtr, "error reading \"", - Tcl_GetChannelName(chan), "\": ", Tcl_PosixError(interp), - (char *) NULL); - Tcl_SetObjResult(interp, resultPtr); + if (linePtr != resultPtr) { + Tcl_DecrRefCount(linePtr); + } + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "error reading \"", name, "\": ", + Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } lineLen = -1; } if (objc == 3) { - Tcl_ResetResult(interp); - objPtr = Tcl_ObjSetVar2(interp, objv[2], NULL, - resultPtr, TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1); - if (objPtr == NULL) { - Tcl_DecrRefCount(resultPtr); + if (Tcl_ObjSetVar2(interp, objv[2], NULL, linePtr, + TCL_LEAVE_ERR_MSG) == NULL) { + Tcl_DecrRefCount(linePtr); return TCL_ERROR; } - Tcl_ResetResult(interp); - Tcl_SetIntObj(Tcl_GetObjResult(interp), lineLen); + Tcl_SetIntObj(resultPtr, lineLen); return TCL_OK; } - Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -300,169 +286,101 @@ 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 toReadNow; /* How many bytes to attempt to - * read in the current iteration? */ - int charactersRead; /* How many characters were read? */ - int charactersReadNow; /* How many characters were read - * in this iteration? */ - int mode; /* Mode in which channel is opened. */ - int bufSize; /* Channel buffer size; used to decide - * in what chunk sizes to read from - * the channel. */ - char *arg; + 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. */ + char *name; Tcl_Obj *resultPtr; if ((objc != 2) && (objc != 3)) { -argerror: + argerror: Tcl_WrongNumArgs(interp, 1, objv, "channelId ?numBytes?"); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), " or \"", - Tcl_GetStringFromObj(objv[0], NULL), + Tcl_AppendResult(interp, " or \"", Tcl_GetString(objv[0]), " ?-nonewline? channelId\"", (char *) NULL); return TCL_ERROR; } + i = 1; newline = 0; - if (strcmp(Tcl_GetStringFromObj(objv[1], NULL), "-nonewline") == 0) { + if (strcmp(Tcl_GetString(objv[1]), "-nonewline") == 0) { newline = 1; i++; } if (i == objc) { goto argerror; } - arg = Tcl_GetStringFromObj(objv[i], NULL); - chan = Tcl_GetChannel(interp, arg, &mode); + name = Tcl_GetString(objv[i]); + chan = Tcl_GetChannel(interp, name, &mode); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } if ((mode & TCL_READABLE) == 0) { - resultPtr = Tcl_GetObjResult(interp); - Tcl_AppendStringsToObj(resultPtr, "channel \"", arg, + Tcl_AppendResult(interp, "channel \"", name, "\" wasn't opened for reading", (char *) NULL); return TCL_ERROR; } - i++; /* Consumed channel name. */ /* * Compute how many bytes to read, and see whether the final * newline should be dropped. */ - toRead = INT_MAX; + toRead = -1; if (i < objc) { - arg = Tcl_GetStringFromObj(objv[i], NULL); - if (isdigit((unsigned char) (arg[0]))) { + char *arg; + + arg = Tcl_GetString(objv[i]); + if (isdigit(UCHAR(arg[0]))) { /* INTL: digit */ if (Tcl_GetIntFromObj(interp, objv[i], &toRead) != TCL_OK) { return TCL_ERROR; } - Tcl_ResetResult(interp); } else if (strcmp(arg, "nonewline") == 0) { newline = 1; } else { - resultPtr = Tcl_GetObjResult(interp); - Tcl_AppendStringsToObj(resultPtr, "bad argument \"", arg, + Tcl_AppendResult(interp, "bad argument \"", arg, "\": should be \"nonewline\"", (char *) NULL); return TCL_ERROR; } } - /* - * Create a new object and use that instead of the interpreter - * result. We cannot use the interpreter's result object because - * it may get smashed at any time by recursive calls. - */ - - resultPtr = Tcl_NewObj(); - - bufSize = Tcl_GetChannelBufferSize(chan); - - /* - * If the caller specified a maximum length to read, then that is - * a good size to preallocate. - */ - - if ((toRead != INT_MAX) && (toRead > bufSize)) { - Tcl_SetObjLength(resultPtr, toRead); - } - - for (charactersRead = 0; charactersRead < toRead; ) { - toReadNow = toRead - charactersRead; - if (toReadNow > bufSize) { - toReadNow = bufSize; - } - - /* - * NOTE: This is a NOOP if we set the size (above) to the - * number of bytes we expect to read. In the degenerate - * case, however, it will grow the buffer by the channel - * buffersize, which is 4K in most cases. This will result - * in inefficient copying for large files. This will be - * fixed in a future release. - */ - - Tcl_SetObjLength(resultPtr, charactersRead + toReadNow); - charactersReadNow = - Tcl_Read(chan, Tcl_GetStringFromObj(resultPtr, NULL) - + charactersRead, toReadNow); - if (charactersReadNow < 0) { - Tcl_SetObjLength(resultPtr, 0); - Tcl_AppendStringsToObj(resultPtr, "error reading \"", - Tcl_GetChannelName(chan), "\": ", - Tcl_PosixError(interp), (char *) NULL); - Tcl_SetObjResult(interp, resultPtr); - - return TCL_ERROR; - } - - /* - * If we had a short read it means that we have either EOF - * or BLOCKED on the channel, so break out. - */ - - charactersRead += charactersReadNow; - - /* - * Do not call the driver again if we got a short read - */ - - if (charactersReadNow < toReadNow) { - break; /* Out of "for" loop. */ - } + resultPtr = Tcl_GetObjResult(interp); + charactersRead = Tcl_ReadChars(chan, resultPtr, toRead, 0); + if (charactersRead < 0) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "error reading \"", name, "\": ", + Tcl_PosixError(interp), (char *) NULL); + return TCL_ERROR; } /* * If requested, remove the last newline in the channel if at EOF. */ - if ((charactersRead > 0) && (newline) && - (Tcl_GetStringFromObj(resultPtr, NULL)[charactersRead-1] == '\n')) { - charactersRead--; - } - Tcl_SetObjLength(resultPtr, charactersRead); - - /* - * Now set the object into the interpreter result and release our - * hold on it by decrrefing it. - */ - - Tcl_SetObjResult(interp, resultPtr); - + if ((charactersRead > 0) && (newline != 0)) { + char *result; + int length; + + result = Tcl_GetStringFromObj(resultPtr, &length); + if (result[length - 1] == '\n') { + Tcl_SetObjLength(resultPtr, length - 1); + } + } return TCL_OK; } /* *---------------------------------------------------------------------- * - * Tcl_SeekCmd -- + * Tcl_SeekObjCmd -- * * This procedure is invoked to process the Tcl "seek" command. See * the user documentation for details on what it does. * * Results: @@ -475,66 +393,58 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_SeekCmd(clientData, interp, argc, argv) +Tcl_SeekObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { Tcl_Channel chan; /* The channel to tell on. */ int offset, mode; /* Where to seek? */ int result; /* Of calling Tcl_Seek. */ - - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " channelId offset ?origin?\"", (char *) NULL); - return TCL_ERROR; - } - chan = Tcl_GetChannel(interp, argv[1], NULL); - if (chan == (Tcl_Channel) NULL) { - return TCL_ERROR; - } - if (Tcl_GetInt(interp, argv[2], &offset) != TCL_OK) { - return TCL_ERROR; - } - mode = SEEK_SET; - if (argc == 4) { - size_t length; - int c; - - length = strlen(argv[3]); - c = argv[3][0]; - if ((c == 's') && (strncmp(argv[3], "start", length) == 0)) { - mode = SEEK_SET; - } else if ((c == 'c') && (strncmp(argv[3], "current", length) == 0)) { - mode = SEEK_CUR; - } else if ((c == 'e') && (strncmp(argv[3], "end", length) == 0)) { - mode = SEEK_END; - } else { - Tcl_AppendResult(interp, "bad origin \"", argv[3], - "\": should be start, current, or end", (char *) NULL); - return TCL_ERROR; - } + char *chanName; + int optionIndex; + static char *originOptions[] = {"start", "current", "end", (char *) NULL}; + static int modeArray[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 1, objv, "channelId offset ?origin?"); + return TCL_ERROR; + } + chanName = Tcl_GetString(objv[1]); + chan = Tcl_GetChannel(interp, chanName, NULL); + if (chan == (Tcl_Channel) NULL) { + return TCL_ERROR; + } + if (Tcl_GetIntFromObj(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]; } result = Tcl_Seek(chan, offset, mode); if (result == -1) { Tcl_AppendResult(interp, "error during seek on \"", - Tcl_GetChannelName(chan), "\": ", - Tcl_PosixError(interp), (char *) NULL); + chanName, "\": ", Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * - * Tcl_TellCmd -- + * Tcl_TellObjCmd -- * * This procedure is invoked to process the Tcl "tell" command. * See the user documentation for details on what it does. * * Results: @@ -546,35 +456,34 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_TellCmd(clientData, interp, argc, argv) +Tcl_TellObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { Tcl_Channel chan; /* The channel to tell on. */ - char buf[40]; + char *chanName; - if (argc != 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " channelId\"", (char *) NULL); + 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. */ - chan = Tcl_GetChannel(interp, argv[1], NULL); + chanName = Tcl_GetString(objv[1]); + chan = Tcl_GetChannel(interp, chanName, NULL); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } - TclFormatInt(buf, Tcl_Tell(chan)); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_SetIntObj(Tcl_GetObjResult(interp), Tcl_Tell(chan)); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -600,51 +509,54 @@ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { Tcl_Channel chan; /* The channel to close. */ - int len; /* Length of error output. */ char *arg; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channelId"); return TCL_ERROR; } - arg = Tcl_GetStringFromObj(objv[1], NULL); + arg = Tcl_GetString(objv[1]); chan = Tcl_GetChannel(interp, arg, NULL); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } 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->result. + * 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. */ - len = strlen(interp->result); - if ((len > 0) && (interp->result[len - 1] == '\n')) { - interp->result[len - 1] = '\0'; + Tcl_Obj *resultPtr; + char *string; + int len; + + resultPtr = Tcl_GetObjResult(interp); + string = Tcl_GetStringFromObj(resultPtr, &len); + if ((len > 0) && (string[len - 1] == '\n')) { + Tcl_SetObjLength(resultPtr, len - 1); } - return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * - * Tcl_FconfigureCmd -- + * Tcl_FconfigureObjCmd -- * * This procedure is invoked to process the Tcl "fconfigure" command. * See the user documentation for details on what it does. * * Results: @@ -656,59 +568,64 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_FconfigureCmd(clientData, interp, argc, argv) +Tcl_FconfigureObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { + char *chanName, *optionName, *valueName; Tcl_Channel chan; /* The channel to set a mode on. */ int i; /* Iterate over arg-value pairs. */ Tcl_DString ds; /* DString to hold result of * calling Tcl_GetChannelOption. */ - if ((argc < 2) || (((argc % 2) == 1) && (argc != 3))) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " channelId ?optionName? ?value? ?optionName value?...\"", - (char *) NULL); + if ((objc < 2) || (((objc % 2) == 1) && (objc != 3))) { + Tcl_WrongNumArgs(interp, 1, objv, + "channelId ?optionName? ?value? ?optionName value?..."); return TCL_ERROR; } - chan = Tcl_GetChannel(interp, argv[1], NULL); + chanName = Tcl_GetString(objv[1]); + chan = Tcl_GetChannel(interp, chanName, NULL); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } - if (argc == 2) { + if (objc == 2) { Tcl_DStringInit(&ds); if (Tcl_GetChannelOption(interp, chan, (char *) NULL, &ds) != TCL_OK) { Tcl_DStringFree(&ds); return TCL_ERROR; } Tcl_DStringResult(interp, &ds); return TCL_OK; } - if (argc == 3) { + if (objc == 3) { Tcl_DStringInit(&ds); - if (Tcl_GetChannelOption(interp, chan, argv[2], &ds) != TCL_OK) { + optionName = Tcl_GetString(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 < argc; i += 2) { - if (Tcl_SetChannelOption(interp, chan, argv[i-1], argv[i]) != TCL_OK) { + for (i = 3; i < objc; i += 2) { + optionName = Tcl_GetString(objv[i-1]); + valueName = Tcl_GetString(objv[i]); + if (Tcl_SetChannelOption(interp, chan, optionName, valueName) + != TCL_OK) { return TCL_ERROR; } } return TCL_OK; } /* - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- * * Tcl_EofObjCmd -- * * This procedure is invoked to process the Tcl "eof" command. * See the user documentation for details on what it does. @@ -715,14 +632,14 @@ * * Results: * A standard Tcl result. * * Side effects: - * Sets interp->result to "0" or "1" depending on whether the - * specified channel has an EOF condition. + * Sets interp's result to boolean true or false depending on whether + * the specified channel has an EOF condition. * - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_EofObjCmd(unused, interp, objc, objv) @@ -729,35 +646,33 @@ ClientData unused; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - Tcl_Channel chan; /* The channel to query for EOF. */ - int mode; /* Mode in which channel is opened. */ - char buf[40]; + Tcl_Channel chan; + int dummy; char *arg; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channelId"); return TCL_ERROR; } - arg = Tcl_GetStringFromObj(objv[1], NULL); - chan = Tcl_GetChannel(interp, arg, &mode); - if (chan == (Tcl_Channel) NULL) { + arg = Tcl_GetString(objv[1]); + chan = Tcl_GetChannel(interp, arg, &dummy); + if (chan == NULL) { return TCL_ERROR; } - TclFormatInt(buf, Tcl_Eof(chan) ? 1 : 0); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), Tcl_Eof(chan)); return TCL_OK; } /* *---------------------------------------------------------------------- * - * Tcl_ExecCmd -- + * Tcl_ExecObjCmd -- * * This procedure is invoked to process the "exec" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -769,134 +684,169 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_ExecCmd(dummy, interp, argc, argv) +Tcl_ExecObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { #ifdef MAC_TCL + Tcl_AppendResult(interp, "exec not implemented under Mac OS", (char *)NULL); return TCL_ERROR; + #else /* !MAC_TCL */ - int keepNewline, firstWord, background, length, result; + + /* + * This procedure generates an argv array for the string arguments. It + * starts out with stack-allocated space but uses dynamically-allocated + * storage if needed. + */ + +#define NUM_ARGS 20 + Tcl_Obj *resultPtr; + char **argv; + char *string; Tcl_Channel chan; - Tcl_DString ds; - int readSoFar, readNow, bufSize; + char *argStorage[NUM_ARGS]; + int argc, background, i, index, keepNewline, result, skip, length; + static char *options[] = { + "-keepnewline", "--", NULL + }; + enum options { + EXEC_KEEPNEWLINE, EXEC_LAST + }; /* * Check for a leading "-keepnewline" argument. */ keepNewline = 0; - for (firstWord = 1; (firstWord < argc) && (argv[firstWord][0] == '-'); - firstWord++) { - if (strcmp(argv[firstWord], "-keepnewline") == 0) { - keepNewline = 1; - } else if (strcmp(argv[firstWord], "--") == 0) { - firstWord++; + for (skip = 1; skip < objc; skip++) { + string = Tcl_GetString(objv[skip]); + if (string[0] != '-') { break; + } + if (Tcl_GetIndexFromObj(interp, objv[skip], options, "switch", + TCL_EXACT, &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == EXEC_KEEPNEWLINE) { + keepNewline = 1; } else { - Tcl_AppendResult(interp, "bad switch \"", argv[firstWord], - "\": must be -keepnewline or --", (char *) NULL); - return TCL_ERROR; + skip++; + break; } } - - if (argc <= firstWord) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ?switches? arg ?arg ...?\"", (char *) NULL); + if (objc <= skip) { + Tcl_WrongNumArgs(interp, 1, objv, "?switches? arg ?arg ...?"); return TCL_ERROR; } /* * See if the command is to be run in background. */ background = 0; - if ((argv[argc-1][0] == '&') && (argv[argc-1][1] == 0)) { - argc--; - argv[argc] = NULL; + string = Tcl_GetString(objv[objc - 1]); + if ((string[0] == '&') && (string[1] == '\0')) { + objc--; background = 1; } - - chan = Tcl_OpenCommandChannel(interp, argc-firstWord, - argv+firstWord, - (background ? 0 : TCL_STDOUT | TCL_STDERR)); + + /* + * 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. + */ + + argv = argStorage; + argc = objc - skip; + if ((argc + 1) > sizeof(argv) / sizeof(argv[0])) { + argv = (char **) ckalloc((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] = Tcl_GetString(objv[i + skip]); + } + argv[argc] = NULL; + chan = Tcl_OpenCommandChannel(interp, argc, argv, + (background ? 0 : TCL_STDOUT | TCL_STDERR)); + + /* + * Free the argv array if malloc'ed storage was used. + */ + + if (argv != argStorage) { + ckfree((char *)argv); + } if (chan == (Tcl_Channel) NULL) { - return TCL_ERROR; + return TCL_ERROR; } if (background) { - /* - * Get the list of PIDs from the pipeline into interp->result and - * detach the PIDs (instead of waiting for them). - */ + * 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_ERROR; } - return TCL_OK; + return TCL_OK; } + resultPtr = Tcl_NewObj(); if (Tcl_GetChannelHandle(chan, TCL_READABLE, NULL) == TCL_OK) { -#define EXEC_BUFFER_SIZE 4096 - - Tcl_DStringInit(&ds); - readSoFar = 0; bufSize = 0; - while (1) { - bufSize += EXEC_BUFFER_SIZE; - Tcl_DStringSetLength(&ds, bufSize); - readNow = Tcl_Read(chan, Tcl_DStringValue(&ds) + readSoFar, - EXEC_BUFFER_SIZE); - if (readNow < 0) { - Tcl_DStringFree(&ds); - Tcl_AppendResult(interp, - "error reading output from command: ", - Tcl_PosixError(interp), (char *) NULL); - return TCL_ERROR; - } - readSoFar += readNow; - if (readNow < EXEC_BUFFER_SIZE) { - break; /* Out of "while (1)" loop. */ - } - } - Tcl_DStringSetLength(&ds, readSoFar); - Tcl_DStringResult(interp, &ds); - } + if (Tcl_ReadChars(chan, resultPtr, -1, 0) < 0) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "error reading output from command: ", + Tcl_PosixError(interp), (char *) NULL); + 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); + string = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length); + Tcl_AppendToObj(resultPtr, string, length); /* - * If the last character of interp->result is a newline, then remove - * the newline character (the newline would just confuse things). - * Special hack: must replace the old terminating null character - * as a signal to Tcl_AppendResult et al. that we've mucked with - * the string. + * If the last character of the result is a newline, then remove + * the newline character. */ - length = strlen(interp->result); - if (!keepNewline && (length > 0) && - (interp->result[length-1] == '\n')) { - interp->result[length-1] = '\0'; - interp->result[length] = 'x'; + if (keepNewline == 0) { + string = Tcl_GetStringFromObj(resultPtr, &length); + if ((length > 0) && (string[length - 1] == '\n')) { + Tcl_SetObjLength(resultPtr, length - 1); + } } + Tcl_SetObjResult(interp, resultPtr); return result; #endif /* !MAC_TCL */ } /* - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- * * Tcl_FblockedObjCmd -- * * This procedure is invoked to process the Tcl "fblocked" command. * See the user documentation for details on what it does. @@ -903,14 +853,14 @@ * * Results: * A standard Tcl result. * * Side effects: - * Sets interp->result to "0" or "1" depending on whether the - * a preceding input operation on the channel would have blocked. + * 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(unused, interp, objc, objv) @@ -917,41 +867,38 @@ ClientData unused; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - Tcl_Channel chan; /* The channel to query for blocked. */ - int mode; /* Mode in which channel was opened. */ - char buf[40]; + Tcl_Channel chan; + int mode; char *arg; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channelId"); return TCL_ERROR; } - arg = Tcl_GetStringFromObj(objv[1], NULL); + arg = Tcl_GetString(objv[1]); chan = Tcl_GetChannel(interp, arg, &mode); - if (chan == (Tcl_Channel) NULL) { + if (chan == NULL) { return TCL_ERROR; } if ((mode & TCL_READABLE) == 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"", - Tcl_GetStringFromObj(objv[1], NULL), - "\" wasn't opened for reading", (char *) NULL); + arg, "\" wasn't opened for reading", (char *) NULL); return TCL_ERROR; } - TclFormatInt(buf, Tcl_InputBlocked(chan) ? 1 : 0); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), Tcl_InputBlocked(chan)); return TCL_OK; } /* *---------------------------------------------------------------------- * - * Tcl_OpenCmd -- + * Tcl_OpenObjCmd -- * * This procedure is invoked to process the "open" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -963,59 +910,59 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_OpenCmd(notUsed, interp, argc, argv) +Tcl_OpenObjCmd(notUsed, interp, objc, objv) ClientData notUsed; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { int pipeline, prot; - char *modeString; + char *modeString, *what; Tcl_Channel chan; - if ((argc < 2) || (argc > 4)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " fileName ?access? ?permissions?\"", (char *) NULL); + if ((objc < 2) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 1, objv, "fileName ?access? ?permissions?"); return TCL_ERROR; } prot = 0666; - if (argc == 2) { + if (objc == 2) { modeString = "r"; } else { - modeString = argv[2]; - if (argc == 4) { - if (Tcl_GetInt(interp, argv[3], &prot) != TCL_OK) { + modeString = Tcl_GetString(objv[2]); + if (objc == 4) { + if (Tcl_GetIntFromObj(interp, objv[3], &prot) != TCL_OK) { return TCL_ERROR; } } } pipeline = 0; - if (argv[1][0] == '|') { + what = Tcl_GetString(objv[1]); + if (what[0] == '|') { pipeline = 1; } /* * Open the file or create a process pipeline. */ if (!pipeline) { - chan = Tcl_OpenFileChannel(interp, argv[1], modeString, prot); + chan = Tcl_OpenFileChannel(interp, what, modeString, prot); } else { #ifdef MAC_TCL Tcl_AppendResult(interp, "command pipelines not supported on Macintosh OS", (char *)NULL); return TCL_ERROR; #else - int mode, seekFlag, cmdArgc; + int mode, seekFlag, cmdObjc; char **cmdArgv; - if (Tcl_SplitList(interp, argv[1]+1, &cmdArgc, &cmdArgv) != TCL_OK) { + if (Tcl_SplitList(interp, what+1, &cmdObjc, &cmdArgv) != TCL_OK) { return TCL_ERROR; } mode = TclGetOpenMode(interp, modeString, &seekFlag); if (mode == -1) { @@ -1034,11 +981,11 @@ break; default: panic("Tcl_OpenCmd: invalid mode value"); break; } - chan = Tcl_OpenCommandChannel(interp, cmdArgc, cmdArgv, flags); + chan = Tcl_OpenCommandChannel(interp, cmdObjc, cmdArgv, flags); } ckfree((char *) cmdArgv); #endif } if (chan == (Tcl_Channel) NULL) { @@ -1215,11 +1162,11 @@ int port; /* Port of client that was accepted. */ { AcceptCallback *acceptCallbackPtr; Tcl_Interp *interp; char *script; - char portBuf[10]; + char portBuf[TCL_INTEGER_SPACE]; int result; acceptCallbackPtr = (AcceptCallback *) callbackData; /* @@ -1236,16 +1183,32 @@ Tcl_Preserve((ClientData) script); Tcl_Preserve((ClientData) 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((Tcl_Interp *) NULL, chan); + result = Tcl_VarEval(interp, script, " ", Tcl_GetChannelName(chan), " ", address, " ", portBuf, (char *) NULL); if (result != TCL_OK) { Tcl_BackgroundError(interp); 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((Tcl_Interp *) NULL, chan); + Tcl_Release((ClientData) interp); Tcl_Release((ClientData) script); } else { /* @@ -1296,11 +1259,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_SocketCmd -- + * Tcl_SocketObjCmd -- * * This procedure is invoked to process the "socket" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -1311,17 +1274,23 @@ * *---------------------------------------------------------------------- */ int -Tcl_SocketCmd(notUsed, interp, argc, argv) +Tcl_SocketObjCmd(notUsed, interp, objc, objv) ClientData notUsed; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { - int a, server, port; + static char *socketOptions[] = { + "-async", "-myaddr", "-myport","-server", (char *) NULL + }; + enum socketOptions { + SKT_ASYNC, SKT_MYADDR, SKT_MYPORT, SKT_SERVER + }; + int optionIndex, a, server, port; char *arg, *copyScript, *host, *script; char *myaddr = NULL; int myport = 0; int async = 0; Tcl_Channel chan; @@ -1328,95 +1297,108 @@ AcceptCallback *acceptCallbackPtr; server = 0; script = NULL; - if (TclHasSockets(interp) != TCL_OK) { + if (TclpHasSockets(interp) != TCL_OK) { return TCL_ERROR; } - for (a = 1; a < argc; a++) { - arg = argv[a]; - if (arg[0] == '-') { - if (strcmp(arg, "-server") == 0) { + for (a = 1; a < objc; a++) { + 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_AppendResult(interp, + "cannot set -async option for server sockets", + (char *) NULL); + return TCL_ERROR; + } + async = 1; + break; + } + case SKT_MYADDR: { + a++; + if (a >= objc) { + Tcl_AppendResult(interp, + "no argument given for -myaddr option", + (char *) NULL); + return TCL_ERROR; + } + myaddr = Tcl_GetString(objv[a]); + break; + } + case SKT_MYPORT: { + char *myPortName; + a++; + if (a >= objc) { + Tcl_AppendResult(interp, + "no argument given for -myport option", + (char *) NULL); + return TCL_ERROR; + } + myPortName = Tcl_GetString(objv[a]); + if (TclSockGetPort(interp, myPortName, "tcp", &myport) + != TCL_OK) { + return TCL_ERROR; + } + break; + } + case SKT_SERVER: { if (async == 1) { Tcl_AppendResult(interp, "cannot set -async option for server sockets", (char *) NULL); return TCL_ERROR; } server = 1; a++; - if (a >= argc) { + if (a >= objc) { Tcl_AppendResult(interp, "no argument given for -server option", (char *) NULL); return TCL_ERROR; } - script = argv[a]; - } else if (strcmp(arg, "-myaddr") == 0) { - a++; - if (a >= argc) { - Tcl_AppendResult(interp, - "no argument given for -myaddr option", - (char *) NULL); - return TCL_ERROR; - } - myaddr = argv[a]; - } else if (strcmp(arg, "-myport") == 0) { - a++; - if (a >= argc) { - Tcl_AppendResult(interp, - "no argument given for -myport option", - (char *) NULL); - return TCL_ERROR; - } - if (TclSockGetPort(interp, argv[a], "tcp", &myport) - != TCL_OK) { - return TCL_ERROR; - } - } else if (strcmp(arg, "-async") == 0) { - if (server == 1) { - Tcl_AppendResult(interp, - "cannot set -async option for server sockets", - (char *) NULL); - return TCL_ERROR; - } - async = 1; - } else { - Tcl_AppendResult(interp, "bad option \"", arg, - "\", must be -async, -myaddr, -myport, or -server", - (char *) NULL); - return TCL_ERROR; - } - } else { - break; + script = Tcl_GetString(objv[a]); + break; + } + default: { + panic("Tcl_SocketObjCmd: bad option index to SocketOptions"); + } } } if (server) { host = myaddr; /* NULL implies INADDR_ANY */ if (myport != 0) { Tcl_AppendResult(interp, "Option -myport is not valid for servers", NULL); return TCL_ERROR; } - } else if (a < argc) { - host = argv[a]; + } else if (a < objc) { + host = Tcl_GetString(objv[a]); a++; } else { wrongNumArgs: Tcl_AppendResult(interp, "wrong # args: should be either:\n", - argv[0], + Tcl_GetString(objv[0]), " ?-myaddr addr? ?-myport myport? ?-async? host port\n", - argv[0], + Tcl_GetString(objv[0]), " -server command ?-myaddr addr? port", (char *) NULL); return TCL_ERROR; } - if (a == argc-1) { - if (TclSockGetPort(interp, argv[a], "tcp", &port) != TCL_OK) { + if (a == objc-1) { + if (TclSockGetPort(interp, Tcl_GetString(objv[a]), + "tcp", &port) != TCL_OK) { return TCL_ERROR; } } else { goto wrongNumArgs; } @@ -1491,14 +1473,14 @@ Tcl_Obj *CONST objv[]; /* Argument objects. */ { Tcl_Channel inChan, outChan; char *arg; int mode, i; - int toRead; + int toRead, index; Tcl_Obj *cmdPtr; static char* switches[] = { "-size", "-command", NULL }; - enum { FcopySize, FcopyCommand } index; + 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; @@ -1507,29 +1489,29 @@ /* * Parse the channel arguments and verify that they are readable * or writable, as appropriate. */ - arg = Tcl_GetStringFromObj(objv[1], NULL); + arg = Tcl_GetString(objv[1]); inChan = Tcl_GetChannel(interp, arg, &mode); if (inChan == (Tcl_Channel) NULL) { return TCL_ERROR; } if ((mode & TCL_READABLE) == 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"", - Tcl_GetStringFromObj(objv[1], NULL), + Tcl_GetString(objv[1]), "\" wasn't opened for reading", (char *) NULL); return TCL_ERROR; } - arg = Tcl_GetStringFromObj(objv[2], NULL); + arg = Tcl_GetString(objv[2]); outChan = Tcl_GetChannel(interp, arg, &mode); if (outChan == (Tcl_Channel) NULL) { return TCL_ERROR; } if ((mode & TCL_WRITABLE) == 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"", - Tcl_GetStringFromObj(objv[1], NULL), + Tcl_GetString(objv[1]), "\" wasn't opened for writing", (char *) NULL); return TCL_ERROR; } toRead = -1; Index: generic/tclIOSock.c ================================================================== --- generic/tclIOSock.c +++ generic/tclIOSock.c @@ -1,39 +1,39 @@ /* * tclIOSock.c -- * * Common routines used by all socket based channel types. * - * Copyright (c) 1995 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclIOSock.c 1.20 97/04/25 16:36:40 + * RCS: @(#) $Id: tclIOSock.c,v 1.1.2.2 1998/09/24 23:58:53 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" /* - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- * * 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 - * interp->result. + * 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(interp, string, proto, portPtr) Tcl_Interp *interp; @@ -40,18 +40,25 @@ char *string; /* Integer or service name */ char *proto; /* "tcp" or "udp", typically */ int *portPtr; /* Return port number */ { struct servent *sp; /* Protocol info for named services */ - if (Tcl_GetInt(interp, string, portPtr) != TCL_OK) { - sp = getservbyname(string, proto); + Tcl_DString ds; + 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); - Tcl_ResetResult(interp); /* clear error message */ return TCL_OK; } - return TCL_ERROR; } if (Tcl_GetInt(interp, string, portPtr) != TCL_OK) { return TCL_ERROR; } if (*portPtr > 0xFFFF) { Index: generic/tclIOUtil.c ================================================================== --- generic/tclIOUtil.c +++ generic/tclIOUtil.c @@ -6,24 +6,81 @@ * * 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-1996 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclIOUtil.c 1.133 97/09/24 16:38:57 + * RCS: @(#) $Id: tclIOUtil.c,v 1.1.2.9 1999/02/01 21:29:53 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" + +/* + * The following typedef declarations allow for hooking into the chain + * of functions maintained for 'Tcl_Stat(...)', 'Tcl_Access(...)' & + * 'Tcl_OpenFileChannel(...)'. Basically for each hookable function + * a linked list is defined. + */ +typedef struct StatProc { + TclStatProc_ *proc; /* Function to process a 'stat()' call */ + struct StatProc *nextPtr; /* The next 'stat()' function to call */ +} StatProc; + +typedef struct AccessProc { + TclAccessProc_ *proc; /* Function to process a 'access()' call */ + struct AccessProc *nextPtr; /* The next 'access()' function to call */ +} AccessProc; + +typedef struct OpenFileChannelProc { + TclOpenFileChannelProc_ *proc; /* Function to process a + * 'Tcl_OpenFileChannel()' call */ + struct OpenFileChannelProc *nextPtr; + /* The next 'Tcl_OpenFileChannel()' + * function to call */ +} OpenFileChannelProc; + +/* + * For each type of hookable function, a static node is declared to + * hold the function pointer for the "built-in" routine (e.g. + * 'TclpStat(...)') and the respective list is initialized as a pointer + * to that node. + * + * The "delete" functions (e.g. 'TclStatDeleteProc(...)') ensure that + * these statically declared list entry cannot be inadvertently removed. + * + * This method avoids the need to call any sort of "initialization" + * function. + * + * All three lists are protected by a global hookMutex. + */ + +static StatProc defaultStatProc = { + &TclpStat, NULL +}; +static StatProc *statProcList = &defaultStatProc; + +static AccessProc defaultAccessProc = { + &TclpAccess, NULL +}; +static AccessProc *accessProcList = &defaultAccessProc; + +static OpenFileChannelProc defaultOpenFileChannelProc = { + &TclpOpenFileChannel, NULL +}; +static OpenFileChannelProc *openFileChannelProcList = + &defaultOpenFileChannelProc; + +TCL_DECLARE_MUTEX(hookMutex) /* - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- * * TclGetOpenMode -- * * Description: * Computes a POSIX mode mask for opening a file, from a given string, @@ -30,22 +87,22 @@ * and also sets a flag to indicate whether the caller should seek to * EOF after opening the file. * * Results: * On success, returns mode to pass to "open". If an error occurs, the - * returns -1 and if interp is not NULL, sets interp->result to an - * error message. + * 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. * * Special note: * This code is based on a prototype implementation contributed * by Mark Diekhans. * - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- */ int TclGetOpenMode(interp, string, seekFlagPtr) Tcl_Interp *interp; /* Interpreter to use for error @@ -66,11 +123,18 @@ * of a lower-case first letter. */ *seekFlagPtr = 0; mode = 0; - if (islower(UCHAR(string[0]))) { + + /* + * Guard against international characters before using byte oriented + * routines. + */ + + if (!(string[0] & 0x80) + && islower(UCHAR(string[0]))) { /* INTL: ISO only. */ switch (string[0]) { case 'r': mode = O_RDONLY; break; case 'w': @@ -210,106 +274,75 @@ Tcl_EvalFile(interp, fileName) Tcl_Interp *interp; /* Interpreter in which to process file. */ char *fileName; /* Name of file to process. Tilde-substitution * will be performed on this name. */ { - int result; + int result, length; struct stat statBuf; - char *cmdBuffer = (char *) NULL; char *oldScriptFile; - Interp *iPtr = (Interp *) interp; - Tcl_DString buffer; - char *nativeName; + Interp *iPtr; + Tcl_DString nameString; + char *name, *string; Tcl_Channel chan; - Tcl_Obj *cmdObjPtr; - - Tcl_ResetResult(interp); - oldScriptFile = iPtr->scriptFile; - iPtr->scriptFile = fileName; - Tcl_DStringInit(&buffer); - nativeName = Tcl_TranslateFileName(interp, fileName, &buffer); - if (nativeName == NULL) { - goto error; - } - - /* - * If Tcl_TranslateFileName didn't already copy the file name, do it - * here. This way we don't depend on fileName staying constant - * throughout the execution of the script (e.g., what if it happens - * to point to a Tcl variable that the script could change?). - */ - - if (nativeName != Tcl_DStringValue(&buffer)) { - Tcl_DStringSetLength(&buffer, 0); - Tcl_DStringAppend(&buffer, nativeName, -1); - nativeName = Tcl_DStringValue(&buffer); - } - if (stat(nativeName, &statBuf) == -1) { + Tcl_Obj *objPtr; + + name = Tcl_TranslateFileName(interp, fileName, &nameString); + if (name == NULL) { + return TCL_ERROR; + } + + result = TCL_ERROR; + objPtr = Tcl_NewObj(); + + if (TclStat(name, &statBuf) == -1) { Tcl_SetErrno(errno); Tcl_AppendResult(interp, "couldn't read file \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); - goto error; + goto end; } - chan = Tcl_OpenFileChannel(interp, nativeName, "r", 0644); + chan = Tcl_OpenFileChannel(interp, name, "r", 0644); if (chan == (Tcl_Channel) NULL) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "couldn't read file \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); - goto error; + goto end; } - cmdBuffer = (char *) ckalloc((unsigned) statBuf.st_size+1); - result = Tcl_Read(chan, cmdBuffer, statBuf.st_size); - if (result < 0) { + if (Tcl_ReadChars(chan, objPtr, -1, 0) < 0) { Tcl_Close(interp, chan); Tcl_AppendResult(interp, "couldn't read file \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); - goto error; + goto end; } - cmdBuffer[result] = 0; if (Tcl_Close(interp, chan) != TCL_OK) { - goto error; - } - - /* - * Transfer the buffer memory allocated above to the object system. - * Tcl_EvalObj will own this new string object if needed, - * so past the Tcl_EvalObj point, we must not ckfree(cmdBuffer) - * but rather use the reference counting mechanism. - * (Nb: and we must not thus not use goto error after this point) - */ - cmdObjPtr = Tcl_NewObj(); - cmdObjPtr->bytes = cmdBuffer; - cmdObjPtr->length = result; - - Tcl_IncrRefCount(cmdObjPtr); - result = Tcl_EvalObj(interp, cmdObjPtr); - Tcl_DecrRefCount(cmdObjPtr); + goto end; + } + + iPtr = (Interp *) interp; + oldScriptFile = iPtr->scriptFile; + iPtr->scriptFile = fileName; + string = Tcl_GetStringFromObj(objPtr, &length); + result = Tcl_EvalEx(interp, string, length, 0); + iPtr->scriptFile = oldScriptFile; if (result == TCL_RETURN) { result = TclUpdateReturnInfo(iPtr); } else if (result == TCL_ERROR) { - char msg[200]; + char msg[200 + TCL_INTEGER_SPACE]; /* * Record information telling where the error occurred. */ sprintf(msg, "\n (file \"%.150s\" line %d)", fileName, interp->errorLine); Tcl_AddErrorInfo(interp, msg); } - iPtr->scriptFile = oldScriptFile; - Tcl_DStringFree(&buffer); - return result; - -error: - if (cmdBuffer != (char *) NULL) { - ckfree(cmdBuffer); - } - iPtr->scriptFile = oldScriptFile; - Tcl_DStringFree(&buffer); - return TCL_ERROR; + + end: + Tcl_DecrRefCount(objPtr); + Tcl_DStringFree(&nameString); + return result; } /* *---------------------------------------------------------------------- * @@ -388,5 +421,456 @@ msg = Tcl_ErrnoMsg(errno); id = Tcl_ErrnoId(); Tcl_SetErrorCode(interp, "POSIX", id, msg, (char *) NULL); return msg; } + +/* + *---------------------------------------------------------------------- + * + * TclStat -- + * + * This procedure replaces the library version of stat and lsat. + * The chain of functions that have been "inserted" into the + * 'statProcList' will be called in succession until either + * a value of zero is returned, or the entire list is visited. + * + * Results: + * See stat documentation. + * + * Side effects: + * See stat documentation. + * + *---------------------------------------------------------------------- + */ + +int +TclStat(path, buf) + CONST char *path; /* Path of file to stat (in current CP). */ + TclStat_ *buf; /* Filled with results of stat call. */ +{ + StatProc *statProcPtr; + int retVal = -1; + + /* + * Call each of the "stat" function in succession. A non-return + * value of -1 indicates the particular function has succeeded. + */ + + Tcl_MutexLock(&hookMutex); + statProcPtr = statProcList; + while ((retVal == -1) && (statProcPtr != NULL)) { + retVal = (*statProcPtr->proc)(path, buf); + statProcPtr = statProcPtr->nextPtr; + } + Tcl_MutexUnlock(&hookMutex); + + return (retVal); +} + +/* + *---------------------------------------------------------------------- + * + * TclAccess -- + * + * This procedure replaces the library version of access. + * The chain of functions that have been "inserted" into the + * 'accessProcList' will be called in succession until either + * a value of zero is returned, or the entire list is visited. + * + * Results: + * See access documentation. + * + * Side effects: + * See access documentation. + * + *---------------------------------------------------------------------- + */ + +int +TclAccess(path, mode) + CONST char *path; /* Path of file to access (in current CP). */ + int mode; /* Permission setting. */ +{ + AccessProc *accessProcPtr; + int retVal = -1; + + /* + * Call each of the "access" function in succession. A non-return + * value of -1 indicates the particular function has succeeded. + */ + + Tcl_MutexLock(&hookMutex); + accessProcPtr = accessProcList; + while ((retVal == -1) && (accessProcPtr != NULL)) { + retVal = (*accessProcPtr->proc)(path, mode); + accessProcPtr = accessProcPtr->nextPtr; + } + Tcl_MutexUnlock(&hookMutex); + + return (retVal); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_OpenFileChannel -- + * + * The chain of functions that have been "inserted" into the + * 'openFileChannelProcList' will be called in succession until + * either a valid file channel is returned, or the entire list is + * visited. + * + * 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_OpenFileChannel(interp, fileName, modeString, permissions) + Tcl_Interp *interp; /* Interpreter for error reporting; + * can be NULL. */ + char *fileName; /* Name of file to open. */ + 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? */ +{ + OpenFileChannelProc *openFileChannelProcPtr; + Tcl_Channel retVal = NULL; + + /* + * Call each of the "Tcl_OpenFileChannel" function in succession. + * A non-NULL return value indicates the particular function has + * succeeded. + */ + + Tcl_MutexLock(&hookMutex); + openFileChannelProcPtr = openFileChannelProcList; + while ((retVal == NULL) && (openFileChannelProcPtr != NULL)) { + retVal = (*openFileChannelProcPtr->proc)(interp, fileName, + modeString, permissions); + openFileChannelProcPtr = openFileChannelProcPtr->nextPtr; + } + Tcl_MutexUnlock(&hookMutex); + + return (retVal); +} + +/* + *---------------------------------------------------------------------- + * + * TclStatInsertProc -- + * + * Insert the passed procedure pointer at the head of the list of + * functions which are used during a call to 'TclStat(...)'. The + * passed function should be have exactly like 'TclStat' when called + * during that time (see 'TclStat(...)' for more informatin). + * The function will be added even if it already in the list. + * + * Results: + * Normally TCL_OK; TCL_ERROR if memory for a new node in the list + * could not be allocated. + * + * Side effects: + * Memory allocataed and modifies the link list for 'TclStat' + * functions. + * + *---------------------------------------------------------------------- + */ + +int +TclStatInsertProc (proc) + TclStatProc_ *proc; +{ + int retVal = TCL_ERROR; + + if (proc != NULL) { + StatProc *newStatProcPtr; + + newStatProcPtr = (StatProc *)Tcl_Alloc(sizeof(StatProc));; + + if (newStatProcPtr != NULL) { + newStatProcPtr->proc = proc; + Tcl_MutexLock(&hookMutex); + newStatProcPtr->nextPtr = statProcList; + statProcList = newStatProcPtr; + Tcl_MutexUnlock(&hookMutex); + + retVal = TCL_OK; + } + } + + return (retVal); +} + +/* + *---------------------------------------------------------------------- + * + * TclStatDeleteProc -- + * + * Removed the passed function pointer from the list of 'TclStat' + * functions. Ensures that the built-in stat function is not + * removvable. + * + * Results: + * TCL_OK if the procedure pointer was successfully removed, + * TCL_ERROR otherwise. + * + * Side effects: + * Memory is deallocated and the respective list updated. + * + *---------------------------------------------------------------------- + */ + +int +TclStatDeleteProc (proc) + TclStatProc_ *proc; +{ + int retVal = TCL_ERROR; + StatProc *tmpStatProcPtr; + StatProc *prevStatProcPtr = NULL; + + Tcl_MutexLock(&hookMutex); + tmpStatProcPtr = statProcList; + /* + * Traverse the 'statProcList' looking for the particular node + * whose 'proc' member matches 'proc' and remove that one from + * the list. Ensure that the "default" node cannot be removed. + */ + + while ((retVal == TCL_ERROR) && (tmpStatProcPtr != &defaultStatProc)) { + if (tmpStatProcPtr->proc == proc) { + if (prevStatProcPtr == NULL) { + statProcList = tmpStatProcPtr->nextPtr; + } else { + prevStatProcPtr->nextPtr = tmpStatProcPtr->nextPtr; + } + + Tcl_Free((char *)tmpStatProcPtr); + + retVal = TCL_OK; + } else { + prevStatProcPtr = tmpStatProcPtr; + tmpStatProcPtr = tmpStatProcPtr->nextPtr; + } + } + + Tcl_MutexUnlock(&hookMutex); + return (retVal); +} + +/* + *---------------------------------------------------------------------- + * + * TclAccessInsertProc -- + * + * Insert the passed procedure pointer at the head of the list of + * functions which are used during a call to 'TclAccess(...)'. The + * passed function should be have exactly like 'TclAccess' when + * called during that time (see 'TclAccess(...)' for more informatin). + * The function will be added even if it already in the list. + * + * Results: + * Normally TCL_OK; TCL_ERROR if memory for a new node in the list + * could not be allocated. + * + * Side effects: + * Memory allocataed and modifies the link list for 'TclAccess' + * functions. + * + *---------------------------------------------------------------------- + */ + +int +TclAccessInsertProc(proc) + TclAccessProc_ *proc; +{ + int retVal = TCL_ERROR; + + if (proc != NULL) { + AccessProc *newAccessProcPtr; + + newAccessProcPtr = (AccessProc *)Tcl_Alloc(sizeof(AccessProc));; + + if (newAccessProcPtr != NULL) { + newAccessProcPtr->proc = proc; + Tcl_MutexLock(&hookMutex); + newAccessProcPtr->nextPtr = accessProcList; + accessProcList = newAccessProcPtr; + Tcl_MutexUnlock(&hookMutex); + + retVal = TCL_OK; + } + } + + return (retVal); +} + +/* + *---------------------------------------------------------------------- + * + * TclAccessDeleteProc -- + * + * Removed the passed function pointer from the list of 'TclAccess' + * functions. Ensures that the built-in access function is not + * removvable. + * + * Results: + * TCL_OK if the procedure pointer was successfully removed, + * TCL_ERROR otherwise. + * + * Side effects: + * Memory is deallocated and the respective list updated. + * + *---------------------------------------------------------------------- + */ + +int +TclAccessDeleteProc(proc) + TclAccessProc_ *proc; +{ + int retVal = TCL_ERROR; + AccessProc *tmpAccessProcPtr; + AccessProc *prevAccessProcPtr = NULL; + + /* + * Traverse the 'accessProcList' looking for the particular node + * whose 'proc' member matches 'proc' and remove that one from + * the list. Ensure that the "default" node cannot be removed. + */ + + Tcl_MutexLock(&hookMutex); + tmpAccessProcPtr = accessProcList; + while ((retVal == TCL_ERROR) && (tmpAccessProcPtr != &defaultAccessProc)) { + if (tmpAccessProcPtr->proc == proc) { + if (prevAccessProcPtr == NULL) { + accessProcList = tmpAccessProcPtr->nextPtr; + } else { + prevAccessProcPtr->nextPtr = tmpAccessProcPtr->nextPtr; + } + + Tcl_Free((char *)tmpAccessProcPtr); + + retVal = TCL_OK; + } else { + prevAccessProcPtr = tmpAccessProcPtr; + tmpAccessProcPtr = tmpAccessProcPtr->nextPtr; + } + } + Tcl_MutexUnlock(&hookMutex); + + return (retVal); +} + +/* + *---------------------------------------------------------------------- + * + * TclOpenFileChannelInsertProc -- + * + * Insert the passed procedure pointer at the head of the list of + * functions which are used during a call to + * 'Tcl_OpenFileChannel(...)'. The passed function should be have + * exactly like 'Tcl_OpenFileChannel' when called during that time + * (see 'Tcl_OpenFileChannel(...)' for more informatin). The + * function will be added even if it already in the list. + * + * Results: + * Normally TCL_OK; TCL_ERROR if memory for a new node in the list + * could not be allocated. + * + * Side effects: + * Memory allocataed and modifies the link list for + * 'Tcl_OpenFileChannel' functions. + * + *---------------------------------------------------------------------- + */ + +int +TclOpenFileChannelInsertProc(proc) + TclOpenFileChannelProc_ *proc; +{ + int retVal = TCL_ERROR; + + if (proc != NULL) { + OpenFileChannelProc *newOpenFileChannelProcPtr; + + newOpenFileChannelProcPtr = + (OpenFileChannelProc *)Tcl_Alloc(sizeof(OpenFileChannelProc));; + + if (newOpenFileChannelProcPtr != NULL) { + newOpenFileChannelProcPtr->proc = proc; + Tcl_MutexLock(&hookMutex); + newOpenFileChannelProcPtr->nextPtr = openFileChannelProcList; + openFileChannelProcList = newOpenFileChannelProcPtr; + Tcl_MutexUnlock(&hookMutex); + + retVal = TCL_OK; + } + } + + return (retVal); +} + +/* + *---------------------------------------------------------------------- + * + * TclOpenFileChannelDeleteProc -- + * + * Removed the passed function pointer from the list of + * 'Tcl_OpenFileChannel' functions. Ensures that the built-in + * open file channel function is not removvable. + * + * Results: + * TCL_OK if the procedure pointer was successfully removed, + * TCL_ERROR otherwise. + * + * Side effects: + * Memory is deallocated and the respective list updated. + * + *---------------------------------------------------------------------- + */ + +int +TclOpenFileChannelDeleteProc(proc) + TclOpenFileChannelProc_ *proc; +{ + int retVal = TCL_ERROR; + OpenFileChannelProc *tmpOpenFileChannelProcPtr = openFileChannelProcList; + OpenFileChannelProc *prevOpenFileChannelProcPtr = NULL; + + /* + * Traverse the 'openFileChannelProcList' looking for the particular + * node whose 'proc' member matches 'proc' and remove that one from + * the list. Ensure that the "default" node cannot be removed. + */ + + Tcl_MutexLock(&hookMutex); + tmpOpenFileChannelProcPtr = openFileChannelProcList; + while ((retVal == TCL_ERROR) && + (tmpOpenFileChannelProcPtr != &defaultOpenFileChannelProc)) { + if (tmpOpenFileChannelProcPtr->proc == proc) { + if (prevOpenFileChannelProcPtr == NULL) { + openFileChannelProcList = tmpOpenFileChannelProcPtr->nextPtr; + } else { + prevOpenFileChannelProcPtr->nextPtr = + tmpOpenFileChannelProcPtr->nextPtr; + } + + Tcl_Free((char *)tmpOpenFileChannelProcPtr); + + retVal = TCL_OK; + } else { + prevOpenFileChannelProcPtr = tmpOpenFileChannelProcPtr; + tmpOpenFileChannelProcPtr = tmpOpenFileChannelProcPtr->nextPtr; + } + } + Tcl_MutexUnlock(&hookMutex); + + return (retVal); +} Index: generic/tclIndexObj.c ================================================================== --- generic/tclIndexObj.c +++ generic/tclIndexObj.c @@ -8,37 +8,41 @@ * 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. * - * SCCS: @(#) tclIndexObj.c 1.8 97/07/29 10:16:54 + * RCS: @(#) $Id: tclIndexObj.c,v 1.1.2.2 1998/09/24 23:58:53 stanton Exp $ */ #include "tclInt.h" /* * Prototypes for procedures defined later in this file: */ -static void DupIndexInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, - Tcl_Obj *copyPtr)); static int SetIndexFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr)); -static void UpdateStringOfIndex _ANSI_ARGS_((Tcl_Obj *listPtr)); /* * The structure below defines the index Tcl object type by means of * procedures that can be invoked by generic object code. */ Tcl_ObjType tclIndexType = { "index", /* name */ (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */ - DupIndexInternalRep, /* dupIntRepProc */ - UpdateStringOfIndex, /* updateStringProc */ + (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */ + (Tcl_UpdateStringProc *) NULL, /* updateStringProc */ SetIndexFromAny /* setFromAnyProc */ }; + +/* + * Boolean flag indicating whether or not the tclIndexType object + * type has been registered with the Tcl compiler. + */ + +static int indexTypeInitialized = 0; /* *---------------------------------------------------------------------- * * Tcl_GetIndexFromObj -- @@ -45,11 +49,11 @@ * * 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 objPtr, 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 @@ -74,10 +78,71 @@ * and there must not be duplicate entries. */ 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 == &tclIndexType) + && (objPtr->internalRep.twoPtrValue.ptr1 == (VOID *) tablePtr)) { + *indexPtr = (int) objPtr->internalRep.twoPtrValue.ptr2; + return TCL_OK; + } + return Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, sizeof(char *), + msg, flags, indexPtr); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_GetIndexFromObjStruct -- + * + * This procedure 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 objPtr, 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. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, + indexPtr) + Tcl_Interp *interp; /* Used for error reporting if not NULL. */ + Tcl_Obj *objPtr; /* Object containing the string to lookup. */ + char **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 */ + 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, length, i, numAbbrev; char *key, *p1, *p2, **entryPtr; Tcl_Obj *resultPtr; /* @@ -92,15 +157,26 @@ /* * Lookup the value of the object in the table. Accept unique * abbreviations unless TCL_EXACT is set in flags. */ + + if (!indexTypeInitialized) { + /* + * This is the first time we've done a lookup. Register the + * tclIndexType. + */ + + Tcl_RegisterObjType(&tclIndexType); + indexTypeInitialized = 1; + } key = Tcl_GetStringFromObj(objPtr, &length); index = -1; numAbbrev = 0; - for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) { + for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; + entryPtr = (char **) ((long) entryPtr + offset), i++) { for (p1 = key, p2 = *entryPtr; *p1 == *p2; p1++, p2++) { if (*p1 == 0) { index = i; goto done; } @@ -133,56 +209,30 @@ *indexPtr = index; return TCL_OK; error: if (interp != NULL) { + int count; resultPtr = Tcl_GetObjResult(interp); Tcl_AppendStringsToObj(resultPtr, (numAbbrev > 1) ? "ambiguous " : "bad ", msg, " \"", key, "\": must be ", *tablePtr, (char *) NULL); - for (entryPtr = tablePtr+1; *entryPtr != NULL; entryPtr++) { - if (entryPtr[1] == NULL) { - Tcl_AppendStringsToObj(resultPtr, ", or ", *entryPtr, + for (entryPtr = (char **) ((long) tablePtr + offset), count = 0; + *entryPtr != NULL; + entryPtr = (char **) ((long) entryPtr + offset), count++) { + if ((*((char **) ((long) entryPtr + offset))) == NULL) { + Tcl_AppendStringsToObj(resultPtr, + (count > 0) ? ", or " : " or ", *entryPtr, (char *) NULL); } else { Tcl_AppendStringsToObj(resultPtr, ", ", *entryPtr, (char *) NULL); } } } return TCL_ERROR; } - -/* - *---------------------------------------------------------------------- - * - * DupIndexInternalRep -- - * - * Copy the internal representation of an index Tcl_Obj from one - * object to another. - * - * Results: - * None. - * - * Side effects: - * "copyPtr"s internal rep is set to same value as "srcPtr"s - * internal rep. - * - *---------------------------------------------------------------------- - */ - -static void -DupIndexInternalRep(srcPtr, copyPtr) - register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ - register Tcl_Obj *copyPtr; /* Object with internal rep to set. */ -{ - copyPtr->internalRep.twoPtrValue.ptr1 - = srcPtr->internalRep.twoPtrValue.ptr1; - copyPtr->internalRep.twoPtrValue.ptr2 - = srcPtr->internalRep.twoPtrValue.ptr2; - copyPtr->typePtr = &tclIndexType; -} /* *---------------------------------------------------------------------- * * SetIndexFromAny -- @@ -210,35 +260,10 @@ Tcl_AppendToObj(Tcl_GetObjResult(interp), "can't convert value to index except via Tcl_GetIndexFromObj API", -1); return TCL_ERROR; } - -/* - *---------------------------------------------------------------------- - * - * UpdateStringOfIndex -- - * - * This procedure is called to update the string representation for - * an index object. It should never be called, because we never - * invalidate the string representation for an index object. - * - * Results: - * None. - * - * Side effects: - * A panic is added - * - *---------------------------------------------------------------------- - */ - -static void -UpdateStringOfIndex(objPtr) - register Tcl_Obj *objPtr; /* Int object whose string rep to update. */ -{ - panic("UpdateStringOfIndex should never be invoked"); -} /* *---------------------------------------------------------------------- * * Tcl_WrongNumArgs -- @@ -291,12 +316,11 @@ tablePtr = ((char **) objv[i]->internalRep.twoPtrValue.ptr1); Tcl_AppendStringsToObj(objPtr, tablePtr[(int) objv[i]->internalRep.twoPtrValue.ptr2], (char *) NULL); } else { - Tcl_AppendStringsToObj(objPtr, - Tcl_GetStringFromObj(objv[i], (int *) NULL), + Tcl_AppendStringsToObj(objPtr, Tcl_GetString(objv[i]), (char *) NULL); } if (i < (objc - 1)) { Tcl_AppendStringsToObj(objPtr, " ", (char *) NULL); } ADDED generic/tclInitScript.h Index: generic/tclInitScript.h ================================================================== --- /dev/null +++ generic/tclInitScript.h @@ -0,0 +1,82 @@ +/* + * tclInitScript.h -- + * + * This file contains Unix & Windows common init script + * It is not used on the Mac. (the mac init script is in tclMacInit.c) + * + * Copyright (c) 1998 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclInitScript.h,v 1.1.2.3 1999/03/12 23:29:14 surles Exp $ + */ + +/* + * The following string is the startup script executed in new + * interpreters. It looks on disk in several different directories + * for a script "init.tcl" that is compatible with this version + * of Tcl. The init.tcl script does all of the real work of + * initialization. + */ + +static char initScript[] = "if {[info proc tclInit]==\"\"} {\n\ + proc tclInit {} {\n\ + global tcl_libPath tcl_library errorInfo\n\ + rename tclInit {}\n\ + set errors {}\n\ + foreach i $tcl_libPath {\n\ + set tcl_library $i\n\ + set tclfile [file join $i init.tcl]\n\ + if {[file exists $tclfile]} {\n\ + if {[catch {uplevel #0 [list source $tclfile]} msg] != 1} {\n\ + return\n\ + } else {\n\ + append errors \"$tclfile: $msg\n$errorInfo\n\"\n\ + }\n\ + }\n\ + }\n\ + set msg \"Can't find a usable init.tcl in the following directories: \n\"\n\ + append msg \" $tcl_libPath\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"; + + +/* + * A pointer to a string that holds an initialization script that if non-NULL + * is evaluated in Tcl_Init() prior to the the built-in initialization script + * above. This variable can be modified by the procedure below. + */ + +static char * tclPreInitScript = NULL; + + +/* + *---------------------------------------------------------------------- + * + * 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. + * + *---------------------------------------------------------------------- + */ + +char * +TclSetPreInitScript (string) + char *string; /* Pointer to a script. */ +{ + char *prevString = tclPreInitScript; + tclPreInitScript = string; + return(prevString); +} ADDED generic/tclInt.decls Index: generic/tclInt.decls ================================================================== --- /dev/null +++ generic/tclInt.decls @@ -0,0 +1,778 @@ +# 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, +# tclIntStub.c, tclPlatStub.c, tclCompileDecls.h and tclCompileStub.c +# files +# +# 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. +# +# RCS: @(#) $Id: tclInt.decls,v 1.3.2.6 1999/04/06 03:13:16 redman Exp $ + +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. + +declare 0 generic { + int TclAccess(CONST char *path, int mode) +} +declare 1 generic { + int TclAccessDeleteProc(TclAccessProc_ *proc) +} +declare 2 generic { + int TclAccessInsertProc(TclAccessProc_ *proc) +} +declare 3 generic { + void TclAllocateFreeObjects(void) +} +# Replaced by TclpChdir in 8.1: +# declare 4 generic { +# int TclChdir(Tcl_Interp *interp, char *dirName) +# } +declare 5 generic { + int TclCleanupChildren(Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, \ + Tcl_Channel errorChan) +} +declare 6 generic { + void TclCleanupCommand(Command *cmdPtr) +} +declare 7 generic { + int TclCopyAndCollapse(int count, CONST char *src, char *dst) +} +declare 8 generic { + int TclCopyChannel(Tcl_Interp *interp, Tcl_Channel inChan, \ + Tcl_Channel outChan, int toRead, Tcl_Obj *cmdPtr) +} + +# TclCreatePipeline unofficially exported for use by BLT. + +declare 9 generic { + int TclCreatePipeline(Tcl_Interp *interp, int argc, char **argv, \ + Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, \ + TclFile *errFilePtr) +} +declare 10 generic { + int TclCreateProc(Tcl_Interp *interp, Namespace *nsPtr, char *procName, \ + Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Proc **procPtrPtr) +} +declare 11 generic { + void TclDeleteCompiledLocalVars(Interp *iPtr, CallFrame *framePtr) +} +declare 12 generic { + void TclDeleteVars(Interp *iPtr, Tcl_HashTable *tablePtr) +} +declare 13 generic { + int TclDoGlob(Tcl_Interp *interp, char *separators, \ + Tcl_DString *headPtr, char *tail) +} +declare 14 generic { + void TclDumpMemoryInfo(FILE *outFile) +} +# Removed in 8.1: +# declare 15 generic { +# void TclExpandParseValue(ParseValue *pvPtr, int needed) +# } +declare 16 generic { + void TclExprFloatError(Tcl_Interp *interp, double value) +} +declare 17 generic { + int TclFileAttrsCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) +} +declare 18 generic { + int TclFileCopyCmd(Tcl_Interp *interp, int argc, char **argv) +} +declare 19 generic { + int TclFileDeleteCmd(Tcl_Interp *interp, int argc, char **argv) +} +declare 20 generic { + int TclFileMakeDirsCmd(Tcl_Interp *interp, int argc, char **argv) +} +declare 21 generic { + int TclFileRenameCmd(Tcl_Interp *interp, int argc, char **argv) +} +declare 22 generic { + int TclFindElement(Tcl_Interp *interp, CONST char *listStr, \ + int listLength, CONST char **elementPtr, CONST char **nextPtr, \ + int *sizePtr, int *bracePtr) +} +declare 23 generic { + Proc * TclFindProc(Interp *iPtr, char *procName) +} +declare 24 generic { + int TclFormatInt(char *buffer, long n) +} +declare 25 generic { + void TclFreePackageInfo(Interp *iPtr) +} +# Removed in 8.1: +# declare 26 generic { +# char * TclGetCwd(Tcl_Interp *interp) +# } +declare 27 generic { + int TclGetDate(char *p, unsigned long now, long zone, \ + unsigned long *timePtr) +} +declare 28 generic { + Tcl_Channel TclpGetDefaultStdChannel(int type) +} +declare 29 generic { + Tcl_Obj * TclGetElementOfIndexedArray(Tcl_Interp *interp, \ + int localIndex, Tcl_Obj *elemPtr, int leaveErrorMsg) +} +# Replaced by char * TclGetEnv(CONST char *name, Tcl_DString *valuePtr) in 8.1: +# declare 30 generic { +# char * TclGetEnv(CONST char *name) +# } +declare 31 generic { + char * TclGetExtension(char *name) +} +declare 32 generic { + int TclGetFrame(Tcl_Interp *interp, char *str, CallFrame **framePtrPtr) +} +declare 33 generic { + TclCmdProcType TclGetInterpProc(void) +} +declare 34 generic { + int TclGetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, \ + int endValue, int *indexPtr) +} +declare 35 generic { + Tcl_Obj * TclGetIndexedScalar(Tcl_Interp *interp, int localIndex, \ + int leaveErrorMsg) +} +declare 36 generic { + int TclGetLong(Tcl_Interp *interp, char *str, long *longPtr) +} +declare 37 generic { + int TclGetLoadedPackages(Tcl_Interp *interp, char *targetName) +} +declare 38 generic { + int TclGetNamespaceForQualName(Tcl_Interp *interp, char *qualName, \ + Namespace *cxtNsPtr, int flags, Namespace **nsPtrPtr, \ + Namespace **altNsPtrPtr, Namespace **actualCxtPtrPtr, \ + char **simpleNamePtr) +} +declare 39 generic { + TclObjCmdProcType TclGetObjInterpProc(void) +} +declare 40 generic { + int TclGetOpenMode(Tcl_Interp *interp, char *str, int *seekFlagPtr) +} +declare 41 generic { + Tcl_Command TclGetOriginalCommand(Tcl_Command command) +} +declare 42 generic { + char * TclpGetUserHome(CONST char *name, Tcl_DString *bufferPtr) +} +declare 43 generic { + int TclGlobalInvoke(Tcl_Interp *interp, int argc, char **argv, int flags) +} +declare 44 generic { + int TclGuessPackageName(char *fileName, Tcl_DString *bufPtr) +} +declare 45 generic { + int TclHideUnsafeCommands(Tcl_Interp *interp) +} +declare 46 generic { + int TclInExit(void) +} +declare 47 generic { + Tcl_Obj * TclIncrElementOfIndexedArray(Tcl_Interp *interp, \ + int localIndex, Tcl_Obj *elemPtr, long incrAmount) +} +declare 48 generic { + Tcl_Obj * TclIncrIndexedScalar(Tcl_Interp *interp, int localIndex, \ + long incrAmount) +} +declare 49 generic { + Tcl_Obj * TclIncrVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, \ + Tcl_Obj *part2Ptr, long incrAmount, int part1NotParsed) +} +declare 50 generic { + void TclInitCompiledLocals(Tcl_Interp *interp, CallFrame *framePtr, \ + Namespace *nsPtr) +} +declare 51 generic { + int TclInterpInit(Tcl_Interp *interp) +} +declare 52 generic { + int TclInvoke(Tcl_Interp *interp, int argc, char **argv, int flags) +} +declare 53 generic { + int TclInvokeObjectCommand(ClientData clientData, Tcl_Interp *interp, \ + int argc, char **argv) +} +declare 54 generic { + int TclInvokeStringCommand(ClientData clientData, Tcl_Interp *interp, \ + int objc, Tcl_Obj *CONST objv[]) +} +declare 55 generic { + Proc * TclIsProc(Command *cmdPtr) +} +# Replaced with TclpLoadFile in 8.1: +# declare 56 generic { +# 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 generic { +# int TclLooksLikeInt(char *p) +# } +declare 58 generic { + Var * TclLookupVar(Tcl_Interp *interp, char *part1, char *part2, \ + int flags, char *msg, int createPart1, int createPart2, \ + Var **arrayPtrPtr) +} +declare 59 generic { + int TclpMatchFiles(Tcl_Interp *interp, char *separators, \ + Tcl_DString *dirPtr, char *pattern, char *tail) +} +declare 60 generic { + int TclNeedSpace(char *start, char *end) +} +declare 61 generic { + Tcl_Obj * TclNewProcBodyObj(Proc *procPtr) +} +declare 62 generic { + int TclObjCommandComplete(Tcl_Obj *cmdPtr) +} +declare 63 generic { + int TclObjInterpProc(ClientData clientData, Tcl_Interp *interp, \ + int objc, Tcl_Obj *CONST objv[]) +} +declare 64 generic { + int TclObjInvoke(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], \ + int flags) +} +declare 65 generic { + int TclObjInvokeGlobal(Tcl_Interp *interp, int objc, \ + Tcl_Obj *CONST objv[], int flags) +} +declare 66 generic { + int TclOpenFileChannelDeleteProc(TclOpenFileChannelProc_ *proc) +} +declare 67 generic { + int TclOpenFileChannelInsertProc(TclOpenFileChannelProc_ *proc) +} +declare 68 generic { + int TclpAccess(CONST char *path, int mode) +} +declare 69 generic { + char * TclpAlloc(unsigned int size) +} +declare 70 generic { + int TclpCopyFile(CONST char *source, CONST char *dest) +} +declare 71 generic { + int TclpCopyDirectory(CONST char *source, CONST char *dest, \ + Tcl_DString *errorPtr) +} +declare 72 generic { + int TclpCreateDirectory(CONST char *path) +} +declare 73 generic { + int TclpDeleteFile(CONST char *path) +} +declare 74 generic { + void TclpFree(char *ptr) +} +declare 75 generic { + unsigned long TclpGetClicks(void) +} +declare 76 generic { + unsigned long TclpGetSeconds(void) +} +declare 77 generic { + void TclpGetTime(Tcl_Time *time) +} +declare 78 generic { + int TclpGetTimeZone(unsigned long time) +} +declare 79 generic { + int TclpListVolumes(Tcl_Interp *interp) +} +declare 80 generic { + Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp, char *fileName, \ + char *modeString, int permissions) +} +declare 81 generic { + char * TclpRealloc(char *ptr, unsigned int size) +} +declare 82 generic { + int TclpRemoveDirectory(CONST char *path, int recursive, \ + Tcl_DString *errorPtr) +} +declare 83 generic { + int TclpRenameFile(CONST char *source, CONST char *dest) +} +# Removed in 8.1: +# declare 84 generic { +# int TclParseBraces(Tcl_Interp *interp, char *str, char **termPtr, \ +# ParseValue *pvPtr) +# } +# declare 85 generic { +# int TclParseNestedCmd(Tcl_Interp *interp, char *str, int flags, \ +# char **termPtr, ParseValue *pvPtr) +# } +# declare 86 generic { +# int TclParseQuotes(Tcl_Interp *interp, char *str, int termChar, \ +# int flags, char **termPtr, ParseValue *pvPtr) +# } +# declare 87 generic { +# void TclPlatformInit(Tcl_Interp *interp) +# } +declare 88 generic { + char * TclPrecTraceProc(ClientData clientData, Tcl_Interp *interp, \ + char *name1, char *name2, int flags) +} +declare 89 generic { + 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 generic { +# void TclPrintByteCodeObj(Tcl_Interp *interp, Tcl_Obj *objPtr) +# } +declare 91 generic { + void TclProcCleanupProc(Proc *procPtr) +} +declare 92 generic { + int TclProcCompileProc(Tcl_Interp *interp, Proc *procPtr, \ + Tcl_Obj *bodyPtr, Namespace *nsPtr, CONST char *description, \ + CONST char *procName) +} +declare 93 generic { + void TclProcDeleteProc(ClientData clientData) +} +declare 94 generic { + int TclProcInterpProc(ClientData clientData, Tcl_Interp *interp, \ + int argc, char **argv) +} +declare 95 generic { + int TclpStat(CONST char *path, struct stat *buf) +} +declare 96 generic { + int TclRenameCommand(Tcl_Interp *interp, char *oldName, char *newName) +} +declare 97 generic { + void TclResetShadowedCmdRefs(Tcl_Interp *interp, Command *newCmdPtr) +} +declare 98 generic { + int TclServiceIdle(void) +} +declare 99 generic { + Tcl_Obj * TclSetElementOfIndexedArray(Tcl_Interp *interp, \ + int localIndex, Tcl_Obj *elemPtr, Tcl_Obj *objPtr, int leaveErrorMsg) +} +declare 100 generic { + Tcl_Obj * TclSetIndexedScalar(Tcl_Interp *interp, int localIndex, \ + Tcl_Obj *objPtr, int leaveErrorMsg) +} +# TODO: needs to be implemented +# declare 101 generic { +# char * TclSetPreInitScript(char *string) +# } +declare 102 generic { + void TclSetupEnv(Tcl_Interp *interp) +} +declare 103 generic { + int TclSockGetPort(Tcl_Interp *interp, char *str, char *proto, \ + int *portPtr) +} +declare 104 generic { + int TclSockMinimumBuffers(int sock, int size) +} +declare 105 generic { + int TclStat(CONST char *path, TclStat_ *buf) +} +declare 106 generic { + int TclStatDeleteProc(TclStatProc_ *proc) +} +declare 107 generic { + int TclStatInsertProc(TclStatProc_ *proc) +} +declare 108 generic { + void TclTeardownNamespace(Namespace *nsPtr) +} +declare 109 generic { + int TclUpdateReturnInfo(Interp *iPtr) +} +# Removed in 8.1: +# declare 110 generic { +# 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 generic { + void Tcl_AddInterpResolvers(Tcl_Interp *interp, char *name, \ + Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, \ + Tcl_ResolveCompiledVarProc *compiledVarProc) +} +declare 112 generic { + int Tcl_AppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr, \ + Tcl_Obj *objPtr) +} +declare 113 generic { + Tcl_Namespace * Tcl_CreateNamespace(Tcl_Interp *interp, char *name, \ + ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc) +} +declare 114 generic { + void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr) +} +declare 115 generic { + int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr, char *pattern, \ + int resetListFirst) +} +declare 116 generic { + Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, char *name, \ + Tcl_Namespace *contextNsPtr, int flags) +} +declare 117 generic { + Tcl_Namespace * Tcl_FindNamespace(Tcl_Interp *interp, char *name, \ + Tcl_Namespace *contextNsPtr, int flags) +} +declare 118 generic { + int Tcl_GetInterpResolvers(Tcl_Interp *interp, char *name, \ + Tcl_ResolverInfo *resInfo) +} +declare 119 generic { + int Tcl_GetNamespaceResolvers(Tcl_Namespace *namespacePtr, \ + Tcl_ResolverInfo *resInfo) +} +declare 120 generic { + Tcl_Var Tcl_FindNamespaceVar(Tcl_Interp *interp, char *name, \ + Tcl_Namespace *contextNsPtr, int flags) +} +declare 121 generic { + int Tcl_ForgetImport(Tcl_Interp *interp, Tcl_Namespace *nsPtr, \ + char *pattern) +} +declare 122 generic { + Tcl_Command Tcl_GetCommandFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr) +} +declare 123 generic { + void Tcl_GetCommandFullName(Tcl_Interp *interp, Tcl_Command command, \ + Tcl_Obj *objPtr) +} +declare 124 generic { + Tcl_Namespace * Tcl_GetCurrentNamespace(Tcl_Interp *interp) +} +declare 125 generic { + Tcl_Namespace * Tcl_GetGlobalNamespace(Tcl_Interp *interp) +} +declare 126 generic { + void Tcl_GetVariableFullName(Tcl_Interp *interp, Tcl_Var variable, \ + Tcl_Obj *objPtr) +} +declare 127 generic { + int Tcl_Import(Tcl_Interp *interp, Tcl_Namespace *nsPtr, \ + char *pattern, int allowOverwrite) +} +declare 128 generic { + void Tcl_PopCallFrame(Tcl_Interp* interp) +} +declare 129 generic { + int Tcl_PushCallFrame(Tcl_Interp* interp, Tcl_CallFrame *framePtr, \ + Tcl_Namespace *nsPtr, int isProcCallFrame) +} +declare 130 generic { + int Tcl_RemoveInterpResolvers(Tcl_Interp *interp, char *name) +} +declare 131 generic { + void Tcl_SetNamespaceResolvers(Tcl_Namespace *namespacePtr, \ + Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, \ + Tcl_ResolveCompiledVarProc *compiledVarProc) +} +declare 132 generic { + int TclpHasSockets(Tcl_Interp *interp) +} +declare 133 generic { + struct tm * TclpGetDate(TclpTime_t time, int useGMT) +} +declare 134 generic { + size_t TclpStrftime(char *s, size_t maxsize, CONST char *format, \ + CONST struct tm *t) +} +declare 135 generic { + int TclpCheckStackSpace(void) +} + +# Added in 8.1: + +declare 137 generic { + int TclpChdir(CONST char *dirName) +} +declare 138 generic { + char * TclGetEnv(CONST char *name, Tcl_DString *valuePtr) +} +declare 139 generic { + int TclpLoadFile(Tcl_Interp *interp, char *fileName, char *sym1, \ + char *sym2, Tcl_PackageInitProc **proc1Ptr, \ + Tcl_PackageInitProc **proc2Ptr, ClientData *clientDataPtr) +} +declare 140 generic { + int TclLooksLikeInt(char *bytes, int length) +} + +declare 141 generic { + char *TclpGetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr) +} +############################################################################## + +# Define the platform specific internal Tcl interface. These functions are +# only available on the designated platform. + +interface tclIntPlat + +######################## +# Mac specific internals + +declare 0 mac { + VOID * TclpSysAlloc(long size, int isBin) +} +declare 1 mac { + void TclpSysFree(VOID *ptr) +} +declare 2 mac { + VOID * TclpSysRealloc(VOID *cp, unsigned int size) +} +declare 3 mac { + void TclpExit(int status) +} + +# Prototypes for functions found in the tclMacUtil.c compatability library. + +declare 4 mac { + int FSpGetDefaultDir(FSSpecPtr theSpec) +} +declare 5 mac { + int FSpSetDefaultDir(FSSpecPtr theSpec) +} +declare 6 mac { + OSErr FSpFindFolder(short vRefNum, OSType folderType, \ + Boolean createFolder, FSSpec *spec) +} +declare 7 mac { + void GetGlobalMouse(Point *mouse) +} + +# The following routines are utility functions in Tcl. They are exported +# here because they are needed in Tk. They are not officially supported, +# however. The first set are from the MoreFiles package. + +declare 8 mac { + pascal OSErr FSpGetDirectoryID(CONST FSSpec *spec, long *theDirID, \ + Boolean *isDirectory) +} +declare 9 mac { + pascal short FSpOpenResFileCompat(CONST FSSpec *spec, \ + SignedByte permission) +} +declare 10 mac { + pascal void FSpCreateResFileCompat(CONST FSSpec *spec, OSType creator, \ + OSType fileType, ScriptCode scriptTag) +} + +# Like the MoreFiles routines these fix problems in the standard +# Mac calls. These routines are from tclMacUtils.h. + +declare 11 mac { + int FSpLocationFromPath(int length, CONST char *path, FSSpecPtr theSpec) +} +declare 12 mac { + OSErr FSpPathFromLocation(FSSpecPtr theSpec, int *length, \ + Handle *fullPath) +} + +# Prototypes of Mac only internal functions. + +declare 13 mac { + void TclMacExitHandler(void) +} +declare 14 mac { + void TclMacInitExitToShell(int usePatch) +} +declare 15 mac { + OSErr TclMacInstallExitToShellPatch(ExitToShellProcPtr newProc) +} +declare 16 mac { + int TclMacOSErrorToPosixError(int error) +} +declare 17 mac { + void TclMacRemoveTimer(void *timerToken) +} +declare 18 mac { + void * TclMacStartTimer(long ms) +} +declare 19 mac { + int TclMacTimerExpired(void *timerToken) +} +declare 20 mac { + int TclMacRegisterResourceFork(short fileRef, Tcl_Obj *tokenPtr, \ + int insert) +} +declare 21 mac { + short TclMacUnRegisterResourceFork(char *tokenPtr, Tcl_Obj *resultPtr) +} +declare 22 mac { + int TclMacCreateEnv(void) +} +declare 23 mac { + FILE * TclMacFOpenHack(CONST char *path, CONST char *mode) +} +# Replaced in 8.1 by TclpReadLink: +# declare 24 mac { +# int TclMacReadlink(char *path, char *buf, int size) +# } +declare 25 mac { + int TclMacChmod(char *path, int mode) +} + +############################ +# Windows specific internals + +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 FAR * optval, int FAR *optlen) +} +declare 4 win { + HINSTANCE TclWinGetTclInstance(void) +} +# Removed in 8.1: +# declare 5 win { +# HINSTANCE TclWinLoadLibrary(char *name) +# } +declare 6 win { + u_short TclWinNToHS(u_short ns) +} +declare 7 win { + int TclWinSetSockOpt(SOCKET s, int level, int optname, \ + CONST char FAR * optval, int optlen) +} +declare 8 win { + unsigned long TclpGetPid(Tcl_Pid pid) +} +declare 9 win { + int TclWinGetPlatformId(void) +} +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, char **argv, \ + TclFile inputFile, TclFile outputFile, TclFile errorFile, \ + Tcl_Pid *pidPtr) +} +# Signature changed in 8.1: +# declare 16 win { +# TclFile TclpCreateTempFile(char *contents, Tcl_DString *namePtr) +# } +# declare 17 win { +# char * TclpGetTZName(void) +# } +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) +} +declare 21 win { + void TclpAsyncMark(Tcl_AsyncHandler async) +} + +# Added in 8.1: +declare 22 win { + TclFile TclpCreateTempFile(CONST char *contents) +} +declare 23 win { + char * TclpGetTZName(int isdst) +} +declare 24 win { + char * TclWinNoBackslash(char *path) +} + +######################### +# Unix specific internals + +# 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, 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) +} Index: generic/tclInt.h ================================================================== --- generic/tclInt.h +++ generic/tclInt.h @@ -2,17 +2,18 @@ * tclInt.h -- * * Declarations of things used internally by the Tcl interpreter. * * Copyright (c) 1987-1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1993-1997 Lucent Technologies. + * Copyright (c) 1994-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. * - *SCCS: @(#) tclInt.h 1.293 97/08/12 17:07:02 + * RCS: @(#) $Id: tclInt.h,v 1.1.2.21 1999/04/14 00:33:23 surles Exp $ */ #ifndef _TCLINT #define _TCLINT @@ -19,23 +20,20 @@ /* * 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 + * the three groups of #includes is important. For example, stdio.h * is needed by tcl.h, and the _ANSI_ARGS_ declaration in tcl.h is * needed by stdlib.h in some configurations. */ #include #ifndef _TCL #include "tcl.h" #endif -#ifndef _REGEXP -#include "tclRegexp.h" -#endif #include #ifdef NO_LIMITS_H # include "../compat/limits.h" #else @@ -49,16 +47,73 @@ #ifdef NO_STRING_H #include "../compat/string.h" #else #include #endif -#if defined(__STDC__) || defined(HAS_STDARG) -# include + +#undef TCL_STORAGE_CLASS +#ifdef BUILD_tcl +# define TCL_STORAGE_CLASS DLLEXPORT #else -# include +# ifdef USE_TCL_STUBS +# define TCL_STORAGE_CLASS +# else +# define TCL_STORAGE_CLASS DLLIMPORT +# endif #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) _ANSI_ARGS_(( + Tcl_Interp* interp, struct Tcl_ResolvedVarInfo *vinfoPtr)); + +typedef void (Tcl_ResolveVarDeleteProc) _ANSI_ARGS_(( + 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) _ANSI_ARGS_(( + Tcl_Interp* interp, char* name, int length, + Tcl_Namespace *context, Tcl_ResolvedVarInfo **rPtr)); + +typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_(( + Tcl_Interp* interp, char* name, Tcl_Namespace *context, + int flags, Tcl_Var *rPtr)); + +typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_((Tcl_Interp* interp, + 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. *---------------------------------------------------------------- */ @@ -84,11 +139,11 @@ * namespace to, e.g., free clientData. */ struct Namespace *parentPtr; /* Points to the namespace that contains * this one. NULL if this is the global * namespace. */ Tcl_HashTable childTable; /* Contains any child namespaces. Indexed - * by strings; values have type + * by strings; values have type * (Namespace *). */ long nsId; /* Unique id for the namespace. */ Tcl_Interp *interp; /* The interpreter containing this * namespace. */ int flags; /* OR-ed combination of the namespace @@ -101,20 +156,20 @@ * 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 *). + * 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. */ Tcl_HashTable varTable; /* Contains all the (global) variables * currently in this namespace. Indexed - * by strings; values have type (Var *). */ + * 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 @@ -127,10 +182,35 @@ 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 the name resolution + * rules change for this namespace; 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. */ } Namespace; /* * Flags used to represent the status of a namespace: * @@ -148,12 +228,12 @@ * in any byte code 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. */ -#define NS_DYING 0x01 -#define NS_DEAD 0x02 +#define NS_DYING 0x01 +#define NS_DEAD 0x02 /* * Flag passed to TclGetNamespaceForQualName to have it create all namespace * components of a namespace-qualified name that cannot be found. The new * namespaces are created within their specified parent. Note that this @@ -181,20 +261,20 @@ 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, and - * TCL_TRACE_UNSETS. */ + * 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; /* * 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 + * 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 { @@ -222,13 +302,13 @@ 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 + * to be enumerated (it's leftover from * the Tcl_FirstHashEntry call or from - * an "array anymore" command). NULL + * 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. */ @@ -302,11 +382,11 @@ * to the variable's value, a Tcl object. * 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 + * 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 @@ -337,21 +417,36 @@ * 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. + * + * 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. */ #define VAR_SCALAR 0x1 #define VAR_ARRAY 0x2 #define VAR_LINK 0x4 -#define VAR_UNDEFINED 0x8 +#define VAR_UNDEFINED 0x8 #define VAR_IN_HASHTABLE 0x10 #define VAR_TRACE_ACTIVE 0x20 #define VAR_ARRAY_ELEMENT 0x40 #define VAR_NAMESPACE_VAR 0x80 +#define VAR_ARGUMENT 0x100 +#define VAR_TEMPORARY 0x200 +#define VAR_RESOLVED 0x400 + /* * Macros to ensure that various flag bits are set properly for variables. * The ANSI C "prototypes" for these macros are: * * EXTERN void TclSetVarScalar _ANSI_ARGS_((Var *varPtr)); @@ -387,10 +482,13 @@ * EXTERN int TclIsVarScalar _ANSI_ARGS_((Var *varPtr)); * EXTERN int TclIsVarLink _ANSI_ARGS_((Var *varPtr)); * EXTERN int TclIsVarArray _ANSI_ARGS_((Var *varPtr)); * EXTERN int TclIsVarUndefined _ANSI_ARGS_((Var *varPtr)); * EXTERN int TclIsVarArrayElement _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarTemporary _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarArgument _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarResolved _ANSI_ARGS_((Var *varPtr)); */ #define TclIsVarScalar(varPtr) \ ((varPtr)->flags & VAR_SCALAR) @@ -404,10 +502,19 @@ ((varPtr)->flags & VAR_UNDEFINED) #define TclIsVarArrayElement(varPtr) \ ((varPtr)->flags & VAR_ARRAY_ELEMENT) +#define TclIsVarTemporary(varPtr) \ + ((varPtr)->flags & VAR_TEMPORARY) + +#define TclIsVarArgument(varPtr) \ + ((varPtr)->flags & VAR_ARGUMENT) + +#define TclIsVarResolved(varPtr) \ + ((varPtr)->flags & VAR_RESOLVED) + /* *---------------------------------------------------------------- * Data structures related to procedures. These are used primarily * in tclProc.c, tclCompile.c, and tclExecute.c. *---------------------------------------------------------------- @@ -441,22 +548,25 @@ 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 isArg; /* 1 if the local variable is a formal - * argument. */ - int isTemp; /* 1 if the local variable is an anonymous - * temporary variable. Temporaries have - * a NULL name. */ int flags; /* Flag bits for the local variable. Same as * the flags for the Var structure above, - * although only VAR_SCALAR, VAR_ARRAY, and - * VAR_LINK make sense. */ + * although only VAR_SCALAR, VAR_ARRAY, + * VAR_LINK, 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[4]; /* 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! */ @@ -495,11 +605,11 @@ * variable or NULL if none. This has * frame index (numCompiledLocals-1). */ } Proc; /* - * The structure below defines a command trace. This is used to allow Tcl + * 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 @@ -517,11 +627,11 @@ */ typedef struct AssocData { Tcl_InterpDeleteProc *proc; /* Proc to call when deleting. */ ClientData clientData; /* Value to pass to proc. */ -} AssocData; +} 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 @@ -581,11 +691,26 @@ * using an index into this array. */ } CallFrame; /* *---------------------------------------------------------------- - * Data structures related to history. These are used primarily + * 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; + +TclHandle TclHandleCreate _ANSI_ARGS_((VOID *ptr)); +void TclHandleFree _ANSI_ARGS_((TclHandle handle)); +TclHandle TclHandlePreserve _ANSI_ARGS_((TclHandle handle)); +void TclHandleRelease _ANSI_ARGS_((TclHandle handle)); + +/* + *---------------------------------------------------------------- + * Data structures related to history. These are used primarily * in tclHistory.c *---------------------------------------------------------------- */ /* @@ -648,24 +773,46 @@ ClientData clientData; /* Additional argument to pass to the * function when invoking it. NULL if * isBuiltinFunc is 1. */ } MathFunc; +/* + * 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. + */ + +EXTERN VOID *TclThreadDataKeyGet _ANSI_ARGS_((Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclThreadDataKeySet _ANSI_ARGS_((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)) + + +#ifdef MAC_TCL +typedef pascal void *(Tcl_ThreadCreateProc) _ANSI_ARGS_((ClientData clientData)); +#else +typedef void (Tcl_ThreadCreateProc) _ANSI_ARGS_((ClientData clientData)); +#endif + /* *---------------------------------------------------------------- * Data structures related to bytecode compilation and execution. * These are used primarily in tclCompile.c, tclExecute.c, and * tclBasic.c. *---------------------------------------------------------------- */ /* - * Forward declaration to prevent an error when the forward reference to - * CompileEnv is encountered in the procedure type CompileProc declared - * below. + * Forward declaration to prevent errors when the forward references to + * Tcl_Parse and CompileEnv are encountered in the procedure type + * CompileProc declared below. */ +struct Tcl_Parse; 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 @@ -683,12 +830,12 @@ * to invoke its command procedure at runtime. */ #define TCL_OUT_LINE_COMPILE (TCL_CONTINUE + 1) -typedef int (CompileProc) _ANSI_ARGS_((Tcl_Interp *interp, char *string, - char *lastChar, int compileFlags, struct CompileEnv *compEnvPtr)); +typedef int (CompileProc) _ANSI_ARGS_((Tcl_Interp *interp, + struct Tcl_Parse *parsePtr, struct CompileEnv *compEnvPtr)); /* * 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 @@ -696,24 +843,105 @@ * TclExecuteByteCode in a local variable: it must be set before calling * TclExecuteByteCode and will be restored by TclExecuteByteCode before it * returns. */ -typedef union StackItem { - Tcl_Obj *o; /* Stack item as a pointer to a Tcl_Obj. */ - int i; /* Stack item as an integer. */ - VOID *p; /* Stack item as an arbitrary pointer. */ -} StackItem; - typedef struct ExecEnv { - StackItem *stackPtr; /* Points to the first item in the + Tcl_Obj **stackPtr; /* Points to the first item in the * evaluation stack on the heap. */ int stackTop; /* Index of current top of stack; -1 when * the stack is empty. */ int stackEnd; /* Index of last usable item in stack. */ } ExecEnv; +/* + * 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. */ +} 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 */ + /* *---------------------------------------------------------------- * Data structures related to commands. *---------------------------------------------------------------- */ @@ -726,11 +954,11 @@ * 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 + /* 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 @@ -737,10 +965,25 @@ * "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. */ @@ -762,13 +1005,13 @@ * 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 + * that point to this command when it is * renamed, deleted, hidden, or exposed. */ - CompileProc *compileProc; /* Procedure called to compile command. NULL + 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. */ @@ -787,10 +1030,42 @@ * command. The list is used to remove all * those imported commands when deleting * this "real" command. */ } Command; +/* + *---------------------------------------------------------------- + * 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; + /* *---------------------------------------------------------------- * 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 @@ -801,11 +1076,11 @@ 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 + * 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 @@ -815,40 +1090,57 @@ * 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 + 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. */ + 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). */ - Tcl_Obj *objResultPtr; /* If the last command returned an object - * result, this points to it. Should not be - * accessed directly; see comment above. */ - Namespace *globalNsPtr; /* The interpreter's global namespace. */ + 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. */ Tcl_HashTable mathFuncTable;/* Contains all the math functions currently - * defined for the interpreter. Indexed by + * defined for the interpreter. Indexed by * strings (function names); values have * type (MathFunc *). */ + + /* * 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 + * 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. */ @@ -870,35 +1162,38 @@ char *errorCode; /* Value to store in errorCode if returnCode * is TCL_ERROR. Malloc'ed, may be NULL */ /* * Information used by Tcl_AppendResult to keep track of partial - * results. See Tcl_AppendResult code for details. + * results. See Tcl_AppendResult code for details. */ char *appendResult; /* Storage space for results generated - * by Tcl_AppendResult. Malloc-ed. NULL + * by Tcl_AppendResult. Malloc-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. */ /* - * A cache of compiled regular expressions. See Tcl_RegExpCompile - * in tclUtil.c for details. + * A cache of compiled regular expressions. See Tcl_RegExpCompile + * in tclUtil.c for details. THIS CACHE IS OBSOLETE and is only + * retained for backward compatibility with Tcl_RegExpCompile. + * New code should use the object interface so the Tcl_Obj caches + * the compiled expression. */ #define NUM_REGEXPS 5 char *patterns[NUM_REGEXPS];/* Strings corresponding to compiled - * regular expression patterns. NULL + * 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. */ - regexp *regexps[NUM_REGEXPS]; + struct TclRegexp *regexps[NUM_REGEXPS]; /* Compiled forms of above strings. Also * malloc-ed, or NULL if not in use yet. */ /* * Information about packages. Used only in tclPkg.c. @@ -923,10 +1218,16 @@ * Normally zero, but may be set before * calling Tcl_Eval. See below for valid * values. */ int termOffset; /* Offset of character just after last one * compiled or executed by Tcl_EvalObj. */ + 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. */ @@ -933,39 +1234,59 @@ 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/removed by calling + * Tcl_AddInterpResolvers and + * Tcl_RemoveInterpResolver. */ char *scriptFile; /* NULL means there is no nested source * command active; otherwise this points to * the name of the file being sourced (it's * not malloc-ed: it points to an argument * to Tcl_EvalFile. */ 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. */ + * this interpreter. Cleaned up when + * this interpreter is deleted. */ struct ExecEnv *execEnvPtr; /* Execution environment for Tcl bytecode - * execution. Contains a pointer to the + * 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 */ + + /* + * Statistical information about the bytecode compiler and interpreter's + * operation. + */ + +#ifdef TCL_COMPILE_STATS + ByteCodeStats stats; /* Holds compilation and execution + * statistics for this interpreter. */ +#endif /* TCL_COMPILE_STATS */ } Interp; /* * EvalFlag bits for Interp structures: * * TCL_BRACKET_TERM 1 means that the current script is terminated by * a close bracket rather than the end of the string. * 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 + * a code other than TCL_OK or TCL_ERROR; 0 means * codes other than these should be turned into errors. */ #define TCL_BRACKET_TERM 1 #define TCL_ALLOW_EXCEPTIONS 4 @@ -984,34 +1305,39 @@ * in $errorInfo for the current Tcl_Eval instance, * so Tcl_Eval needn't log it (used to implement the * "error message log" command). * ERROR_CODE_SET: Non-zero means that Tcl_SetErrorCode has been * called to record information for the current - * error. Zero means Tcl_Eval must clear the + * error. Zero means Tcl_Eval must clear the * errorCode variable if an error is returned. * EXPR_INITIALIZED: Non-zero means initialization specific to * expressions has been carried out. * 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 + * 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 (ie it has only the safe commands - * installed, less priviledge than a regular interp). + * SAFE_INTERP: Non zero means that the current interp is a + * safe interp (ie it has only the safe commands + * installed, less priviledge than a regular interp). + * USE_EVAL_DIRECT: Non-zero means don't use the compiler or byte-code + * interpreter; instead, have Tcl_EvalObj call + * Tcl_EvalEx. Used primarily for testing the + * new parser. */ -#define DELETED 1 -#define ERR_IN_PROGRESS 2 -#define ERR_ALREADY_LOGGED 4 -#define ERROR_CODE_SET 8 -#define EXPR_INITIALIZED 0x10 -#define DONT_COMPILE_CMDS_INLINE 0x20 -#define RAND_SEED_INITIALIZED 0x40 -#define SAFE_INTERP 0x80 +#define DELETED 1 +#define ERR_IN_PROGRESS 2 +#define ERR_ALREADY_LOGGED 4 +#define ERROR_CODE_SET 8 +#define EXPR_INITIALIZED 0x10 +#define DONT_COMPILE_CMDS_INLINE 0x20 +#define RAND_SEED_INITIALIZED 0x40 +#define SAFE_INTERP 0x80 +#define USE_EVAL_DIRECT 0x100 /* *---------------------------------------------------------------- * Data structures related to command parsing. These are used in * tclParse.c and its clients. @@ -1039,52 +1365,10 @@ * it will make more space. */ ClientData clientData; /* Arbitrary information for use of * expandProc. */ } ParseValue; -/* - * A table used to classify input characters to assist in parsing - * Tcl commands. The table should be indexed with a signed character - * using the CHAR_TYPE macro. The character may have a negative - * value. The CHAR_TYPE macro takes a pointer to a signed character - * and a pointer to the last character in the source string. If the - * src pointer is pointing at the terminating null of the string, - * CHAR_TYPE returns TCL_COMMAND_END. - */ - -extern unsigned char tclTypeTable[]; -#define CHAR_TYPE(src,last) \ - (((src)==(last))?TCL_COMMAND_END:(tclTypeTable+128)[*(src)]) - -/* - * Possible values returned by CHAR_TYPE. Note that except for TCL_DOLLAR, - * these are all one byte values with a single bit set 1. This means these - * values may be bit-or'ed together (except for TCL_DOLLAR) to quickly test - * whether a character is one of several different kinds of characters. - * - * TCL_NORMAL - All characters that don't have special significance - * to the Tcl language. - * TCL_SPACE - Character is space, tab, or return. - * TCL_COMMAND_END - Character is newline or semicolon or close-bracket - * or terminating null. - * TCL_QUOTE - Character is a double-quote. - * TCL_OPEN_BRACKET - Character is a "[". - * TCL_OPEN_BRACE - Character is a "{". - * TCL_CLOSE_BRACE - Character is a "}". - * TCL_BACKSLASH - Character is a "\". - * TCL_DOLLAR - Character is a "$". - */ - -#define TCL_NORMAL 0x01 -#define TCL_SPACE 0x02 -#define TCL_COMMAND_END 0x04 -#define TCL_QUOTE 0x08 -#define TCL_OPEN_BRACKET 0x10 -#define TCL_OPEN_BRACE 0x20 -#define TCL_CLOSE_BRACE 0x40 -#define TCL_BACKSLASH 0x80 -#define TCL_DOLLAR 0x00 /* * Maximum number of levels of nesting permitted in Tcl commands (used * to catch infinite recursion). */ @@ -1132,14 +1416,19 @@ * 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 is an array of pointers to the element objects. This array * is grown (reallocated and copied) as necessary to hold all the list's @@ -1151,10 +1440,11 @@ typedef struct List { int maxElemCount; /* Total number of element array slots. */ int elemCount; /* Current number of list elements. */ Tcl_Obj **elements; /* Array of pointers to element objects. */ } List; + /* * 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 @@ -1161,18 +1451,16 @@ * in the file attributes code. For more information about the callbacks, * see TclFileAttrsCmd in tclFCmd.c. */ typedef int (TclGetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp, - int objIndex, char *fileName, - Tcl_Obj **attrObjPtrPtr)); + int objIndex, CONST char *fileName, Tcl_Obj **attrObjPtrPtr)); typedef int (TclSetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp, - int objIndex, char *fileName, - Tcl_Obj *attrObjPtr)); + int objIndex, CONST char *fileName, Tcl_Obj *attrObjPtr)); typedef struct TclFileAttrProcs { - TclGetFileAttrProc *getProc; /* The procedure for getting attrs. */ + 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 @@ -1179,34 +1467,63 @@ * state. */ typedef struct TclFile_ *TclFile; +/* + *---------------------------------------------------------------- + * Data structures related to hooking 'TclStat(...)' and + * 'TclAccess(...)'. + *---------------------------------------------------------------- + */ + +typedef struct stat TclStat_; +typedef int (TclStatProc_) _ANSI_ARGS_((CONST char *path, TclStat_ *buf)); +typedef int (TclAccessProc_) _ANSI_ARGS_((CONST char *path, int mode)); +typedef Tcl_Channel (TclOpenFileChannelProc_) _ANSI_ARGS_((Tcl_Interp *interp, + char *fileName, char *modeString, + int permissions)); + +typedef int (*TclCmdProcType) _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char *argv[])); +typedef int (*TclObjCmdProcType) _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, struct Tcl_Obj * CONST objv[])); + +/* + * Opaque names for platform specific types. + */ + +typedef struct TclpTime_t_ *TclpTime_t; + /* *---------------------------------------------------------------- * Variables shared among Tcl modules but not used by the outside world. *---------------------------------------------------------------- */ extern Tcl_Time tclBlockTime; extern int tclBlockTimeSet; extern char * tclExecutableName; -extern Tcl_ChannelType tclFileChannelType; +extern char * tclNativeExecutableName; +extern char * tclDefaultEncodingDir; +extern Tcl_ChannelType tclFileChannelType; extern char * tclMemDumpFileName; extern TclPlatformType tclPlatform; extern char * tclpFileAttrStrings[]; -extern CONST TclFileAttrProcs tclpFileAttrProcs[]; +extern CONST TclFileAttrProcs tclpFileAttrProcs[]; /* * Variables denoting the Tcl object types defined in the core. */ extern Tcl_ObjType tclBooleanType; +extern Tcl_ObjType tclByteArrayType; extern Tcl_ObjType tclByteCodeType; extern Tcl_ObjType tclDoubleType; extern Tcl_ObjType tclIntType; extern Tcl_ObjType tclListType; +extern Tcl_ObjType tclProcBodyType; extern Tcl_ObjType tclStringType; /* * The head of the list of free Tcl objects, and the total number of Tcl * objects ever allocated and freed. @@ -1213,12 +1530,12 @@ */ extern Tcl_Obj * tclFreeObjList; #ifdef TCL_COMPILE_STATS -extern long tclObjsAlloced; -extern long tclObjsFreed; +extern long tclObjsAlloced; +extern long tclObjsFreed; #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 @@ -1232,24 +1549,21 @@ * Procedures shared among Tcl modules but not used by the outside * world: *---------------------------------------------------------------- */ -EXTERN void panic _ANSI_ARGS_(TCL_VARARGS(char *,format)); +EXTERN int TclAccess _ANSI_ARGS_((CONST char *path, + int mode)); +EXTERN int TclAccessDeleteProc _ANSI_ARGS_((TclAccessProc_ *proc)); +EXTERN int TclAccessInsertProc _ANSI_ARGS_((TclAccessProc_ *proc)); EXTERN void TclAllocateFreeObjects _ANSI_ARGS_((void)); -EXTERN int TclChdir _ANSI_ARGS_((Tcl_Interp *interp, - char *dirName)); +EXTERN int TclArraySet _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj)); EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp *interp, - int numPids, Tcl_Pid *pidPtr, + int numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan)); EXTERN void TclCleanupCommand _ANSI_ARGS_((Command *cmdPtr)); -EXTERN char * TclConvertToNative _ANSI_ARGS_((Tcl_Interp *interp, - char *name, Tcl_DString *bufferPtr)); -EXTERN char * TclConvertToNetwork _ANSI_ARGS_((Tcl_Interp *interp, - char *name, Tcl_DString *bufferPtr)); -EXTERN int TclCopyAndCollapse _ANSI_ARGS_((int count, - char *src, char *dst)); EXTERN int TclCopyChannel _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj *cmdPtr)); /* * TclCreatePipeline unofficially exported for use by BLT. @@ -1261,60 +1575,66 @@ EXTERN int TclCreateProc _ANSI_ARGS_((Tcl_Interp *interp, Namespace *nsPtr, char *procName, Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Proc **procPtrPtr)); EXTERN void TclDeleteCompiledLocalVars _ANSI_ARGS_(( - Interp *iPtr, CallFrame *framePtr)); + Interp *iPtr, CallFrame *framePtr)); EXTERN void TclDeleteVars _ANSI_ARGS_((Interp *iPtr, Tcl_HashTable *tablePtr)); EXTERN int TclDoGlob _ANSI_ARGS_((Tcl_Interp *interp, char *separators, Tcl_DString *headPtr, char *tail)); EXTERN void TclDumpMemoryInfo _ANSI_ARGS_((FILE *outFile)); -EXTERN void TclExpandParseValue _ANSI_ARGS_((ParseValue *pvPtr, - int needed)); +EXTERN void TclExpandTokenArray _ANSI_ARGS_(( + Tcl_Parse *parsePtr)); EXTERN void TclExprFloatError _ANSI_ARGS_((Tcl_Interp *interp, double value)); EXTERN int TclFileAttrsCmd _ANSI_ARGS_((Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int TclFileCopyCmd _ANSI_ARGS_((Tcl_Interp *interp, int argc, char **argv)) ; -EXTERN int TclFileDeleteCmd _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int TclFileDeleteCmd _ANSI_ARGS_((Tcl_Interp *interp, int argc, char **argv)); EXTERN int TclFileMakeDirsCmd _ANSI_ARGS_((Tcl_Interp *interp, int argc, char **argv)) ; EXTERN int TclFileRenameCmd _ANSI_ARGS_((Tcl_Interp *interp, int argc, char **argv)) ; +EXTERN void TclFinalizeAllocSubsystem _ANSI_ARGS_((void)); EXTERN void TclFinalizeCompExecEnv _ANSI_ARGS_((void)); +EXTERN void TclFinalizeCondition _ANSI_ARGS_(( + Tcl_Condition *condPtr)); +EXTERN void TclFinalizeCompilation _ANSI_ARGS_((void)); +EXTERN void TclFinalizeEncodingSubsystem _ANSI_ARGS_((void)); EXTERN void TclFinalizeEnvironment _ANSI_ARGS_((void)); -EXTERN void TclFinalizeExecEnv _ANSI_ARGS_((void)); -EXTERN int TclFindElement _ANSI_ARGS_((Tcl_Interp *interp, - char *list, int listLength, char **elementPtr, - char **nextPtr, int *sizePtr, int *bracePtr)); +EXTERN void TclFinalizeExecution _ANSI_ARGS_((void)); +EXTERN void TclFinalizeIOSubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeLoad _ANSI_ARGS_((void)); +EXTERN void TclFinalizeMemorySubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeMutex _ANSI_ARGS_((Tcl_Mutex *mutex)); +EXTERN void TclFinalizeNotifier _ANSI_ARGS_((void)); +EXTERN void TclFinalizeSynchronization _ANSI_ARGS_((void)); +EXTERN void TclFinalizeThreadData _ANSI_ARGS_((void)); +EXTERN void TclFindEncodings _ANSI_ARGS_((CONST char *argv0)); EXTERN Proc * TclFindProc _ANSI_ARGS_((Interp *iPtr, char *procName)); EXTERN int TclFormatInt _ANSI_ARGS_((char *buffer, long n)); EXTERN void TclFreePackageInfo _ANSI_ARGS_((Interp *iPtr)); -EXTERN void TclGetAndDetachPids _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan)); -EXTERN char * TclGetCwd _ANSI_ARGS_((Tcl_Interp *interp)); EXTERN int TclGetDate _ANSI_ARGS_((char *p, unsigned long now, long zone, unsigned long *timePtr)); -EXTERN Tcl_Channel TclGetDefaultStdChannel _ANSI_ARGS_((int type)); EXTERN Tcl_Obj * TclGetElementOfIndexedArray _ANSI_ARGS_(( - Tcl_Interp *interp, int localIndex, + Tcl_Interp *interp, int localIndex, Tcl_Obj *elemPtr, int leaveErrorMsg)); -EXTERN char * TclGetEnv _ANSI_ARGS_((CONST char *name)); EXTERN char * TclGetExtension _ANSI_ARGS_((char *name)); EXTERN int TclGetFrame _ANSI_ARGS_((Tcl_Interp *interp, char *string, CallFrame **framePtrPtr)); -EXTERN int TclGetIdleGeneration _ANSI_ARGS_((void)); +EXTERN TclCmdProcType TclGetInterpProc _ANSI_ARGS_((void)); EXTERN int TclGetIntForIndex _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr)); EXTERN Tcl_Obj * TclGetIndexedScalar _ANSI_ARGS_((Tcl_Interp *interp, int localIndex, int leaveErrorMsg)); +EXTERN Tcl_Obj * TclGetLibraryPath _ANSI_ARGS_((void)); EXTERN int TclGetLong _ANSI_ARGS_((Tcl_Interp *interp, char *string, long *longPtr)); EXTERN int TclGetLoadedPackages _ANSI_ARGS_(( Tcl_Interp *interp, char *targetName)); EXTERN int TclGetNamespaceForQualName _ANSI_ARGS_(( @@ -1321,168 +1641,190 @@ Tcl_Interp *interp, char *qualName, Namespace *cxtNsPtr, int flags, Namespace **nsPtrPtr, Namespace **altNsPtrPtr, Namespace **actualCxtPtrPtr, char **simpleNamePtr)); +EXTERN TclObjCmdProcType TclGetObjInterpProc _ANSI_ARGS_((void)); EXTERN int TclGetOpenMode _ANSI_ARGS_((Tcl_Interp *interp, - char *string, int *seekFlagPtr)); + char *string, int *seekFlagPtr)); EXTERN Tcl_Command TclGetOriginalCommand _ANSI_ARGS_(( Tcl_Command command)); -EXTERN char * TclGetUserHome _ANSI_ARGS_((char *name, - Tcl_DString *bufferPtr)); +EXTERN int TclGlob _ANSI_ARGS_((Tcl_Interp *interp, + char *pattern, int noComplain)); EXTERN int TclGlobalInvoke _ANSI_ARGS_((Tcl_Interp *interp, - int argc, char **argv, int flags)); + int argc, char **argv, int flags)); EXTERN int TclGuessPackageName _ANSI_ARGS_((char *fileName, Tcl_DString *bufPtr)); -EXTERN int TclHasPipes _ANSI_ARGS_((void)); -EXTERN int TclHasSockets _ANSI_ARGS_((Tcl_Interp *interp)); EXTERN int TclHideUnsafeCommands _ANSI_ARGS_(( - Tcl_Interp *interp)); -EXTERN int TclIdlePending _ANSI_ARGS_((void)); + Tcl_Interp *interp)); EXTERN int TclInExit _ANSI_ARGS_((void)); EXTERN Tcl_Obj * TclIncrElementOfIndexedArray _ANSI_ARGS_(( - Tcl_Interp *interp, int localIndex, + Tcl_Interp *interp, int localIndex, Tcl_Obj *elemPtr, long incrAmount)); EXTERN Tcl_Obj * TclIncrIndexedScalar _ANSI_ARGS_(( - Tcl_Interp *interp, int localIndex, + Tcl_Interp *interp, int localIndex, long incrAmount)); EXTERN Tcl_Obj * TclIncrVar2 _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, - long incrAmount, int part1NotParsed)); -EXTERN void TclInitNamespaces _ANSI_ARGS_((void)); -EXTERN int TclInterpInit _ANSI_ARGS_((Tcl_Interp *interp)); + long incrAmount, int flags)); +EXTERN void TclInitAlloc _ANSI_ARGS_((void)); +EXTERN void TclInitCompiledLocals _ANSI_ARGS_(( + Tcl_Interp *interp, CallFrame *framePtr, + Namespace *nsPtr)); +EXTERN void TclInitDbCkalloc _ANSI_ARGS_((void)); +EXTERN void TclInitEncodingSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitIOSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitNamespaceSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitNotifier _ANSI_ARGS_((void)); +EXTERN void TclInitObjSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitSubsystems _ANSI_ARGS_((CONST char *argv0)); EXTERN int TclInvoke _ANSI_ARGS_((Tcl_Interp *interp, - int argc, char **argv, int flags)); + int argc, char **argv, int flags)); EXTERN int TclInvokeObjectCommand _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - int argc, char **argv)); + ClientData clientData, Tcl_Interp *interp, + int argc, char **argv)); EXTERN int TclInvokeStringCommand _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[])); + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int TclIsLocalScalar _ANSI_ARGS_((CONST char *src, + int len)); EXTERN Proc * TclIsProc _ANSI_ARGS_((Command *cmdPtr)); -EXTERN int TclLoadFile _ANSI_ARGS_((Tcl_Interp *interp, - char *fileName, char *sym1, char *sym2, - Tcl_PackageInitProc **proc1Ptr, - Tcl_PackageInitProc **proc2Ptr)); -EXTERN int TclLooksLikeInt _ANSI_ARGS_((char *p)); EXTERN Var * TclLookupVar _ANSI_ARGS_((Tcl_Interp *interp, char *part1, char *part2, int flags, char *msg, int createPart1, int createPart2, Var **arrayPtrPtr)); -EXTERN int TclMakeFileTable _ANSI_ARGS_((Tcl_Interp *interp, - int noStdio)); -EXTERN int TclMatchFiles _ANSI_ARGS_((Tcl_Interp *interp, - char *separators, Tcl_DString *dirPtr, - char *pattern, char *tail)); +EXTERN int TclMathInProgress _ANSI_ARGS_((void)); EXTERN int TclNeedSpace _ANSI_ARGS_((char *start, char *end)); +EXTERN Tcl_Obj * TclNewProcBodyObj _ANSI_ARGS_((Proc *procPtr)); EXTERN int TclObjCommandComplete _ANSI_ARGS_((Tcl_Obj *cmdPtr)); EXTERN int TclObjInterpProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int TclObjInvoke _ANSI_ARGS_((Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[], int flags)); + int objc, Tcl_Obj *CONST objv[], int flags)); EXTERN int TclObjInvokeGlobal _ANSI_ARGS_((Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[], int flags)); + int objc, Tcl_Obj *CONST objv[], int flags)); +EXTERN int TclOpenFileChannelDeleteProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ *proc)); +EXTERN int TclOpenFileChannelInsertProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ *proc)); +EXTERN int TclpAccess _ANSI_ARGS_((CONST char *filename, + int mode)); EXTERN char * TclpAlloc _ANSI_ARGS_((unsigned int size)); - -/* - * On a Mac, we can exit gracefully if the stack gets too small. - */ - -#ifdef MAC_TCL EXTERN int TclpCheckStackSpace _ANSI_ARGS_((void)); -#else -#define TclpCheckStackSpace() (1) -#endif - -EXTERN int TclpCloseFile _ANSI_ARGS_((TclFile file)); -EXTERN int TclpCopyFile _ANSI_ARGS_((char *source, char *dest)); -EXTERN int TclpCopyDirectory _ANSI_ARGS_((char *source, - char *dest, Tcl_DString *errorPtr)); -EXTERN Tcl_Channel TclpCreateCommandChannel _ANSI_ARGS_(( - TclFile readFile, TclFile writeFile, - TclFile errorFile, int numPids, Tcl_Pid *pidPtr)); -EXTERN int TclpCreateDirectory _ANSI_ARGS_((char *path)); -EXTERN int TclpCreatePipe _ANSI_ARGS_((TclFile *readPipe, - TclFile *writePipe)); -EXTERN int TclpCreateProcess _ANSI_ARGS_((Tcl_Interp *interp, - int argc, char **argv, TclFile inputFile, - TclFile outputFile, TclFile errorFile, - Tcl_Pid *pidPtr)); -EXTERN TclFile TclpCreateTempFile _ANSI_ARGS_((char *contents, - Tcl_DString *namePtr)); -EXTERN int TclpDeleteFile _ANSI_ARGS_((char *path)); +EXTERN int TclpCopyFile _ANSI_ARGS_((CONST char *source, + CONST char *dest)); +EXTERN int TclpCopyDirectory _ANSI_ARGS_((CONST char *source, + CONST char *dest, Tcl_DString *errorPtr)); +EXTERN int TclpCreateDirectory _ANSI_ARGS_((CONST char *path)); +EXTERN int TclpDeleteFile _ANSI_ARGS_((CONST char *path)); +EXTERN void TclpExit _ANSI_ARGS_((int status)); +EXTERN void TclpFinalizeCondition _ANSI_ARGS_(( + Tcl_Condition *condPtr)); +EXTERN void TclpFinalizeMutex _ANSI_ARGS_((Tcl_Mutex *mutexPtr)); +EXTERN void TclpFinalizeThreadData _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpFinalizeThreadDataKey _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN char * TclpFindExecutable _ANSI_ARGS_(( + CONST char *argv0)); +EXTERN int TclpFindVariable _ANSI_ARGS_((CONST char *name, + int *lengthPtr)); EXTERN void TclpFree _ANSI_ARGS_((char *ptr)); EXTERN unsigned long TclpGetClicks _ANSI_ARGS_((void)); +EXTERN Tcl_Channel TclpGetDefaultStdChannel _ANSI_ARGS_((int type)); EXTERN unsigned long TclpGetSeconds _ANSI_ARGS_((void)); EXTERN void TclpGetTime _ANSI_ARGS_((Tcl_Time *time)); EXTERN int TclpGetTimeZone _ANSI_ARGS_((unsigned long time)); -EXTERN char * TclpGetTZName _ANSI_ARGS_((void)); +EXTERN char * TclpGetUserHome _ANSI_ARGS_((CONST char *name, + Tcl_DString *bufferPtr)); +EXTERN int TclpHasSockets _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN void TclpInitLibraryPath _ANSI_ARGS_((CONST char *argv0)); +EXTERN void TclpInitLock _ANSI_ARGS_((void)); +EXTERN void TclpInitPlatform _ANSI_ARGS_((void)); +EXTERN void TclpInitUnlock _ANSI_ARGS_((void)); EXTERN int TclpListVolumes _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN TclFile TclpMakeFile _ANSI_ARGS_((Tcl_Channel channel, - int direction)); -EXTERN TclFile TclpOpenFile _ANSI_ARGS_((char *fname, int mode)); +EXTERN void TclpMasterLock _ANSI_ARGS_((void)); +EXTERN void TclpMasterUnlock _ANSI_ARGS_((void)); +EXTERN int TclpMatchFiles _ANSI_ARGS_((Tcl_Interp *interp, + char *separators, Tcl_DString *dirPtr, + char *pattern, char *tail)); +EXTERN Tcl_Channel TclpOpenFileChannel _ANSI_ARGS_((Tcl_Interp *interp, + char *fileName, char *modeString, + int permissions)); +EXTERN char * TclpReadlink _ANSI_ARGS_((CONST char *fileName, + Tcl_DString *linkPtr)); EXTERN char * TclpRealloc _ANSI_ARGS_((char *ptr, unsigned int size)); -EXTERN int TclpRemoveDirectory _ANSI_ARGS_((char *path, +EXTERN void TclpReleaseFile _ANSI_ARGS_((TclFile file)); +EXTERN int TclpRemoveDirectory _ANSI_ARGS_((CONST char *path, int recursive, Tcl_DString *errorPtr)); -EXTERN int TclpRenameFile _ANSI_ARGS_((char *source, char *dest)); -EXTERN char * TclpSetEnv _ANSI_ARGS_((CONST char *name, - CONST char *value)); -#ifndef TclpSysAlloc -EXTERN VOID * TclpSysAlloc _ANSI_ARGS_((long size, int isBin)); -#endif -#ifndef TclpSysFree -EXTERN void TclpSysFree _ANSI_ARGS_((VOID *ptr)); -#endif -#ifndef TclpSysRealloc -EXTERN VOID * TclpSysRealloc _ANSI_ARGS_((VOID *cp, +EXTERN int TclpRenameFile _ANSI_ARGS_((CONST char *source, + CONST char *dest)); +EXTERN void TclpSetInitialEncodings _ANSI_ARGS_((void)); +EXTERN void TclpSetVariables _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN VOID * TclpSysAlloc _ANSI_ARGS_((long size, int isBin)); +EXTERN void TclpSysFree _ANSI_ARGS_((VOID *ptr)); +EXTERN VOID * TclpSysRealloc _ANSI_ARGS_((VOID *cp, unsigned int size)); -#endif -EXTERN int TclParseBraces _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char **termPtr, ParseValue *pvPtr)); -EXTERN int TclParseNestedCmd _ANSI_ARGS_((Tcl_Interp *interp, - char *string, int flags, char **termPtr, - ParseValue *pvPtr)); -EXTERN int TclParseQuotes _ANSI_ARGS_((Tcl_Interp *interp, - char *string, int termChar, int flags, - char **termPtr, ParseValue *pvPtr)); -EXTERN void TclPlatformExit _ANSI_ARGS_((int status)); -EXTERN void TclPlatformInit _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN void TclpUnloadFile _ANSI_ARGS_((ClientData clientData)); EXTERN char * TclPrecTraceProc _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags)); EXTERN int TclPreventAliasLoop _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Interp *cmdInterp, Tcl_Command cmd)); -EXTERN void TclPrintByteCodeObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr)); + Tcl_Interp *cmdInterp, Tcl_Command cmd)); +EXTERN void TclProcCleanupProc _ANSI_ARGS_((Proc *procPtr)); +EXTERN int TclProcCompileProc _ANSI_ARGS_((Tcl_Interp *interp, + Proc *procPtr, Tcl_Obj *bodyPtr, Namespace *nsPtr, + CONST char *description, CONST char *procName)); +EXTERN void TclProcDeleteProc _ANSI_ARGS_((ClientData clientData)); +EXTERN int TclProcInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int TclpThreadCreate _ANSI_ARGS_((Tcl_ThreadId *idPtr, + Tcl_ThreadCreateProc proc, ClientData clientData)); +EXTERN VOID * TclpThreadDataKeyGet _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpThreadDataKeyInit _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpThreadDataKeySet _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr, VOID *data)); +EXTERN void TclpThreadExit _ANSI_ARGS_((int status)); +EXTERN void TclRememberCondition _ANSI_ARGS_((Tcl_Condition *mutex)); +EXTERN void TclRememberDataKey _ANSI_ARGS_((Tcl_ThreadDataKey *mutex)); +EXTERN void TclRememberMutex _ANSI_ARGS_((Tcl_Mutex *mutex)); EXTERN int TclRenameCommand _ANSI_ARGS_((Tcl_Interp *interp, char *oldName, char *newName)) ; EXTERN void TclResetShadowedCmdRefs _ANSI_ARGS_(( Tcl_Interp *interp, Command *newCmdPtr)); EXTERN int TclServiceIdle _ANSI_ARGS_((void)); EXTERN Tcl_Obj * TclSetElementOfIndexedArray _ANSI_ARGS_(( - Tcl_Interp *interp, int localIndex, + Tcl_Interp *interp, int localIndex, Tcl_Obj *elemPtr, Tcl_Obj *objPtr, int leaveErrorMsg)); +EXTERN void TclSetLibraryPath _ANSI_ARGS_((Tcl_Obj *pathPtr)); EXTERN Tcl_Obj * TclSetIndexedScalar _ANSI_ARGS_((Tcl_Interp *interp, int localIndex, Tcl_Obj *objPtr, int leaveErrorMsg)); +EXTERN char * TclSetPreInitScript _ANSI_ARGS_((char *string)); EXTERN void TclSetupEnv _ANSI_ARGS_((Tcl_Interp *interp)); EXTERN int TclSockGetPort _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *proto, int *portPtr)); + char *string, char *proto, int *portPtr)); EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock, - int size)); + int size)); +EXTERN int TclStat _ANSI_ARGS_((CONST char *path, + TclStat_ *buf)); +EXTERN int TclStatDeleteProc _ANSI_ARGS_((TclStatProc_ *proc)); +EXTERN int TclStatInsertProc _ANSI_ARGS_((TclStatProc_ *proc)); EXTERN void TclTeardownNamespace _ANSI_ARGS_((Namespace *nsPtr)); EXTERN int TclTestChannelCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv)); EXTERN int TclTestChannelEventCmd _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - int argc, char **argv)); + ClientData clientData, Tcl_Interp *interp, + int argc, char **argv)); +EXTERN void TclTransferResult _ANSI_ARGS_((Tcl_Interp *sourceInterp, + int result, Tcl_Interp *targetInterp)); EXTERN int TclUpdateReturnInfo _ANSI_ARGS_((Interp *iPtr)); -EXTERN char * TclWordEnd _ANSI_ARGS_((char *start, char *lastChar, - int nested, int *semiPtr)); /* *---------------------------------------------------------------- * Command procedures in the generic core: *---------------------------------------------------------------- @@ -1494,12 +1836,12 @@ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_ArrayObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_BinaryObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_BreakCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_BreakObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_CaseObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_CatchObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_CdObjCmd _ANSI_ARGS_((ClientData clientData, @@ -1508,54 +1850,54 @@ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_CloseObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_ConcatObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_ContinueCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_ContinueObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_EncodingObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_EofObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_ErrorObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_EvalObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_ExecCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_ExecObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_ExitObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_ExprObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_FblockedObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_FconfigureCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_FconfigureObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_FcopyObjCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_FileObjCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_FileEventCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_FileEventObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_FlushObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_ForCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_ForObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_ForeachObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_FormatObjCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_GetsObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_GlobalObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_GlobCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tcl_HistoryCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tcl_IfCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tcl_IncrCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_GlobObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_IfObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_IncrObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_InfoObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_InterpObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_JoinObjCmd _ANSI_ARGS_((ClientData clientData, @@ -1568,12 +1910,12 @@ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_LlengthObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_ListObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_LoadCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_LoadObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_LrangeObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_LreplaceObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_LsearchObjCmd _ANSI_ARGS_((ClientData clientData, @@ -1580,85 +1922,85 @@ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_LsortObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_NamespaceObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_OpenCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tcl_PackageCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_OpenObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PackageObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_PidObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_ProcObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_PutsObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_PwdCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_PwdObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_ReadObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_RegexpCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tcl_RegsubCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_RegexpObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_RegsubObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_RenameObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_ReturnObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_ScanCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tcl_SeekCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tcl_SetCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_ScanObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SeekObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SetObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_SplitObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_SocketCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_SocketObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_SourceObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_StringObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_SubstCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_SubstObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_SwitchObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_TellCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_TellObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_TimeObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_TraceCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_TraceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_UnsetObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_UpdateCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_UpdateObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_UplevelObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_UpvarObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_VariableObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_VwaitCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tcl_WhileCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_VwaitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_WhileObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); /* *---------------------------------------------------------------- * Command procedures found only in the Mac version of the core: *---------------------------------------------------------------- */ #ifdef MAC_TCL -EXTERN int Tcl_EchoCmd _ANSI_ARGS_((ClientData clientData, +EXTERN int Tcl_EchoCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tcl_LsCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tcl_BeepObjCmd _ANSI_ARGS_((ClientData clientData, +EXTERN int Tcl_LsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_BeepObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tcl_MacSourceObjCmd _ANSI_ARGS_((ClientData clientData, +EXTERN int Tcl_MacSourceObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); EXTERN int Tcl_ResourceObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); #endif @@ -1667,39 +2009,29 @@ * Compilation procedures for commands in the generic core: *---------------------------------------------------------------- */ EXTERN int TclCompileBreakCmd _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int compileFlags, - struct CompileEnv *compileEnvPtr)); + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); EXTERN int TclCompileCatchCmd _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int compileFlags, - struct CompileEnv *compileEnvPtr)); + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); EXTERN int TclCompileContinueCmd _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int compileFlags, - struct CompileEnv *compileEnvPtr)); + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); EXTERN int TclCompileExprCmd _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int compileFlags, - struct CompileEnv *compileEnvPtr)); + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); EXTERN int TclCompileForCmd _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int compileFlags, - struct CompileEnv *compileEnvPtr)); + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); EXTERN int TclCompileForeachCmd _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int compileFlags, - struct CompileEnv *compileEnvPtr)); + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); EXTERN int TclCompileIfCmd _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int compileFlags, - struct CompileEnv *compileEnvPtr)); + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); EXTERN int TclCompileIncrCmd _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int compileFlags, - struct CompileEnv *compileEnvPtr)); + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); EXTERN int TclCompileSetCmd _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int compileFlags, - struct CompileEnv *compileEnvPtr)); + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); EXTERN int TclCompileWhileCmd _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *lastChar, int compileFlags, - struct CompileEnv *compileEnvPtr)); + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); /* *---------------------------------------------------------------- * Macros used by the Tcl core to create and release Tcl objects. * TclNewObj(objPtr) creates a new object denoting an empty string. @@ -1727,41 +2059,51 @@ # define TclIncrObjsFreed() #endif /* TCL_COMPILE_STATS */ #ifdef TCL_MEM_DEBUG # define TclNewObj(objPtr) \ - (objPtr) = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), __FILE__, __LINE__); \ + (objPtr) = (Tcl_Obj *) \ + Tcl_DbCkalloc(sizeof(Tcl_Obj), __FILE__, __LINE__); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = tclEmptyStringRep; \ (objPtr)->length = 0; \ (objPtr)->typePtr = NULL; \ TclIncrObjsAllocated() + # define TclDbNewObj(objPtr, file, line) \ (objPtr) = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = tclEmptyStringRep; \ (objPtr)->length = 0; \ (objPtr)->typePtr = NULL; \ TclIncrObjsAllocated() + # define TclDecrRefCount(objPtr) \ if (--(objPtr)->refCount <= 0) { \ - if ((objPtr)->refCount < -1) \ - panic("Reference count for %lx was negative: %s line %d", \ + if ((objPtr)->refCount < -1) \ + panic("Reference count for %lx was negative: %s line %d", \ (objPtr), __FILE__, __LINE__); \ - if (((objPtr)->bytes != NULL) \ - && ((objPtr)->bytes != tclEmptyStringRep)) { \ + if (((objPtr)->bytes != NULL) \ + && ((objPtr)->bytes != tclEmptyStringRep)) { \ ckfree((char *) (objPtr)->bytes); \ - } \ - if (((objPtr)->typePtr != NULL) \ - && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \ + } \ + if (((objPtr)->typePtr != NULL) \ + && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \ (objPtr)->typePtr->freeIntRepProc(objPtr); \ - } \ - ckfree((char *) (objPtr)); \ - TclIncrObjsFreed(); \ + } \ + ckfree((char *) (objPtr)); \ + TclIncrObjsFreed(); \ } + #else /* not TCL_MEM_DEBUG */ + +#ifdef TCL_THREADS +extern Tcl_Mutex tclObjMutex; +#endif + # define TclNewObj(objPtr) \ + Tcl_MutexLock(&tclObjMutex); \ if (tclFreeObjList == NULL) { \ TclAllocateFreeObjects(); \ } \ (objPtr) = tclFreeObjList; \ tclFreeObjList = (Tcl_Obj *) \ @@ -1768,24 +2110,28 @@ tclFreeObjList->internalRep.otherValuePtr; \ (objPtr)->refCount = 0; \ (objPtr)->bytes = tclEmptyStringRep; \ (objPtr)->length = 0; \ (objPtr)->typePtr = NULL; \ - TclIncrObjsAllocated() + TclIncrObjsAllocated(); \ + Tcl_MutexUnlock(&tclObjMutex) + # define TclDecrRefCount(objPtr) \ if (--(objPtr)->refCount <= 0) { \ - if (((objPtr)->bytes != NULL) \ - && ((objPtr)->bytes != tclEmptyStringRep)) { \ + if (((objPtr)->bytes != NULL) \ + && ((objPtr)->bytes != tclEmptyStringRep)) { \ ckfree((char *) (objPtr)->bytes); \ - } \ - if (((objPtr)->typePtr != NULL) \ - && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \ + } \ + if (((objPtr)->typePtr != NULL) \ + && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \ (objPtr)->typePtr->freeIntRepProc(objPtr); \ - } \ - (objPtr)->internalRep.otherValuePtr = (VOID *) tclFreeObjList; \ - tclFreeObjList = (objPtr); \ - TclIncrObjsFreed(); \ + } \ + Tcl_MutexLock(&tclObjMutex); \ + (objPtr)->internalRep.otherValuePtr = (VOID *) tclFreeObjList; \ + tclFreeObjList = (objPtr); \ + TclIncrObjsFreed(); \ + Tcl_MutexUnlock(&tclObjMutex); \ } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------- @@ -1801,123 +2147,38 @@ *---------------------------------------------------------------- */ #define TclInitStringRep(objPtr, bytePtr, len) \ if ((len) == 0) { \ - (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->bytes = tclEmptyStringRep; \ (objPtr)->length = 0; \ } else { \ (objPtr)->bytes = (char *) ckalloc((unsigned) ((len) + 1)); \ memcpy((VOID *) (objPtr)->bytes, (VOID *) (bytePtr), \ - (unsigned) (len)); \ + (unsigned) (len)); \ (objPtr)->bytes[len] = '\0'; \ (objPtr)->length = (len); \ } /* *---------------------------------------------------------------- * Macro used by the Tcl core to get the string representation's - * byte array pointer and length from a Tcl_Obj. This is an inline - * version of Tcl_GetStringFromObj(). "lengthPtr" must be the - * address of an integer variable or NULL; If non-NULL, that variable - * will be set to the string rep's length. The macro's expression - * result is the string rep's byte pointer which might be NULL. - * Note that the bytes referenced by this pointer must not be modified - * by the caller. The ANSI C "prototype" for this macro is: - * - * EXTERN char * TclGetStringFromObj _ANSI_ARGS_((Tcl_Obj *objPtr, - * int *lengthPtr)); - *---------------------------------------------------------------- - */ - -#define TclGetStringFromObj(objPtr, lengthPtr) \ - ((objPtr)->bytes? \ - ((lengthPtr)? \ - ((*(lengthPtr) = (objPtr)->length), (objPtr)->bytes) : \ - (objPtr)->bytes) : \ - Tcl_GetStringFromObj((objPtr), (lengthPtr))) - -/* - *---------------------------------------------------------------- - * Macro used by the Tcl core to reset an interpreter's Tcl object - * result to an unshared empty string object with ref count one. - * This does not clear any error information for the interpreter. - * The ANSI C "prototype" for this macro is: - * - * EXTERN void TclResetObjResult _ANSI_ARGS_((Tcl_Interp *interp)); - *--------------------------------------------------------------- - */ - -#define TclResetObjResult(interp) \ - { \ - register Tcl_Obj *objResultPtr = ((Interp *) interp)->objResultPtr; \ - if (Tcl_IsShared(objResultPtr)) { \ - TclDecrRefCount(objResultPtr); \ - TclNewObj(objResultPtr); \ - Tcl_IncrRefCount(objResultPtr); \ - ((Interp *) interp)->objResultPtr = objResultPtr; \ - } else { \ - if ((objResultPtr->bytes != NULL) \ - && (objResultPtr->bytes != tclEmptyStringRep)) { \ - ckfree((char *) objResultPtr->bytes); \ - } \ - objResultPtr->bytes = tclEmptyStringRep; \ - objResultPtr->length = 0; \ - if ((objResultPtr->typePtr != NULL) \ - && (objResultPtr->typePtr->freeIntRepProc != NULL)) { \ - objResultPtr->typePtr->freeIntRepProc(objResultPtr); \ - } \ - objResultPtr->typePtr = (Tcl_ObjType *) NULL; \ - } \ - } - -/* - *---------------------------------------------------------------- - * Procedures used in conjunction with Tcl namespaces. They are - * defined here instead of in tcl.h since they are not stable yet. - *---------------------------------------------------------------- - */ - -EXTERN int Tcl_AppendExportList _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Namespace *nsPtr, - Tcl_Obj *objPtr)); -EXTERN Tcl_Namespace * Tcl_CreateNamespace _ANSI_ARGS_((Tcl_Interp *interp, - char *name, ClientData clientData, - Tcl_NamespaceDeleteProc *deleteProc)); -EXTERN void Tcl_DeleteNamespace _ANSI_ARGS_(( - Tcl_Namespace *nsPtr)); -EXTERN int Tcl_Export _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Namespace *nsPtr, char *pattern, - int resetListFirst)); -EXTERN Tcl_Command Tcl_FindCommand _ANSI_ARGS_((Tcl_Interp *interp, - char *name, Tcl_Namespace *contextNsPtr, - int flags)); -EXTERN Tcl_Namespace * Tcl_FindNamespace _ANSI_ARGS_((Tcl_Interp *interp, - char *name, Tcl_Namespace *contextNsPtr, - int flags)); -EXTERN Tcl_Var Tcl_FindNamespaceVar _ANSI_ARGS_(( - Tcl_Interp *interp, char *name, - Tcl_Namespace *contextNsPtr, int flags)); -EXTERN int Tcl_ForgetImport _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Namespace *nsPtr, char *pattern)); -EXTERN Tcl_Command Tcl_GetCommandFromObj _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Obj *objPtr)); -EXTERN void Tcl_GetCommandFullName _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Command command, - Tcl_Obj *objPtr)); -EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace _ANSI_ARGS_(( - Tcl_Interp *interp)); -EXTERN Tcl_Namespace * Tcl_GetGlobalNamespace _ANSI_ARGS_(( - Tcl_Interp *interp)); -EXTERN void Tcl_GetVariableFullName _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Var variable, - Tcl_Obj *objPtr)); -EXTERN int Tcl_Import _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Namespace *nsPtr, char *pattern, - int allowOverwrite)); -EXTERN void Tcl_PopCallFrame _ANSI_ARGS_((Tcl_Interp* interp)); -EXTERN int Tcl_PushCallFrame _ANSI_ARGS_((Tcl_Interp* interp, - Tcl_CallFrame *framePtr, Tcl_Namespace *nsPtr, - int isProcCallFrame)); + * 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: + * + * EXTERN char * TclGetString _ANSI_ARGS_((Tcl_Obj *objPtr)); + *---------------------------------------------------------------- + */ + +#define TclGetString(objPtr) \ + ((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString((objPtr))) + +#include "tclIntDecls.h" + +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT #endif /* _TCLINT */ ADDED generic/tclIntDecls.h Index: generic/tclIntDecls.h ================================================================== --- /dev/null +++ generic/tclIntDecls.h @@ -0,0 +1,1134 @@ +/* + * 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. + * + * RCS: @(#) $Id: tclIntDecls.h,v 1.3.2.7 1999/04/06 03:13:17 redman Exp $ + */ + +#ifndef _TCLINTDECLS +#define _TCLINTDECLS + +/* + * 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. */ + +/* + * Exported function declarations: + */ + +/* 0 */ +EXTERN int TclAccess _ANSI_ARGS_((CONST char * path, int mode)); +/* 1 */ +EXTERN int TclAccessDeleteProc _ANSI_ARGS_(( + TclAccessProc_ * proc)); +/* 2 */ +EXTERN int TclAccessInsertProc _ANSI_ARGS_(( + TclAccessProc_ * proc)); +/* 3 */ +EXTERN void TclAllocateFreeObjects _ANSI_ARGS_((void)); +/* Slot 4 is reserved */ +/* 5 */ +EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp * interp, + int numPids, Tcl_Pid * pidPtr, + Tcl_Channel errorChan)); +/* 6 */ +EXTERN void TclCleanupCommand _ANSI_ARGS_((Command * cmdPtr)); +/* 7 */ +EXTERN int TclCopyAndCollapse _ANSI_ARGS_((int count, + CONST char * src, char * dst)); +/* 8 */ +EXTERN int TclCopyChannel _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Channel inChan, Tcl_Channel outChan, + int toRead, Tcl_Obj * cmdPtr)); +/* 9 */ +EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv, + Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, + TclFile * outPipePtr, TclFile * errFilePtr)); +/* 10 */ +EXTERN int TclCreateProc _ANSI_ARGS_((Tcl_Interp * interp, + Namespace * nsPtr, char * procName, + Tcl_Obj * argsPtr, Tcl_Obj * bodyPtr, + Proc ** procPtrPtr)); +/* 11 */ +EXTERN void TclDeleteCompiledLocalVars _ANSI_ARGS_(( + Interp * iPtr, CallFrame * framePtr)); +/* 12 */ +EXTERN void TclDeleteVars _ANSI_ARGS_((Interp * iPtr, + Tcl_HashTable * tablePtr)); +/* 13 */ +EXTERN int TclDoGlob _ANSI_ARGS_((Tcl_Interp * interp, + char * separators, Tcl_DString * headPtr, + char * tail)); +/* 14 */ +EXTERN void TclDumpMemoryInfo _ANSI_ARGS_((FILE * outFile)); +/* Slot 15 is reserved */ +/* 16 */ +EXTERN void TclExprFloatError _ANSI_ARGS_((Tcl_Interp * interp, + double value)); +/* 17 */ +EXTERN int TclFileAttrsCmd _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[])); +/* 18 */ +EXTERN int TclFileCopyCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 19 */ +EXTERN int TclFileDeleteCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 20 */ +EXTERN int TclFileMakeDirsCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 21 */ +EXTERN int TclFileRenameCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 22 */ +EXTERN int TclFindElement _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * listStr, int listLength, + CONST char ** elementPtr, + CONST char ** nextPtr, int * sizePtr, + int * bracePtr)); +/* 23 */ +EXTERN Proc * TclFindProc _ANSI_ARGS_((Interp * iPtr, + char * procName)); +/* 24 */ +EXTERN int TclFormatInt _ANSI_ARGS_((char * buffer, long n)); +/* 25 */ +EXTERN void TclFreePackageInfo _ANSI_ARGS_((Interp * iPtr)); +/* Slot 26 is reserved */ +/* 27 */ +EXTERN int TclGetDate _ANSI_ARGS_((char * p, unsigned long now, + long zone, unsigned long * timePtr)); +/* 28 */ +EXTERN Tcl_Channel TclpGetDefaultStdChannel _ANSI_ARGS_((int type)); +/* 29 */ +EXTERN Tcl_Obj * TclGetElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + Tcl_Obj * elemPtr, int leaveErrorMsg)); +/* Slot 30 is reserved */ +/* 31 */ +EXTERN char * TclGetExtension _ANSI_ARGS_((char * name)); +/* 32 */ +EXTERN int TclGetFrame _ANSI_ARGS_((Tcl_Interp * interp, + char * str, CallFrame ** framePtrPtr)); +/* 33 */ +EXTERN TclCmdProcType TclGetInterpProc _ANSI_ARGS_((void)); +/* 34 */ +EXTERN int TclGetIntForIndex _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, int endValue, + int * indexPtr)); +/* 35 */ +EXTERN Tcl_Obj * TclGetIndexedScalar _ANSI_ARGS_((Tcl_Interp * interp, + int localIndex, int leaveErrorMsg)); +/* 36 */ +EXTERN int TclGetLong _ANSI_ARGS_((Tcl_Interp * interp, + char * str, long * longPtr)); +/* 37 */ +EXTERN int TclGetLoadedPackages _ANSI_ARGS_(( + Tcl_Interp * interp, char * targetName)); +/* 38 */ +EXTERN int TclGetNamespaceForQualName _ANSI_ARGS_(( + Tcl_Interp * interp, char * qualName, + Namespace * cxtNsPtr, int flags, + Namespace ** nsPtrPtr, + Namespace ** altNsPtrPtr, + Namespace ** actualCxtPtrPtr, + char ** simpleNamePtr)); +/* 39 */ +EXTERN TclObjCmdProcType TclGetObjInterpProc _ANSI_ARGS_((void)); +/* 40 */ +EXTERN int TclGetOpenMode _ANSI_ARGS_((Tcl_Interp * interp, + char * str, int * seekFlagPtr)); +/* 41 */ +EXTERN Tcl_Command TclGetOriginalCommand _ANSI_ARGS_(( + Tcl_Command command)); +/* 42 */ +EXTERN char * TclpGetUserHome _ANSI_ARGS_((CONST char * name, + Tcl_DString * bufferPtr)); +/* 43 */ +EXTERN int TclGlobalInvoke _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv, int flags)); +/* 44 */ +EXTERN int TclGuessPackageName _ANSI_ARGS_((char * fileName, + Tcl_DString * bufPtr)); +/* 45 */ +EXTERN int TclHideUnsafeCommands _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 46 */ +EXTERN int TclInExit _ANSI_ARGS_((void)); +/* 47 */ +EXTERN Tcl_Obj * TclIncrElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + Tcl_Obj * elemPtr, long incrAmount)); +/* 48 */ +EXTERN Tcl_Obj * TclIncrIndexedScalar _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + long incrAmount)); +/* 49 */ +EXTERN Tcl_Obj * TclIncrVar2 _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, + long incrAmount, int part1NotParsed)); +/* 50 */ +EXTERN void TclInitCompiledLocals _ANSI_ARGS_(( + Tcl_Interp * interp, CallFrame * framePtr, + Namespace * nsPtr)); +/* 51 */ +EXTERN int TclInterpInit _ANSI_ARGS_((Tcl_Interp * interp)); +/* 52 */ +EXTERN int TclInvoke _ANSI_ARGS_((Tcl_Interp * interp, int argc, + char ** argv, int flags)); +/* 53 */ +EXTERN int TclInvokeObjectCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp * interp, + int argc, char ** argv)); +/* 54 */ +EXTERN int TclInvokeStringCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[])); +/* 55 */ +EXTERN Proc * TclIsProc _ANSI_ARGS_((Command * cmdPtr)); +/* Slot 56 is reserved */ +/* Slot 57 is reserved */ +/* 58 */ +EXTERN Var * TclLookupVar _ANSI_ARGS_((Tcl_Interp * interp, + char * part1, char * part2, int flags, + char * msg, int createPart1, int createPart2, + Var ** arrayPtrPtr)); +/* 59 */ +EXTERN int TclpMatchFiles _ANSI_ARGS_((Tcl_Interp * interp, + char * separators, Tcl_DString * dirPtr, + char * pattern, char * tail)); +/* 60 */ +EXTERN int TclNeedSpace _ANSI_ARGS_((char * start, char * end)); +/* 61 */ +EXTERN Tcl_Obj * TclNewProcBodyObj _ANSI_ARGS_((Proc * procPtr)); +/* 62 */ +EXTERN int TclObjCommandComplete _ANSI_ARGS_((Tcl_Obj * cmdPtr)); +/* 63 */ +EXTERN int TclObjInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int objc, + Tcl_Obj *CONST objv[])); +/* 64 */ +EXTERN int TclObjInvoke _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +/* 65 */ +EXTERN int TclObjInvokeGlobal _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +/* 66 */ +EXTERN int TclOpenFileChannelDeleteProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ * proc)); +/* 67 */ +EXTERN int TclOpenFileChannelInsertProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ * proc)); +/* 68 */ +EXTERN int TclpAccess _ANSI_ARGS_((CONST char * path, int mode)); +/* 69 */ +EXTERN char * TclpAlloc _ANSI_ARGS_((unsigned int size)); +/* 70 */ +EXTERN int TclpCopyFile _ANSI_ARGS_((CONST char * source, + CONST char * dest)); +/* 71 */ +EXTERN int TclpCopyDirectory _ANSI_ARGS_((CONST char * source, + CONST char * dest, Tcl_DString * errorPtr)); +/* 72 */ +EXTERN int TclpCreateDirectory _ANSI_ARGS_((CONST char * path)); +/* 73 */ +EXTERN int TclpDeleteFile _ANSI_ARGS_((CONST char * path)); +/* 74 */ +EXTERN void TclpFree _ANSI_ARGS_((char * ptr)); +/* 75 */ +EXTERN unsigned long TclpGetClicks _ANSI_ARGS_((void)); +/* 76 */ +EXTERN unsigned long TclpGetSeconds _ANSI_ARGS_((void)); +/* 77 */ +EXTERN void TclpGetTime _ANSI_ARGS_((Tcl_Time * time)); +/* 78 */ +EXTERN int TclpGetTimeZone _ANSI_ARGS_((unsigned long time)); +/* 79 */ +EXTERN int TclpListVolumes _ANSI_ARGS_((Tcl_Interp * interp)); +/* 80 */ +EXTERN Tcl_Channel TclpOpenFileChannel _ANSI_ARGS_((Tcl_Interp * interp, + char * fileName, char * modeString, + int permissions)); +/* 81 */ +EXTERN char * TclpRealloc _ANSI_ARGS_((char * ptr, + unsigned int size)); +/* 82 */ +EXTERN int TclpRemoveDirectory _ANSI_ARGS_((CONST char * path, + int recursive, Tcl_DString * errorPtr)); +/* 83 */ +EXTERN int TclpRenameFile _ANSI_ARGS_((CONST char * source, + CONST char * dest)); +/* Slot 84 is reserved */ +/* Slot 85 is reserved */ +/* Slot 86 is reserved */ +/* Slot 87 is reserved */ +/* 88 */ +EXTERN char * TclPrecTraceProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, char * name1, + char * name2, int flags)); +/* 89 */ +EXTERN int TclPreventAliasLoop _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Interp * cmdInterp, Tcl_Command cmd)); +/* Slot 90 is reserved */ +/* 91 */ +EXTERN void TclProcCleanupProc _ANSI_ARGS_((Proc * procPtr)); +/* 92 */ +EXTERN int TclProcCompileProc _ANSI_ARGS_((Tcl_Interp * interp, + Proc * procPtr, Tcl_Obj * bodyPtr, + Namespace * nsPtr, CONST char * description, + CONST char * procName)); +/* 93 */ +EXTERN void TclProcDeleteProc _ANSI_ARGS_((ClientData clientData)); +/* 94 */ +EXTERN int TclProcInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int argc, char ** argv)); +/* 95 */ +EXTERN int TclpStat _ANSI_ARGS_((CONST char * path, + struct stat * buf)); +/* 96 */ +EXTERN int TclRenameCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * oldName, char * newName)); +/* 97 */ +EXTERN void TclResetShadowedCmdRefs _ANSI_ARGS_(( + Tcl_Interp * interp, Command * newCmdPtr)); +/* 98 */ +EXTERN int TclServiceIdle _ANSI_ARGS_((void)); +/* 99 */ +EXTERN Tcl_Obj * TclSetElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + Tcl_Obj * elemPtr, Tcl_Obj * objPtr, + int leaveErrorMsg)); +/* 100 */ +EXTERN Tcl_Obj * TclSetIndexedScalar _ANSI_ARGS_((Tcl_Interp * interp, + int localIndex, Tcl_Obj * objPtr, + int leaveErrorMsg)); +/* Slot 101 is reserved */ +/* 102 */ +EXTERN void TclSetupEnv _ANSI_ARGS_((Tcl_Interp * interp)); +/* 103 */ +EXTERN int TclSockGetPort _ANSI_ARGS_((Tcl_Interp * interp, + char * str, char * proto, int * portPtr)); +/* 104 */ +EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock, + int size)); +/* 105 */ +EXTERN int TclStat _ANSI_ARGS_((CONST char * path, + TclStat_ * buf)); +/* 106 */ +EXTERN int TclStatDeleteProc _ANSI_ARGS_((TclStatProc_ * proc)); +/* 107 */ +EXTERN int TclStatInsertProc _ANSI_ARGS_((TclStatProc_ * proc)); +/* 108 */ +EXTERN void TclTeardownNamespace _ANSI_ARGS_((Namespace * nsPtr)); +/* 109 */ +EXTERN int TclUpdateReturnInfo _ANSI_ARGS_((Interp * iPtr)); +/* Slot 110 is reserved */ +/* 111 */ +EXTERN void Tcl_AddInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, char * name, + Tcl_ResolveCmdProc * cmdProc, + Tcl_ResolveVarProc * varProc, + Tcl_ResolveCompiledVarProc * compiledVarProc)); +/* 112 */ +EXTERN int Tcl_AppendExportList _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Namespace * nsPtr, + Tcl_Obj * objPtr)); +/* 113 */ +EXTERN Tcl_Namespace * Tcl_CreateNamespace _ANSI_ARGS_((Tcl_Interp * interp, + char * name, ClientData clientData, + Tcl_NamespaceDeleteProc * deleteProc)); +/* 114 */ +EXTERN void Tcl_DeleteNamespace _ANSI_ARGS_(( + Tcl_Namespace * nsPtr)); +/* 115 */ +EXTERN int Tcl_Export _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, char * pattern, + int resetListFirst)); +/* 116 */ +EXTERN Tcl_Command Tcl_FindCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * name, Tcl_Namespace * contextNsPtr, + int flags)); +/* 117 */ +EXTERN Tcl_Namespace * Tcl_FindNamespace _ANSI_ARGS_((Tcl_Interp * interp, + char * name, Tcl_Namespace * contextNsPtr, + int flags)); +/* 118 */ +EXTERN int Tcl_GetInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, char * name, + Tcl_ResolverInfo * resInfo)); +/* 119 */ +EXTERN int Tcl_GetNamespaceResolvers _ANSI_ARGS_(( + Tcl_Namespace * namespacePtr, + Tcl_ResolverInfo * resInfo)); +/* 120 */ +EXTERN Tcl_Var Tcl_FindNamespaceVar _ANSI_ARGS_(( + Tcl_Interp * interp, char * name, + Tcl_Namespace * contextNsPtr, int flags)); +/* 121 */ +EXTERN int Tcl_ForgetImport _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, char * pattern)); +/* 122 */ +EXTERN Tcl_Command Tcl_GetCommandFromObj _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr)); +/* 123 */ +EXTERN void Tcl_GetCommandFullName _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Command command, + Tcl_Obj * objPtr)); +/* 124 */ +EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 125 */ +EXTERN Tcl_Namespace * Tcl_GetGlobalNamespace _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 126 */ +EXTERN void Tcl_GetVariableFullName _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Var variable, + Tcl_Obj * objPtr)); +/* 127 */ +EXTERN int Tcl_Import _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, char * pattern, + int allowOverwrite)); +/* 128 */ +EXTERN void Tcl_PopCallFrame _ANSI_ARGS_((Tcl_Interp* interp)); +/* 129 */ +EXTERN int Tcl_PushCallFrame _ANSI_ARGS_((Tcl_Interp* interp, + Tcl_CallFrame * framePtr, + Tcl_Namespace * nsPtr, int isProcCallFrame)); +/* 130 */ +EXTERN int Tcl_RemoveInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, char * name)); +/* 131 */ +EXTERN void Tcl_SetNamespaceResolvers _ANSI_ARGS_(( + Tcl_Namespace * namespacePtr, + Tcl_ResolveCmdProc * cmdProc, + Tcl_ResolveVarProc * varProc, + Tcl_ResolveCompiledVarProc * compiledVarProc)); +/* 132 */ +EXTERN int TclpHasSockets _ANSI_ARGS_((Tcl_Interp * interp)); +/* 133 */ +EXTERN struct tm * TclpGetDate _ANSI_ARGS_((TclpTime_t time, int useGMT)); +/* 134 */ +EXTERN size_t TclpStrftime _ANSI_ARGS_((char * s, size_t maxsize, + CONST char * format, CONST struct tm * t)); +/* 135 */ +EXTERN int TclpCheckStackSpace _ANSI_ARGS_((void)); +/* Slot 136 is reserved */ +/* 137 */ +EXTERN int TclpChdir _ANSI_ARGS_((CONST char * dirName)); +/* 138 */ +EXTERN char * TclGetEnv _ANSI_ARGS_((CONST char * name, + Tcl_DString * valuePtr)); +/* 139 */ +EXTERN int TclpLoadFile _ANSI_ARGS_((Tcl_Interp * interp, + char * fileName, char * sym1, char * sym2, + Tcl_PackageInitProc ** proc1Ptr, + Tcl_PackageInitProc ** proc2Ptr, + ClientData * clientDataPtr)); +/* 140 */ +EXTERN int TclLooksLikeInt _ANSI_ARGS_((char * bytes, + int length)); +/* 141 */ +EXTERN char * TclpGetCwd _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_DString * cwdPtr)); + +typedef struct TclIntStubs { + int magic; + struct TclIntStubHooks *hooks; + + int (*tclAccess) _ANSI_ARGS_((CONST char * path, int mode)); /* 0 */ + int (*tclAccessDeleteProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 1 */ + int (*tclAccessInsertProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 2 */ + void (*tclAllocateFreeObjects) _ANSI_ARGS_((void)); /* 3 */ + void *reserved4; + int (*tclCleanupChildren) _ANSI_ARGS_((Tcl_Interp * interp, int numPids, Tcl_Pid * pidPtr, Tcl_Channel errorChan)); /* 5 */ + void (*tclCleanupCommand) _ANSI_ARGS_((Command * cmdPtr)); /* 6 */ + int (*tclCopyAndCollapse) _ANSI_ARGS_((int count, CONST char * src, char * dst)); /* 7 */ + int (*tclCopyChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj * cmdPtr)); /* 8 */ + int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, TclFile * outPipePtr, TclFile * errFilePtr)); /* 9 */ + int (*tclCreateProc) _ANSI_ARGS_((Tcl_Interp * interp, Namespace * nsPtr, char * procName, Tcl_Obj * argsPtr, Tcl_Obj * bodyPtr, Proc ** procPtrPtr)); /* 10 */ + void (*tclDeleteCompiledLocalVars) _ANSI_ARGS_((Interp * iPtr, CallFrame * framePtr)); /* 11 */ + void (*tclDeleteVars) _ANSI_ARGS_((Interp * iPtr, Tcl_HashTable * tablePtr)); /* 12 */ + int (*tclDoGlob) _ANSI_ARGS_((Tcl_Interp * interp, char * separators, Tcl_DString * headPtr, char * tail)); /* 13 */ + void (*tclDumpMemoryInfo) _ANSI_ARGS_((FILE * outFile)); /* 14 */ + void *reserved15; + void (*tclExprFloatError) _ANSI_ARGS_((Tcl_Interp * interp, double value)); /* 16 */ + int (*tclFileAttrsCmd) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 17 */ + int (*tclFileCopyCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 18 */ + int (*tclFileDeleteCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 19 */ + int (*tclFileMakeDirsCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 20 */ + int (*tclFileRenameCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 21 */ + int (*tclFindElement) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * listStr, int listLength, CONST char ** elementPtr, CONST char ** nextPtr, int * sizePtr, int * bracePtr)); /* 22 */ + Proc * (*tclFindProc) _ANSI_ARGS_((Interp * iPtr, char * procName)); /* 23 */ + int (*tclFormatInt) _ANSI_ARGS_((char * buffer, long n)); /* 24 */ + void (*tclFreePackageInfo) _ANSI_ARGS_((Interp * iPtr)); /* 25 */ + void *reserved26; + int (*tclGetDate) _ANSI_ARGS_((char * p, unsigned long now, long zone, unsigned long * timePtr)); /* 27 */ + Tcl_Channel (*tclpGetDefaultStdChannel) _ANSI_ARGS_((int type)); /* 28 */ + Tcl_Obj * (*tclGetElementOfIndexedArray) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * elemPtr, int leaveErrorMsg)); /* 29 */ + void *reserved30; + char * (*tclGetExtension) _ANSI_ARGS_((char * name)); /* 31 */ + int (*tclGetFrame) _ANSI_ARGS_((Tcl_Interp * interp, char * str, CallFrame ** framePtrPtr)); /* 32 */ + TclCmdProcType (*tclGetInterpProc) _ANSI_ARGS_((void)); /* 33 */ + int (*tclGetIntForIndex) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int endValue, int * indexPtr)); /* 34 */ + Tcl_Obj * (*tclGetIndexedScalar) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, int leaveErrorMsg)); /* 35 */ + int (*tclGetLong) _ANSI_ARGS_((Tcl_Interp * interp, char * str, long * longPtr)); /* 36 */ + int (*tclGetLoadedPackages) _ANSI_ARGS_((Tcl_Interp * interp, char * targetName)); /* 37 */ + int (*tclGetNamespaceForQualName) _ANSI_ARGS_((Tcl_Interp * interp, char * qualName, Namespace * cxtNsPtr, int flags, Namespace ** nsPtrPtr, Namespace ** altNsPtrPtr, Namespace ** actualCxtPtrPtr, char ** simpleNamePtr)); /* 38 */ + TclObjCmdProcType (*tclGetObjInterpProc) _ANSI_ARGS_((void)); /* 39 */ + int (*tclGetOpenMode) _ANSI_ARGS_((Tcl_Interp * interp, char * str, int * seekFlagPtr)); /* 40 */ + Tcl_Command (*tclGetOriginalCommand) _ANSI_ARGS_((Tcl_Command command)); /* 41 */ + char * (*tclpGetUserHome) _ANSI_ARGS_((CONST char * name, Tcl_DString * bufferPtr)); /* 42 */ + int (*tclGlobalInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, int flags)); /* 43 */ + int (*tclGuessPackageName) _ANSI_ARGS_((char * fileName, Tcl_DString * bufPtr)); /* 44 */ + int (*tclHideUnsafeCommands) _ANSI_ARGS_((Tcl_Interp * interp)); /* 45 */ + int (*tclInExit) _ANSI_ARGS_((void)); /* 46 */ + Tcl_Obj * (*tclIncrElementOfIndexedArray) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * elemPtr, long incrAmount)); /* 47 */ + Tcl_Obj * (*tclIncrIndexedScalar) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, long incrAmount)); /* 48 */ + Tcl_Obj * (*tclIncrVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, long incrAmount, int part1NotParsed)); /* 49 */ + void (*tclInitCompiledLocals) _ANSI_ARGS_((Tcl_Interp * interp, CallFrame * framePtr, Namespace * nsPtr)); /* 50 */ + int (*tclInterpInit) _ANSI_ARGS_((Tcl_Interp * interp)); /* 51 */ + int (*tclInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, int flags)); /* 52 */ + int (*tclInvokeObjectCommand) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv)); /* 53 */ + int (*tclInvokeStringCommand) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 54 */ + Proc * (*tclIsProc) _ANSI_ARGS_((Command * cmdPtr)); /* 55 */ + void *reserved56; + void *reserved57; + Var * (*tclLookupVar) _ANSI_ARGS_((Tcl_Interp * interp, char * part1, char * part2, int flags, char * msg, int createPart1, int createPart2, Var ** arrayPtrPtr)); /* 58 */ + int (*tclpMatchFiles) _ANSI_ARGS_((Tcl_Interp * interp, char * separators, Tcl_DString * dirPtr, char * pattern, char * tail)); /* 59 */ + int (*tclNeedSpace) _ANSI_ARGS_((char * start, char * end)); /* 60 */ + Tcl_Obj * (*tclNewProcBodyObj) _ANSI_ARGS_((Proc * procPtr)); /* 61 */ + int (*tclObjCommandComplete) _ANSI_ARGS_((Tcl_Obj * cmdPtr)); /* 62 */ + int (*tclObjInterpProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 63 */ + int (*tclObjInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 64 */ + int (*tclObjInvokeGlobal) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 65 */ + int (*tclOpenFileChannelDeleteProc) _ANSI_ARGS_((TclOpenFileChannelProc_ * proc)); /* 66 */ + int (*tclOpenFileChannelInsertProc) _ANSI_ARGS_((TclOpenFileChannelProc_ * proc)); /* 67 */ + int (*tclpAccess) _ANSI_ARGS_((CONST char * path, int mode)); /* 68 */ + char * (*tclpAlloc) _ANSI_ARGS_((unsigned int size)); /* 69 */ + int (*tclpCopyFile) _ANSI_ARGS_((CONST char * source, CONST char * dest)); /* 70 */ + int (*tclpCopyDirectory) _ANSI_ARGS_((CONST char * source, CONST char * dest, Tcl_DString * errorPtr)); /* 71 */ + int (*tclpCreateDirectory) _ANSI_ARGS_((CONST char * path)); /* 72 */ + int (*tclpDeleteFile) _ANSI_ARGS_((CONST char * path)); /* 73 */ + void (*tclpFree) _ANSI_ARGS_((char * ptr)); /* 74 */ + unsigned long (*tclpGetClicks) _ANSI_ARGS_((void)); /* 75 */ + unsigned long (*tclpGetSeconds) _ANSI_ARGS_((void)); /* 76 */ + void (*tclpGetTime) _ANSI_ARGS_((Tcl_Time * time)); /* 77 */ + int (*tclpGetTimeZone) _ANSI_ARGS_((unsigned long time)); /* 78 */ + int (*tclpListVolumes) _ANSI_ARGS_((Tcl_Interp * interp)); /* 79 */ + Tcl_Channel (*tclpOpenFileChannel) _ANSI_ARGS_((Tcl_Interp * interp, char * fileName, char * modeString, int permissions)); /* 80 */ + char * (*tclpRealloc) _ANSI_ARGS_((char * ptr, unsigned int size)); /* 81 */ + int (*tclpRemoveDirectory) _ANSI_ARGS_((CONST char * path, int recursive, Tcl_DString * errorPtr)); /* 82 */ + int (*tclpRenameFile) _ANSI_ARGS_((CONST char * source, CONST char * dest)); /* 83 */ + void *reserved84; + void *reserved85; + void *reserved86; + void *reserved87; + char * (*tclPrecTraceProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, char * name1, char * name2, int flags)); /* 88 */ + int (*tclPreventAliasLoop) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Interp * cmdInterp, Tcl_Command cmd)); /* 89 */ + void *reserved90; + void (*tclProcCleanupProc) _ANSI_ARGS_((Proc * procPtr)); /* 91 */ + int (*tclProcCompileProc) _ANSI_ARGS_((Tcl_Interp * interp, Proc * procPtr, Tcl_Obj * bodyPtr, Namespace * nsPtr, CONST char * description, CONST char * procName)); /* 92 */ + void (*tclProcDeleteProc) _ANSI_ARGS_((ClientData clientData)); /* 93 */ + int (*tclProcInterpProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv)); /* 94 */ + int (*tclpStat) _ANSI_ARGS_((CONST char * path, struct stat * buf)); /* 95 */ + int (*tclRenameCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * oldName, char * newName)); /* 96 */ + void (*tclResetShadowedCmdRefs) _ANSI_ARGS_((Tcl_Interp * interp, Command * newCmdPtr)); /* 97 */ + int (*tclServiceIdle) _ANSI_ARGS_((void)); /* 98 */ + Tcl_Obj * (*tclSetElementOfIndexedArray) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * elemPtr, Tcl_Obj * objPtr, int leaveErrorMsg)); /* 99 */ + Tcl_Obj * (*tclSetIndexedScalar) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * objPtr, int leaveErrorMsg)); /* 100 */ + void *reserved101; + void (*tclSetupEnv) _ANSI_ARGS_((Tcl_Interp * interp)); /* 102 */ + int (*tclSockGetPort) _ANSI_ARGS_((Tcl_Interp * interp, char * str, char * proto, int * portPtr)); /* 103 */ + int (*tclSockMinimumBuffers) _ANSI_ARGS_((int sock, int size)); /* 104 */ + int (*tclStat) _ANSI_ARGS_((CONST char * path, TclStat_ * buf)); /* 105 */ + int (*tclStatDeleteProc) _ANSI_ARGS_((TclStatProc_ * proc)); /* 106 */ + int (*tclStatInsertProc) _ANSI_ARGS_((TclStatProc_ * proc)); /* 107 */ + void (*tclTeardownNamespace) _ANSI_ARGS_((Namespace * nsPtr)); /* 108 */ + int (*tclUpdateReturnInfo) _ANSI_ARGS_((Interp * iPtr)); /* 109 */ + void *reserved110; + void (*tcl_AddInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc, Tcl_ResolveCompiledVarProc * compiledVarProc)); /* 111 */ + int (*tcl_AppendExportList) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, Tcl_Obj * objPtr)); /* 112 */ + Tcl_Namespace * (*tcl_CreateNamespace) _ANSI_ARGS_((Tcl_Interp * interp, char * name, ClientData clientData, Tcl_NamespaceDeleteProc * deleteProc)); /* 113 */ + void (*tcl_DeleteNamespace) _ANSI_ARGS_((Tcl_Namespace * nsPtr)); /* 114 */ + int (*tcl_Export) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, char * pattern, int resetListFirst)); /* 115 */ + Tcl_Command (*tcl_FindCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 116 */ + Tcl_Namespace * (*tcl_FindNamespace) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 117 */ + int (*tcl_GetInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_ResolverInfo * resInfo)); /* 118 */ + int (*tcl_GetNamespaceResolvers) _ANSI_ARGS_((Tcl_Namespace * namespacePtr, Tcl_ResolverInfo * resInfo)); /* 119 */ + Tcl_Var (*tcl_FindNamespaceVar) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 120 */ + int (*tcl_ForgetImport) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, char * pattern)); /* 121 */ + Tcl_Command (*tcl_GetCommandFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 122 */ + void (*tcl_GetCommandFullName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command command, Tcl_Obj * objPtr)); /* 123 */ + Tcl_Namespace * (*tcl_GetCurrentNamespace) _ANSI_ARGS_((Tcl_Interp * interp)); /* 124 */ + Tcl_Namespace * (*tcl_GetGlobalNamespace) _ANSI_ARGS_((Tcl_Interp * interp)); /* 125 */ + void (*tcl_GetVariableFullName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Var variable, Tcl_Obj * objPtr)); /* 126 */ + int (*tcl_Import) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, char * pattern, int allowOverwrite)); /* 127 */ + void (*tcl_PopCallFrame) _ANSI_ARGS_((Tcl_Interp* interp)); /* 128 */ + int (*tcl_PushCallFrame) _ANSI_ARGS_((Tcl_Interp* interp, Tcl_CallFrame * framePtr, Tcl_Namespace * nsPtr, int isProcCallFrame)); /* 129 */ + int (*tcl_RemoveInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, char * name)); /* 130 */ + void (*tcl_SetNamespaceResolvers) _ANSI_ARGS_((Tcl_Namespace * namespacePtr, Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc, Tcl_ResolveCompiledVarProc * compiledVarProc)); /* 131 */ + int (*tclpHasSockets) _ANSI_ARGS_((Tcl_Interp * interp)); /* 132 */ + struct tm * (*tclpGetDate) _ANSI_ARGS_((TclpTime_t time, int useGMT)); /* 133 */ + size_t (*tclpStrftime) _ANSI_ARGS_((char * s, size_t maxsize, CONST char * format, CONST struct tm * t)); /* 134 */ + int (*tclpCheckStackSpace) _ANSI_ARGS_((void)); /* 135 */ + void *reserved136; + int (*tclpChdir) _ANSI_ARGS_((CONST char * dirName)); /* 137 */ + char * (*tclGetEnv) _ANSI_ARGS_((CONST char * name, Tcl_DString * valuePtr)); /* 138 */ + int (*tclpLoadFile) _ANSI_ARGS_((Tcl_Interp * interp, char * fileName, char * sym1, char * sym2, Tcl_PackageInitProc ** proc1Ptr, Tcl_PackageInitProc ** proc2Ptr, ClientData * clientDataPtr)); /* 139 */ + int (*tclLooksLikeInt) _ANSI_ARGS_((char * bytes, int length)); /* 140 */ + char * (*tclpGetCwd) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * cwdPtr)); /* 141 */ +} TclIntStubs; + +extern TclIntStubs *tclIntStubsPtr; + +#if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifndef TclAccess +#define TclAccess \ + (tclIntStubsPtr->tclAccess) /* 0 */ +#endif +#ifndef TclAccessDeleteProc +#define TclAccessDeleteProc \ + (tclIntStubsPtr->tclAccessDeleteProc) /* 1 */ +#endif +#ifndef TclAccessInsertProc +#define TclAccessInsertProc \ + (tclIntStubsPtr->tclAccessInsertProc) /* 2 */ +#endif +#ifndef TclAllocateFreeObjects +#define TclAllocateFreeObjects \ + (tclIntStubsPtr->tclAllocateFreeObjects) /* 3 */ +#endif +/* Slot 4 is reserved */ +#ifndef TclCleanupChildren +#define TclCleanupChildren \ + (tclIntStubsPtr->tclCleanupChildren) /* 5 */ +#endif +#ifndef TclCleanupCommand +#define TclCleanupCommand \ + (tclIntStubsPtr->tclCleanupCommand) /* 6 */ +#endif +#ifndef TclCopyAndCollapse +#define TclCopyAndCollapse \ + (tclIntStubsPtr->tclCopyAndCollapse) /* 7 */ +#endif +#ifndef TclCopyChannel +#define TclCopyChannel \ + (tclIntStubsPtr->tclCopyChannel) /* 8 */ +#endif +#ifndef TclCreatePipeline +#define TclCreatePipeline \ + (tclIntStubsPtr->tclCreatePipeline) /* 9 */ +#endif +#ifndef TclCreateProc +#define TclCreateProc \ + (tclIntStubsPtr->tclCreateProc) /* 10 */ +#endif +#ifndef TclDeleteCompiledLocalVars +#define TclDeleteCompiledLocalVars \ + (tclIntStubsPtr->tclDeleteCompiledLocalVars) /* 11 */ +#endif +#ifndef TclDeleteVars +#define TclDeleteVars \ + (tclIntStubsPtr->tclDeleteVars) /* 12 */ +#endif +#ifndef TclDoGlob +#define TclDoGlob \ + (tclIntStubsPtr->tclDoGlob) /* 13 */ +#endif +#ifndef TclDumpMemoryInfo +#define TclDumpMemoryInfo \ + (tclIntStubsPtr->tclDumpMemoryInfo) /* 14 */ +#endif +/* Slot 15 is reserved */ +#ifndef TclExprFloatError +#define TclExprFloatError \ + (tclIntStubsPtr->tclExprFloatError) /* 16 */ +#endif +#ifndef TclFileAttrsCmd +#define TclFileAttrsCmd \ + (tclIntStubsPtr->tclFileAttrsCmd) /* 17 */ +#endif +#ifndef TclFileCopyCmd +#define TclFileCopyCmd \ + (tclIntStubsPtr->tclFileCopyCmd) /* 18 */ +#endif +#ifndef TclFileDeleteCmd +#define TclFileDeleteCmd \ + (tclIntStubsPtr->tclFileDeleteCmd) /* 19 */ +#endif +#ifndef TclFileMakeDirsCmd +#define TclFileMakeDirsCmd \ + (tclIntStubsPtr->tclFileMakeDirsCmd) /* 20 */ +#endif +#ifndef TclFileRenameCmd +#define TclFileRenameCmd \ + (tclIntStubsPtr->tclFileRenameCmd) /* 21 */ +#endif +#ifndef TclFindElement +#define TclFindElement \ + (tclIntStubsPtr->tclFindElement) /* 22 */ +#endif +#ifndef TclFindProc +#define TclFindProc \ + (tclIntStubsPtr->tclFindProc) /* 23 */ +#endif +#ifndef TclFormatInt +#define TclFormatInt \ + (tclIntStubsPtr->tclFormatInt) /* 24 */ +#endif +#ifndef TclFreePackageInfo +#define TclFreePackageInfo \ + (tclIntStubsPtr->tclFreePackageInfo) /* 25 */ +#endif +/* Slot 26 is reserved */ +#ifndef TclGetDate +#define TclGetDate \ + (tclIntStubsPtr->tclGetDate) /* 27 */ +#endif +#ifndef TclpGetDefaultStdChannel +#define TclpGetDefaultStdChannel \ + (tclIntStubsPtr->tclpGetDefaultStdChannel) /* 28 */ +#endif +#ifndef TclGetElementOfIndexedArray +#define TclGetElementOfIndexedArray \ + (tclIntStubsPtr->tclGetElementOfIndexedArray) /* 29 */ +#endif +/* Slot 30 is reserved */ +#ifndef TclGetExtension +#define TclGetExtension \ + (tclIntStubsPtr->tclGetExtension) /* 31 */ +#endif +#ifndef TclGetFrame +#define TclGetFrame \ + (tclIntStubsPtr->tclGetFrame) /* 32 */ +#endif +#ifndef TclGetInterpProc +#define TclGetInterpProc \ + (tclIntStubsPtr->tclGetInterpProc) /* 33 */ +#endif +#ifndef TclGetIntForIndex +#define TclGetIntForIndex \ + (tclIntStubsPtr->tclGetIntForIndex) /* 34 */ +#endif +#ifndef TclGetIndexedScalar +#define TclGetIndexedScalar \ + (tclIntStubsPtr->tclGetIndexedScalar) /* 35 */ +#endif +#ifndef TclGetLong +#define TclGetLong \ + (tclIntStubsPtr->tclGetLong) /* 36 */ +#endif +#ifndef TclGetLoadedPackages +#define TclGetLoadedPackages \ + (tclIntStubsPtr->tclGetLoadedPackages) /* 37 */ +#endif +#ifndef TclGetNamespaceForQualName +#define TclGetNamespaceForQualName \ + (tclIntStubsPtr->tclGetNamespaceForQualName) /* 38 */ +#endif +#ifndef TclGetObjInterpProc +#define TclGetObjInterpProc \ + (tclIntStubsPtr->tclGetObjInterpProc) /* 39 */ +#endif +#ifndef TclGetOpenMode +#define TclGetOpenMode \ + (tclIntStubsPtr->tclGetOpenMode) /* 40 */ +#endif +#ifndef TclGetOriginalCommand +#define TclGetOriginalCommand \ + (tclIntStubsPtr->tclGetOriginalCommand) /* 41 */ +#endif +#ifndef TclpGetUserHome +#define TclpGetUserHome \ + (tclIntStubsPtr->tclpGetUserHome) /* 42 */ +#endif +#ifndef TclGlobalInvoke +#define TclGlobalInvoke \ + (tclIntStubsPtr->tclGlobalInvoke) /* 43 */ +#endif +#ifndef TclGuessPackageName +#define TclGuessPackageName \ + (tclIntStubsPtr->tclGuessPackageName) /* 44 */ +#endif +#ifndef TclHideUnsafeCommands +#define TclHideUnsafeCommands \ + (tclIntStubsPtr->tclHideUnsafeCommands) /* 45 */ +#endif +#ifndef TclInExit +#define TclInExit \ + (tclIntStubsPtr->tclInExit) /* 46 */ +#endif +#ifndef TclIncrElementOfIndexedArray +#define TclIncrElementOfIndexedArray \ + (tclIntStubsPtr->tclIncrElementOfIndexedArray) /* 47 */ +#endif +#ifndef TclIncrIndexedScalar +#define TclIncrIndexedScalar \ + (tclIntStubsPtr->tclIncrIndexedScalar) /* 48 */ +#endif +#ifndef TclIncrVar2 +#define TclIncrVar2 \ + (tclIntStubsPtr->tclIncrVar2) /* 49 */ +#endif +#ifndef TclInitCompiledLocals +#define TclInitCompiledLocals \ + (tclIntStubsPtr->tclInitCompiledLocals) /* 50 */ +#endif +#ifndef TclInterpInit +#define TclInterpInit \ + (tclIntStubsPtr->tclInterpInit) /* 51 */ +#endif +#ifndef TclInvoke +#define TclInvoke \ + (tclIntStubsPtr->tclInvoke) /* 52 */ +#endif +#ifndef TclInvokeObjectCommand +#define TclInvokeObjectCommand \ + (tclIntStubsPtr->tclInvokeObjectCommand) /* 53 */ +#endif +#ifndef TclInvokeStringCommand +#define TclInvokeStringCommand \ + (tclIntStubsPtr->tclInvokeStringCommand) /* 54 */ +#endif +#ifndef TclIsProc +#define TclIsProc \ + (tclIntStubsPtr->tclIsProc) /* 55 */ +#endif +/* Slot 56 is reserved */ +/* Slot 57 is reserved */ +#ifndef TclLookupVar +#define TclLookupVar \ + (tclIntStubsPtr->tclLookupVar) /* 58 */ +#endif +#ifndef TclpMatchFiles +#define TclpMatchFiles \ + (tclIntStubsPtr->tclpMatchFiles) /* 59 */ +#endif +#ifndef TclNeedSpace +#define TclNeedSpace \ + (tclIntStubsPtr->tclNeedSpace) /* 60 */ +#endif +#ifndef TclNewProcBodyObj +#define TclNewProcBodyObj \ + (tclIntStubsPtr->tclNewProcBodyObj) /* 61 */ +#endif +#ifndef TclObjCommandComplete +#define TclObjCommandComplete \ + (tclIntStubsPtr->tclObjCommandComplete) /* 62 */ +#endif +#ifndef TclObjInterpProc +#define TclObjInterpProc \ + (tclIntStubsPtr->tclObjInterpProc) /* 63 */ +#endif +#ifndef TclObjInvoke +#define TclObjInvoke \ + (tclIntStubsPtr->tclObjInvoke) /* 64 */ +#endif +#ifndef TclObjInvokeGlobal +#define TclObjInvokeGlobal \ + (tclIntStubsPtr->tclObjInvokeGlobal) /* 65 */ +#endif +#ifndef TclOpenFileChannelDeleteProc +#define TclOpenFileChannelDeleteProc \ + (tclIntStubsPtr->tclOpenFileChannelDeleteProc) /* 66 */ +#endif +#ifndef TclOpenFileChannelInsertProc +#define TclOpenFileChannelInsertProc \ + (tclIntStubsPtr->tclOpenFileChannelInsertProc) /* 67 */ +#endif +#ifndef TclpAccess +#define TclpAccess \ + (tclIntStubsPtr->tclpAccess) /* 68 */ +#endif +#ifndef TclpAlloc +#define TclpAlloc \ + (tclIntStubsPtr->tclpAlloc) /* 69 */ +#endif +#ifndef TclpCopyFile +#define TclpCopyFile \ + (tclIntStubsPtr->tclpCopyFile) /* 70 */ +#endif +#ifndef TclpCopyDirectory +#define TclpCopyDirectory \ + (tclIntStubsPtr->tclpCopyDirectory) /* 71 */ +#endif +#ifndef TclpCreateDirectory +#define TclpCreateDirectory \ + (tclIntStubsPtr->tclpCreateDirectory) /* 72 */ +#endif +#ifndef TclpDeleteFile +#define TclpDeleteFile \ + (tclIntStubsPtr->tclpDeleteFile) /* 73 */ +#endif +#ifndef TclpFree +#define TclpFree \ + (tclIntStubsPtr->tclpFree) /* 74 */ +#endif +#ifndef TclpGetClicks +#define TclpGetClicks \ + (tclIntStubsPtr->tclpGetClicks) /* 75 */ +#endif +#ifndef TclpGetSeconds +#define TclpGetSeconds \ + (tclIntStubsPtr->tclpGetSeconds) /* 76 */ +#endif +#ifndef TclpGetTime +#define TclpGetTime \ + (tclIntStubsPtr->tclpGetTime) /* 77 */ +#endif +#ifndef TclpGetTimeZone +#define TclpGetTimeZone \ + (tclIntStubsPtr->tclpGetTimeZone) /* 78 */ +#endif +#ifndef TclpListVolumes +#define TclpListVolumes \ + (tclIntStubsPtr->tclpListVolumes) /* 79 */ +#endif +#ifndef TclpOpenFileChannel +#define TclpOpenFileChannel \ + (tclIntStubsPtr->tclpOpenFileChannel) /* 80 */ +#endif +#ifndef TclpRealloc +#define TclpRealloc \ + (tclIntStubsPtr->tclpRealloc) /* 81 */ +#endif +#ifndef TclpRemoveDirectory +#define TclpRemoveDirectory \ + (tclIntStubsPtr->tclpRemoveDirectory) /* 82 */ +#endif +#ifndef TclpRenameFile +#define TclpRenameFile \ + (tclIntStubsPtr->tclpRenameFile) /* 83 */ +#endif +/* Slot 84 is reserved */ +/* Slot 85 is reserved */ +/* Slot 86 is reserved */ +/* Slot 87 is reserved */ +#ifndef TclPrecTraceProc +#define TclPrecTraceProc \ + (tclIntStubsPtr->tclPrecTraceProc) /* 88 */ +#endif +#ifndef TclPreventAliasLoop +#define TclPreventAliasLoop \ + (tclIntStubsPtr->tclPreventAliasLoop) /* 89 */ +#endif +/* Slot 90 is reserved */ +#ifndef TclProcCleanupProc +#define TclProcCleanupProc \ + (tclIntStubsPtr->tclProcCleanupProc) /* 91 */ +#endif +#ifndef TclProcCompileProc +#define TclProcCompileProc \ + (tclIntStubsPtr->tclProcCompileProc) /* 92 */ +#endif +#ifndef TclProcDeleteProc +#define TclProcDeleteProc \ + (tclIntStubsPtr->tclProcDeleteProc) /* 93 */ +#endif +#ifndef TclProcInterpProc +#define TclProcInterpProc \ + (tclIntStubsPtr->tclProcInterpProc) /* 94 */ +#endif +#ifndef TclpStat +#define TclpStat \ + (tclIntStubsPtr->tclpStat) /* 95 */ +#endif +#ifndef TclRenameCommand +#define TclRenameCommand \ + (tclIntStubsPtr->tclRenameCommand) /* 96 */ +#endif +#ifndef TclResetShadowedCmdRefs +#define TclResetShadowedCmdRefs \ + (tclIntStubsPtr->tclResetShadowedCmdRefs) /* 97 */ +#endif +#ifndef TclServiceIdle +#define TclServiceIdle \ + (tclIntStubsPtr->tclServiceIdle) /* 98 */ +#endif +#ifndef TclSetElementOfIndexedArray +#define TclSetElementOfIndexedArray \ + (tclIntStubsPtr->tclSetElementOfIndexedArray) /* 99 */ +#endif +#ifndef TclSetIndexedScalar +#define TclSetIndexedScalar \ + (tclIntStubsPtr->tclSetIndexedScalar) /* 100 */ +#endif +/* Slot 101 is reserved */ +#ifndef TclSetupEnv +#define TclSetupEnv \ + (tclIntStubsPtr->tclSetupEnv) /* 102 */ +#endif +#ifndef TclSockGetPort +#define TclSockGetPort \ + (tclIntStubsPtr->tclSockGetPort) /* 103 */ +#endif +#ifndef TclSockMinimumBuffers +#define TclSockMinimumBuffers \ + (tclIntStubsPtr->tclSockMinimumBuffers) /* 104 */ +#endif +#ifndef TclStat +#define TclStat \ + (tclIntStubsPtr->tclStat) /* 105 */ +#endif +#ifndef TclStatDeleteProc +#define TclStatDeleteProc \ + (tclIntStubsPtr->tclStatDeleteProc) /* 106 */ +#endif +#ifndef TclStatInsertProc +#define TclStatInsertProc \ + (tclIntStubsPtr->tclStatInsertProc) /* 107 */ +#endif +#ifndef TclTeardownNamespace +#define TclTeardownNamespace \ + (tclIntStubsPtr->tclTeardownNamespace) /* 108 */ +#endif +#ifndef TclUpdateReturnInfo +#define TclUpdateReturnInfo \ + (tclIntStubsPtr->tclUpdateReturnInfo) /* 109 */ +#endif +/* Slot 110 is reserved */ +#ifndef Tcl_AddInterpResolvers +#define Tcl_AddInterpResolvers \ + (tclIntStubsPtr->tcl_AddInterpResolvers) /* 111 */ +#endif +#ifndef Tcl_AppendExportList +#define Tcl_AppendExportList \ + (tclIntStubsPtr->tcl_AppendExportList) /* 112 */ +#endif +#ifndef Tcl_CreateNamespace +#define Tcl_CreateNamespace \ + (tclIntStubsPtr->tcl_CreateNamespace) /* 113 */ +#endif +#ifndef Tcl_DeleteNamespace +#define Tcl_DeleteNamespace \ + (tclIntStubsPtr->tcl_DeleteNamespace) /* 114 */ +#endif +#ifndef Tcl_Export +#define Tcl_Export \ + (tclIntStubsPtr->tcl_Export) /* 115 */ +#endif +#ifndef Tcl_FindCommand +#define Tcl_FindCommand \ + (tclIntStubsPtr->tcl_FindCommand) /* 116 */ +#endif +#ifndef Tcl_FindNamespace +#define Tcl_FindNamespace \ + (tclIntStubsPtr->tcl_FindNamespace) /* 117 */ +#endif +#ifndef Tcl_GetInterpResolvers +#define Tcl_GetInterpResolvers \ + (tclIntStubsPtr->tcl_GetInterpResolvers) /* 118 */ +#endif +#ifndef Tcl_GetNamespaceResolvers +#define Tcl_GetNamespaceResolvers \ + (tclIntStubsPtr->tcl_GetNamespaceResolvers) /* 119 */ +#endif +#ifndef Tcl_FindNamespaceVar +#define Tcl_FindNamespaceVar \ + (tclIntStubsPtr->tcl_FindNamespaceVar) /* 120 */ +#endif +#ifndef Tcl_ForgetImport +#define Tcl_ForgetImport \ + (tclIntStubsPtr->tcl_ForgetImport) /* 121 */ +#endif +#ifndef Tcl_GetCommandFromObj +#define Tcl_GetCommandFromObj \ + (tclIntStubsPtr->tcl_GetCommandFromObj) /* 122 */ +#endif +#ifndef Tcl_GetCommandFullName +#define Tcl_GetCommandFullName \ + (tclIntStubsPtr->tcl_GetCommandFullName) /* 123 */ +#endif +#ifndef Tcl_GetCurrentNamespace +#define Tcl_GetCurrentNamespace \ + (tclIntStubsPtr->tcl_GetCurrentNamespace) /* 124 */ +#endif +#ifndef Tcl_GetGlobalNamespace +#define Tcl_GetGlobalNamespace \ + (tclIntStubsPtr->tcl_GetGlobalNamespace) /* 125 */ +#endif +#ifndef Tcl_GetVariableFullName +#define Tcl_GetVariableFullName \ + (tclIntStubsPtr->tcl_GetVariableFullName) /* 126 */ +#endif +#ifndef Tcl_Import +#define Tcl_Import \ + (tclIntStubsPtr->tcl_Import) /* 127 */ +#endif +#ifndef Tcl_PopCallFrame +#define Tcl_PopCallFrame \ + (tclIntStubsPtr->tcl_PopCallFrame) /* 128 */ +#endif +#ifndef Tcl_PushCallFrame +#define Tcl_PushCallFrame \ + (tclIntStubsPtr->tcl_PushCallFrame) /* 129 */ +#endif +#ifndef Tcl_RemoveInterpResolvers +#define Tcl_RemoveInterpResolvers \ + (tclIntStubsPtr->tcl_RemoveInterpResolvers) /* 130 */ +#endif +#ifndef Tcl_SetNamespaceResolvers +#define Tcl_SetNamespaceResolvers \ + (tclIntStubsPtr->tcl_SetNamespaceResolvers) /* 131 */ +#endif +#ifndef TclpHasSockets +#define TclpHasSockets \ + (tclIntStubsPtr->tclpHasSockets) /* 132 */ +#endif +#ifndef TclpGetDate +#define TclpGetDate \ + (tclIntStubsPtr->tclpGetDate) /* 133 */ +#endif +#ifndef TclpStrftime +#define TclpStrftime \ + (tclIntStubsPtr->tclpStrftime) /* 134 */ +#endif +#ifndef TclpCheckStackSpace +#define TclpCheckStackSpace \ + (tclIntStubsPtr->tclpCheckStackSpace) /* 135 */ +#endif +/* Slot 136 is reserved */ +#ifndef TclpChdir +#define TclpChdir \ + (tclIntStubsPtr->tclpChdir) /* 137 */ +#endif +#ifndef TclGetEnv +#define TclGetEnv \ + (tclIntStubsPtr->tclGetEnv) /* 138 */ +#endif +#ifndef TclpLoadFile +#define TclpLoadFile \ + (tclIntStubsPtr->tclpLoadFile) /* 139 */ +#endif +#ifndef TclLooksLikeInt +#define TclLooksLikeInt \ + (tclIntStubsPtr->tclLooksLikeInt) /* 140 */ +#endif +#ifndef TclpGetCwd +#define TclpGetCwd \ + (tclIntStubsPtr->tclpGetCwd) /* 141 */ +#endif + +#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#endif /* _TCLINTDECLS */ ADDED generic/tclIntPlatDecls.h Index: generic/tclIntPlatDecls.h ================================================================== --- /dev/null +++ generic/tclIntPlatDecls.h @@ -0,0 +1,519 @@ +/* + * 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. + * + * RCS: @(#) $Id: tclIntPlatDecls.h,v 1.3.2.7 1999/04/01 21:58:18 stanton Exp $ + */ + +#ifndef _TCLINTPLATDECLS +#define _TCLINTPLATDECLS + +/* + * 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. */ + +/* + * Exported function declarations: + */ + +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 0 */ +EXTERN void TclGetAndDetachPids _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Channel chan)); +/* 1 */ +EXTERN int TclpCloseFile _ANSI_ARGS_((TclFile file)); +/* 2 */ +EXTERN Tcl_Channel TclpCreateCommandChannel _ANSI_ARGS_(( + TclFile readFile, TclFile writeFile, + TclFile errorFile, int numPids, + Tcl_Pid * pidPtr)); +/* 3 */ +EXTERN int TclpCreatePipe _ANSI_ARGS_((TclFile * readPipe, + TclFile * writePipe)); +/* 4 */ +EXTERN int TclpCreateProcess _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv, TclFile inputFile, + TclFile outputFile, TclFile errorFile, + Tcl_Pid * pidPtr)); +/* Slot 5 is reserved */ +/* 6 */ +EXTERN TclFile TclpMakeFile _ANSI_ARGS_((Tcl_Channel channel, + int direction)); +/* 7 */ +EXTERN TclFile TclpOpenFile _ANSI_ARGS_((CONST char * fname, + int mode)); +/* 8 */ +EXTERN int TclUnixWaitForFile _ANSI_ARGS_((int fd, int mask, + int timeout)); +/* 9 */ +EXTERN TclFile TclpCreateTempFile _ANSI_ARGS_(( + CONST char * contents)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 0 */ +EXTERN void TclWinConvertError _ANSI_ARGS_((DWORD errCode)); +/* 1 */ +EXTERN void TclWinConvertWSAError _ANSI_ARGS_((DWORD errCode)); +/* 2 */ +EXTERN struct servent * TclWinGetServByName _ANSI_ARGS_((CONST char * nm, + CONST char * proto)); +/* 3 */ +EXTERN int TclWinGetSockOpt _ANSI_ARGS_((SOCKET s, int level, + int optname, char FAR * optval, + int FAR * optlen)); +/* 4 */ +EXTERN HINSTANCE TclWinGetTclInstance _ANSI_ARGS_((void)); +/* Slot 5 is reserved */ +/* 6 */ +EXTERN u_short TclWinNToHS _ANSI_ARGS_((u_short ns)); +/* 7 */ +EXTERN int TclWinSetSockOpt _ANSI_ARGS_((SOCKET s, int level, + int optname, CONST char FAR * optval, + int optlen)); +/* 8 */ +EXTERN unsigned long TclpGetPid _ANSI_ARGS_((Tcl_Pid pid)); +/* 9 */ +EXTERN int TclWinGetPlatformId _ANSI_ARGS_((void)); +/* 10 */ +EXTERN int TclWinSynchSpawn _ANSI_ARGS_((void * args, int type, + void ** trans, Tcl_Pid * pidPtr)); +/* 11 */ +EXTERN void TclGetAndDetachPids _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Channel chan)); +/* 12 */ +EXTERN int TclpCloseFile _ANSI_ARGS_((TclFile file)); +/* 13 */ +EXTERN Tcl_Channel TclpCreateCommandChannel _ANSI_ARGS_(( + TclFile readFile, TclFile writeFile, + TclFile errorFile, int numPids, + Tcl_Pid * pidPtr)); +/* 14 */ +EXTERN int TclpCreatePipe _ANSI_ARGS_((TclFile * readPipe, + TclFile * writePipe)); +/* 15 */ +EXTERN int TclpCreateProcess _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv, TclFile inputFile, + TclFile outputFile, TclFile errorFile, + Tcl_Pid * pidPtr)); +/* Slot 16 is reserved */ +/* Slot 17 is reserved */ +/* 18 */ +EXTERN TclFile TclpMakeFile _ANSI_ARGS_((Tcl_Channel channel, + int direction)); +/* 19 */ +EXTERN TclFile TclpOpenFile _ANSI_ARGS_((CONST char * fname, + int mode)); +/* 20 */ +EXTERN void TclWinAddProcess _ANSI_ARGS_((HANDLE hProcess, + DWORD id)); +/* 21 */ +EXTERN void TclpAsyncMark _ANSI_ARGS_((Tcl_AsyncHandler async)); +/* 22 */ +EXTERN TclFile TclpCreateTempFile _ANSI_ARGS_(( + CONST char * contents)); +/* 23 */ +EXTERN char * TclpGetTZName _ANSI_ARGS_((int isdst)); +/* 24 */ +EXTERN char * TclWinNoBackslash _ANSI_ARGS_((char * path)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 0 */ +EXTERN VOID * TclpSysAlloc _ANSI_ARGS_((long size, int isBin)); +/* 1 */ +EXTERN void TclpSysFree _ANSI_ARGS_((VOID * ptr)); +/* 2 */ +EXTERN VOID * TclpSysRealloc _ANSI_ARGS_((VOID * cp, + unsigned int size)); +/* 3 */ +EXTERN void TclpExit _ANSI_ARGS_((int status)); +/* 4 */ +EXTERN int FSpGetDefaultDir _ANSI_ARGS_((FSSpecPtr theSpec)); +/* 5 */ +EXTERN int FSpSetDefaultDir _ANSI_ARGS_((FSSpecPtr theSpec)); +/* 6 */ +EXTERN OSErr FSpFindFolder _ANSI_ARGS_((short vRefNum, + OSType folderType, Boolean createFolder, + FSSpec * spec)); +/* 7 */ +EXTERN void GetGlobalMouse _ANSI_ARGS_((Point * mouse)); +/* 8 */ +EXTERN pascal OSErr FSpGetDirectoryID _ANSI_ARGS_((CONST FSSpec * spec, + long * theDirID, Boolean * isDirectory)); +/* 9 */ +EXTERN pascal short FSpOpenResFileCompat _ANSI_ARGS_(( + CONST FSSpec * spec, SignedByte permission)); +/* 10 */ +EXTERN pascal void FSpCreateResFileCompat _ANSI_ARGS_(( + CONST FSSpec * spec, OSType creator, + OSType fileType, ScriptCode scriptTag)); +/* 11 */ +EXTERN int FSpLocationFromPath _ANSI_ARGS_((int length, + CONST char * path, FSSpecPtr theSpec)); +/* 12 */ +EXTERN OSErr FSpPathFromLocation _ANSI_ARGS_((FSSpecPtr theSpec, + int * length, Handle * fullPath)); +/* 13 */ +EXTERN void TclMacExitHandler _ANSI_ARGS_((void)); +/* 14 */ +EXTERN void TclMacInitExitToShell _ANSI_ARGS_((int usePatch)); +/* 15 */ +EXTERN OSErr TclMacInstallExitToShellPatch _ANSI_ARGS_(( + ExitToShellProcPtr newProc)); +/* 16 */ +EXTERN int TclMacOSErrorToPosixError _ANSI_ARGS_((int error)); +/* 17 */ +EXTERN void TclMacRemoveTimer _ANSI_ARGS_((void * timerToken)); +/* 18 */ +EXTERN void * TclMacStartTimer _ANSI_ARGS_((long ms)); +/* 19 */ +EXTERN int TclMacTimerExpired _ANSI_ARGS_((void * timerToken)); +/* 20 */ +EXTERN int TclMacRegisterResourceFork _ANSI_ARGS_(( + short fileRef, Tcl_Obj * tokenPtr, + int insert)); +/* 21 */ +EXTERN short TclMacUnRegisterResourceFork _ANSI_ARGS_(( + char * tokenPtr, Tcl_Obj * resultPtr)); +/* 22 */ +EXTERN int TclMacCreateEnv _ANSI_ARGS_((void)); +/* 23 */ +EXTERN FILE * TclMacFOpenHack _ANSI_ARGS_((CONST char * path, + CONST char * mode)); +/* Slot 24 is reserved */ +/* 25 */ +EXTERN int TclMacChmod _ANSI_ARGS_((char * path, int mode)); +#endif /* MAC_TCL */ + +typedef struct TclIntPlatStubs { + int magic; + struct TclIntPlatStubHooks *hooks; + +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void (*tclGetAndDetachPids) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 0 */ + int (*tclpCloseFile) _ANSI_ARGS_((TclFile file)); /* 1 */ + Tcl_Channel (*tclpCreateCommandChannel) _ANSI_ARGS_((TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid * pidPtr)); /* 2 */ + int (*tclpCreatePipe) _ANSI_ARGS_((TclFile * readPipe, TclFile * writePipe)); /* 3 */ + int (*tclpCreateProcess) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid * pidPtr)); /* 4 */ + void *reserved5; + TclFile (*tclpMakeFile) _ANSI_ARGS_((Tcl_Channel channel, int direction)); /* 6 */ + TclFile (*tclpOpenFile) _ANSI_ARGS_((CONST char * fname, int mode)); /* 7 */ + int (*tclUnixWaitForFile) _ANSI_ARGS_((int fd, int mask, int timeout)); /* 8 */ + TclFile (*tclpCreateTempFile) _ANSI_ARGS_((CONST char * contents)); /* 9 */ +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tclWinConvertError) _ANSI_ARGS_((DWORD errCode)); /* 0 */ + void (*tclWinConvertWSAError) _ANSI_ARGS_((DWORD errCode)); /* 1 */ + struct servent * (*tclWinGetServByName) _ANSI_ARGS_((CONST char * nm, CONST char * proto)); /* 2 */ + int (*tclWinGetSockOpt) _ANSI_ARGS_((SOCKET s, int level, int optname, char FAR * optval, int FAR * optlen)); /* 3 */ + HINSTANCE (*tclWinGetTclInstance) _ANSI_ARGS_((void)); /* 4 */ + void *reserved5; + u_short (*tclWinNToHS) _ANSI_ARGS_((u_short ns)); /* 6 */ + int (*tclWinSetSockOpt) _ANSI_ARGS_((SOCKET s, int level, int optname, CONST char FAR * optval, int optlen)); /* 7 */ + unsigned long (*tclpGetPid) _ANSI_ARGS_((Tcl_Pid pid)); /* 8 */ + int (*tclWinGetPlatformId) _ANSI_ARGS_((void)); /* 9 */ + int (*tclWinSynchSpawn) _ANSI_ARGS_((void * args, int type, void ** trans, Tcl_Pid * pidPtr)); /* 10 */ + void (*tclGetAndDetachPids) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 11 */ + int (*tclpCloseFile) _ANSI_ARGS_((TclFile file)); /* 12 */ + Tcl_Channel (*tclpCreateCommandChannel) _ANSI_ARGS_((TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid * pidPtr)); /* 13 */ + int (*tclpCreatePipe) _ANSI_ARGS_((TclFile * readPipe, TclFile * writePipe)); /* 14 */ + int (*tclpCreateProcess) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid * pidPtr)); /* 15 */ + void *reserved16; + void *reserved17; + TclFile (*tclpMakeFile) _ANSI_ARGS_((Tcl_Channel channel, int direction)); /* 18 */ + TclFile (*tclpOpenFile) _ANSI_ARGS_((CONST char * fname, int mode)); /* 19 */ + void (*tclWinAddProcess) _ANSI_ARGS_((HANDLE hProcess, DWORD id)); /* 20 */ + void (*tclpAsyncMark) _ANSI_ARGS_((Tcl_AsyncHandler async)); /* 21 */ + TclFile (*tclpCreateTempFile) _ANSI_ARGS_((CONST char * contents)); /* 22 */ + char * (*tclpGetTZName) _ANSI_ARGS_((int isdst)); /* 23 */ + char * (*tclWinNoBackslash) _ANSI_ARGS_((char * path)); /* 24 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + VOID * (*tclpSysAlloc) _ANSI_ARGS_((long size, int isBin)); /* 0 */ + void (*tclpSysFree) _ANSI_ARGS_((VOID * ptr)); /* 1 */ + VOID * (*tclpSysRealloc) _ANSI_ARGS_((VOID * cp, unsigned int size)); /* 2 */ + void (*tclpExit) _ANSI_ARGS_((int status)); /* 3 */ + int (*fSpGetDefaultDir) _ANSI_ARGS_((FSSpecPtr theSpec)); /* 4 */ + int (*fSpSetDefaultDir) _ANSI_ARGS_((FSSpecPtr theSpec)); /* 5 */ + OSErr (*fSpFindFolder) _ANSI_ARGS_((short vRefNum, OSType folderType, Boolean createFolder, FSSpec * spec)); /* 6 */ + void (*getGlobalMouse) _ANSI_ARGS_((Point * mouse)); /* 7 */ + pascal OSErr (*fSpGetDirectoryID) _ANSI_ARGS_((CONST FSSpec * spec, long * theDirID, Boolean * isDirectory)); /* 8 */ + pascal short (*fSpOpenResFileCompat) _ANSI_ARGS_((CONST FSSpec * spec, SignedByte permission)); /* 9 */ + pascal void (*fSpCreateResFileCompat) _ANSI_ARGS_((CONST FSSpec * spec, OSType creator, OSType fileType, ScriptCode scriptTag)); /* 10 */ + int (*fSpLocationFromPath) _ANSI_ARGS_((int length, CONST char * path, FSSpecPtr theSpec)); /* 11 */ + OSErr (*fSpPathFromLocation) _ANSI_ARGS_((FSSpecPtr theSpec, int * length, Handle * fullPath)); /* 12 */ + void (*tclMacExitHandler) _ANSI_ARGS_((void)); /* 13 */ + void (*tclMacInitExitToShell) _ANSI_ARGS_((int usePatch)); /* 14 */ + OSErr (*tclMacInstallExitToShellPatch) _ANSI_ARGS_((ExitToShellProcPtr newProc)); /* 15 */ + int (*tclMacOSErrorToPosixError) _ANSI_ARGS_((int error)); /* 16 */ + void (*tclMacRemoveTimer) _ANSI_ARGS_((void * timerToken)); /* 17 */ + void * (*tclMacStartTimer) _ANSI_ARGS_((long ms)); /* 18 */ + int (*tclMacTimerExpired) _ANSI_ARGS_((void * timerToken)); /* 19 */ + int (*tclMacRegisterResourceFork) _ANSI_ARGS_((short fileRef, Tcl_Obj * tokenPtr, int insert)); /* 20 */ + short (*tclMacUnRegisterResourceFork) _ANSI_ARGS_((char * tokenPtr, Tcl_Obj * resultPtr)); /* 21 */ + int (*tclMacCreateEnv) _ANSI_ARGS_((void)); /* 22 */ + FILE * (*tclMacFOpenHack) _ANSI_ARGS_((CONST char * path, CONST char * mode)); /* 23 */ + void *reserved24; + int (*tclMacChmod) _ANSI_ARGS_((char * path, int mode)); /* 25 */ +#endif /* MAC_TCL */ +} TclIntPlatStubs; + +extern TclIntPlatStubs *tclIntPlatStubsPtr; + +#if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclGetAndDetachPids +#define TclGetAndDetachPids \ + (tclIntPlatStubsPtr->tclGetAndDetachPids) /* 0 */ +#endif +#ifndef TclpCloseFile +#define TclpCloseFile \ + (tclIntPlatStubsPtr->tclpCloseFile) /* 1 */ +#endif +#ifndef TclpCreateCommandChannel +#define TclpCreateCommandChannel \ + (tclIntPlatStubsPtr->tclpCreateCommandChannel) /* 2 */ +#endif +#ifndef TclpCreatePipe +#define TclpCreatePipe \ + (tclIntPlatStubsPtr->tclpCreatePipe) /* 3 */ +#endif +#ifndef TclpCreateProcess +#define TclpCreateProcess \ + (tclIntPlatStubsPtr->tclpCreateProcess) /* 4 */ +#endif +/* Slot 5 is reserved */ +#ifndef TclpMakeFile +#define TclpMakeFile \ + (tclIntPlatStubsPtr->tclpMakeFile) /* 6 */ +#endif +#ifndef TclpOpenFile +#define TclpOpenFile \ + (tclIntPlatStubsPtr->tclpOpenFile) /* 7 */ +#endif +#ifndef TclUnixWaitForFile +#define TclUnixWaitForFile \ + (tclIntPlatStubsPtr->tclUnixWaitForFile) /* 8 */ +#endif +#ifndef TclpCreateTempFile +#define TclpCreateTempFile \ + (tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclWinConvertError +#define TclWinConvertError \ + (tclIntPlatStubsPtr->tclWinConvertError) /* 0 */ +#endif +#ifndef TclWinConvertWSAError +#define TclWinConvertWSAError \ + (tclIntPlatStubsPtr->tclWinConvertWSAError) /* 1 */ +#endif +#ifndef TclWinGetServByName +#define TclWinGetServByName \ + (tclIntPlatStubsPtr->tclWinGetServByName) /* 2 */ +#endif +#ifndef TclWinGetSockOpt +#define TclWinGetSockOpt \ + (tclIntPlatStubsPtr->tclWinGetSockOpt) /* 3 */ +#endif +#ifndef TclWinGetTclInstance +#define TclWinGetTclInstance \ + (tclIntPlatStubsPtr->tclWinGetTclInstance) /* 4 */ +#endif +/* Slot 5 is reserved */ +#ifndef TclWinNToHS +#define TclWinNToHS \ + (tclIntPlatStubsPtr->tclWinNToHS) /* 6 */ +#endif +#ifndef TclWinSetSockOpt +#define TclWinSetSockOpt \ + (tclIntPlatStubsPtr->tclWinSetSockOpt) /* 7 */ +#endif +#ifndef TclpGetPid +#define TclpGetPid \ + (tclIntPlatStubsPtr->tclpGetPid) /* 8 */ +#endif +#ifndef TclWinGetPlatformId +#define TclWinGetPlatformId \ + (tclIntPlatStubsPtr->tclWinGetPlatformId) /* 9 */ +#endif +#ifndef TclWinSynchSpawn +#define TclWinSynchSpawn \ + (tclIntPlatStubsPtr->tclWinSynchSpawn) /* 10 */ +#endif +#ifndef TclGetAndDetachPids +#define TclGetAndDetachPids \ + (tclIntPlatStubsPtr->tclGetAndDetachPids) /* 11 */ +#endif +#ifndef TclpCloseFile +#define TclpCloseFile \ + (tclIntPlatStubsPtr->tclpCloseFile) /* 12 */ +#endif +#ifndef TclpCreateCommandChannel +#define TclpCreateCommandChannel \ + (tclIntPlatStubsPtr->tclpCreateCommandChannel) /* 13 */ +#endif +#ifndef TclpCreatePipe +#define TclpCreatePipe \ + (tclIntPlatStubsPtr->tclpCreatePipe) /* 14 */ +#endif +#ifndef TclpCreateProcess +#define TclpCreateProcess \ + (tclIntPlatStubsPtr->tclpCreateProcess) /* 15 */ +#endif +/* Slot 16 is reserved */ +/* Slot 17 is reserved */ +#ifndef TclpMakeFile +#define TclpMakeFile \ + (tclIntPlatStubsPtr->tclpMakeFile) /* 18 */ +#endif +#ifndef TclpOpenFile +#define TclpOpenFile \ + (tclIntPlatStubsPtr->tclpOpenFile) /* 19 */ +#endif +#ifndef TclWinAddProcess +#define TclWinAddProcess \ + (tclIntPlatStubsPtr->tclWinAddProcess) /* 20 */ +#endif +#ifndef TclpAsyncMark +#define TclpAsyncMark \ + (tclIntPlatStubsPtr->tclpAsyncMark) /* 21 */ +#endif +#ifndef TclpCreateTempFile +#define TclpCreateTempFile \ + (tclIntPlatStubsPtr->tclpCreateTempFile) /* 22 */ +#endif +#ifndef TclpGetTZName +#define TclpGetTZName \ + (tclIntPlatStubsPtr->tclpGetTZName) /* 23 */ +#endif +#ifndef TclWinNoBackslash +#define TclWinNoBackslash \ + (tclIntPlatStubsPtr->tclWinNoBackslash) /* 24 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TclpSysAlloc +#define TclpSysAlloc \ + (tclIntPlatStubsPtr->tclpSysAlloc) /* 0 */ +#endif +#ifndef TclpSysFree +#define TclpSysFree \ + (tclIntPlatStubsPtr->tclpSysFree) /* 1 */ +#endif +#ifndef TclpSysRealloc +#define TclpSysRealloc \ + (tclIntPlatStubsPtr->tclpSysRealloc) /* 2 */ +#endif +#ifndef TclpExit +#define TclpExit \ + (tclIntPlatStubsPtr->tclpExit) /* 3 */ +#endif +#ifndef FSpGetDefaultDir +#define FSpGetDefaultDir \ + (tclIntPlatStubsPtr->fSpGetDefaultDir) /* 4 */ +#endif +#ifndef FSpSetDefaultDir +#define FSpSetDefaultDir \ + (tclIntPlatStubsPtr->fSpSetDefaultDir) /* 5 */ +#endif +#ifndef FSpFindFolder +#define FSpFindFolder \ + (tclIntPlatStubsPtr->fSpFindFolder) /* 6 */ +#endif +#ifndef GetGlobalMouse +#define GetGlobalMouse \ + (tclIntPlatStubsPtr->getGlobalMouse) /* 7 */ +#endif +#ifndef FSpGetDirectoryID +#define FSpGetDirectoryID \ + (tclIntPlatStubsPtr->fSpGetDirectoryID) /* 8 */ +#endif +#ifndef FSpOpenResFileCompat +#define FSpOpenResFileCompat \ + (tclIntPlatStubsPtr->fSpOpenResFileCompat) /* 9 */ +#endif +#ifndef FSpCreateResFileCompat +#define FSpCreateResFileCompat \ + (tclIntPlatStubsPtr->fSpCreateResFileCompat) /* 10 */ +#endif +#ifndef FSpLocationFromPath +#define FSpLocationFromPath \ + (tclIntPlatStubsPtr->fSpLocationFromPath) /* 11 */ +#endif +#ifndef FSpPathFromLocation +#define FSpPathFromLocation \ + (tclIntPlatStubsPtr->fSpPathFromLocation) /* 12 */ +#endif +#ifndef TclMacExitHandler +#define TclMacExitHandler \ + (tclIntPlatStubsPtr->tclMacExitHandler) /* 13 */ +#endif +#ifndef TclMacInitExitToShell +#define TclMacInitExitToShell \ + (tclIntPlatStubsPtr->tclMacInitExitToShell) /* 14 */ +#endif +#ifndef TclMacInstallExitToShellPatch +#define TclMacInstallExitToShellPatch \ + (tclIntPlatStubsPtr->tclMacInstallExitToShellPatch) /* 15 */ +#endif +#ifndef TclMacOSErrorToPosixError +#define TclMacOSErrorToPosixError \ + (tclIntPlatStubsPtr->tclMacOSErrorToPosixError) /* 16 */ +#endif +#ifndef TclMacRemoveTimer +#define TclMacRemoveTimer \ + (tclIntPlatStubsPtr->tclMacRemoveTimer) /* 17 */ +#endif +#ifndef TclMacStartTimer +#define TclMacStartTimer \ + (tclIntPlatStubsPtr->tclMacStartTimer) /* 18 */ +#endif +#ifndef TclMacTimerExpired +#define TclMacTimerExpired \ + (tclIntPlatStubsPtr->tclMacTimerExpired) /* 19 */ +#endif +#ifndef TclMacRegisterResourceFork +#define TclMacRegisterResourceFork \ + (tclIntPlatStubsPtr->tclMacRegisterResourceFork) /* 20 */ +#endif +#ifndef TclMacUnRegisterResourceFork +#define TclMacUnRegisterResourceFork \ + (tclIntPlatStubsPtr->tclMacUnRegisterResourceFork) /* 21 */ +#endif +#ifndef TclMacCreateEnv +#define TclMacCreateEnv \ + (tclIntPlatStubsPtr->tclMacCreateEnv) /* 22 */ +#endif +#ifndef TclMacFOpenHack +#define TclMacFOpenHack \ + (tclIntPlatStubsPtr->tclMacFOpenHack) /* 23 */ +#endif +/* Slot 24 is reserved */ +#ifndef TclMacChmod +#define TclMacChmod \ + (tclIntPlatStubsPtr->tclMacChmod) /* 25 */ +#endif +#endif /* MAC_TCL */ + +#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#endif /* _TCLINTPLATDECLS */ Index: generic/tclInterp.c ================================================================== --- generic/tclInterp.c +++ generic/tclInterp.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) tclInterp.c 1.128 97/11/05 09:35:12 + * RCS: @(#) $Id: tclInterp.c,v 1.1.2.11 1999/03/26 02:24:45 stanton Exp $ */ #include #include "tclInt.h" #include "tclPort.h" @@ -19,10 +19,46 @@ /* * Counter for how many aliases were created (global) */ static int aliasCounter = 0; +TCL_DECLARE_MUTEX(cntMutex) + +/* + * 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 *namePtr; /* Name of alias command in slave interp. */ + Tcl_Interp *targetInterp; /* Interp in which target command will be + * invoked. */ + Tcl_Obj *prefixPtr; /* Tcl list making up 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_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. */ + Tcl_HashEntry *targetEntryPtr; + /* 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. Random access to this + * hash table is never required - we are using + * a hash table only for convenience. */ +} Alias; /* * * struct Slave: * @@ -29,51 +65,25 @@ * 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 { +typedef struct Slave { Tcl_Interp *masterInterp; /* Master interpreter for this slave. */ - Tcl_HashEntry *slaveEntry; /* Hash entry in masters slave table for - * this slave interpreter. Used to find + 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 - * masters table. */ + * 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 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 { - char *aliasName; /* Name of alias command. */ - char *targetName; /* Name of target command in master interp. */ - Tcl_Interp *targetInterp; /* Master interpreter. */ - int objc; /* Count of additional args to pass. */ - Tcl_Obj **objv; /* Actual additional args to pass. */ - Tcl_HashEntry *aliasEntry; /* Entry for the alias hash table in slave. - * This is used by alias deletion to remove - * the alias from the slave interpreter - * alias table. */ - Tcl_HashEntry *targetEntry; /* 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. Random access to this - * hash table is never required - we are using - * a hash table only for convenience. */ - Tcl_Command slaveCmd; /* Source command in slave interpreter. */ -} Alias; - /* * 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 @@ -84,11 +94,11 @@ * 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. */ -typedef struct { +typedef struct Target { Tcl_Command slaveCmd; /* Command for alias in slave interp. */ Tcl_Interp *slaveInterp; /* Slave Interpreter. */ } Target; /* @@ -105,11 +115,11 @@ * 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 { +typedef struct Master { Tcl_HashTable slaveTable; /* Hash table for slave interpreters. * Maps from command names to Slave records. */ Tcl_HashTable targetTable; /* Hash table for Target Records. Contains * all Target records which denote aliases * from slaves or sibling interpreters that @@ -117,122 +127,883 @@ * table 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; + /* * Prototypes for local static procedures: */ -static int AliasCmd _ANSI_ARGS_((ClientData dummy, +static int AliasCreate _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *slaveInterp, Tcl_Interp *masterInterp, + Tcl_Obj *namePtr, Tcl_Obj *targetPtr, int objc, + Tcl_Obj *CONST objv[])); +static int AliasDelete _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *slaveInterp, Tcl_Obj *namePtr)); +static int AliasDescribe _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *slaveInterp, Tcl_Obj *objPtr)); +static int AliasList _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *slaveInterp)); +static int AliasObjCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *currentInterp, int objc, Tcl_Obj *CONST objv[])); -static void AliasCmdDeleteProc _ANSI_ARGS_(( +static void AliasObjCmdDeleteProc _ANSI_ARGS_(( ClientData clientData)); -static int AliasCreationHelper _ANSI_ARGS_((Tcl_Interp *curInterp, - Tcl_Interp *slaveInterp, Tcl_Interp *masterInterp, - Master *masterPtr, char *aliasName, - char *targetName, int objc, - Tcl_Obj *CONST objv[])); -static int CreateInterpObject _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static Tcl_Interp *CreateSlave _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, char *slavePath, int safe)); -static int DeleteAlias _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Interp *slaveInterp, char *aliasName)); -static int DescribeAlias _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Interp *slaveInterp, char *aliasName)); -static int DeleteInterpObject _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int DeleteOneInterpObject _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, char *path)); -static Tcl_Interp *GetInterp _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, char *path, - Master **masterPtrPtr)); -static int GetTarget _ANSI_ARGS_((Tcl_Interp *interp, char *path, - char *aliasName)); -static int InterpAliasHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpAliasesHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpExistsHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpEvalHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpExposeHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpIsSafeHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpHideHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpHiddenHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpInvokeHiddenHelper _ANSI_ARGS_(( - Tcl_Interp *interp, Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpMarkTrustedHelper _ANSI_ARGS_(( - Tcl_Interp *interp, Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpSlavesHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpShareHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpTargetHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int InterpTransferHelper _ANSI_ARGS_((Tcl_Interp *interp, - Master *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static int MarkTrusted _ANSI_ARGS_((Tcl_Interp *interp)); -static void MasterRecordDeleteProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp)); -static int SlaveAliasHelper _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Interp *slaveInterp, Slave *slavePtr, - int objc, Tcl_Obj *CONST objv[])); -static int SlaveAliasesHelper _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Interp *slaveInterp, Slave *slavePtr, - int objc, Tcl_Obj *CONST objv[])); -static int SlaveEvalHelper _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Interp *slaveInterp, Slave *slavePtr, - int objc, Tcl_Obj *CONST objv[])); -static int SlaveExposeHelper _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Interp *slaveInterp, Slave *slavePtr, - int objc, Tcl_Obj *CONST objv[])); -static int SlaveHideHelper _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Interp *slaveInterp, Slave *slavePtr, - int objc, Tcl_Obj *CONST objv[])); -static int SlaveHiddenHelper _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Interp *slaveInterp, Slave *slavePtr, - int objc, Tcl_Obj *CONST objv[])); -static int SlaveIsSafeHelper _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Interp *slaveInterp, - Slave *slavePtr, int objc, Tcl_Obj *CONST objv[])); -static int SlaveInvokeHiddenHelper _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Interp *slaveInterp, - Slave *slavePtr, int objc, Tcl_Obj *CONST objv[])); -static int SlaveMarkTrustedHelper _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Interp *slaveInterp, Slave *slavePtr, - int objc, Tcl_Obj *CONST objv[])); -static int SlaveObjectCmd _ANSI_ARGS_((ClientData dummy, + +static Tcl_Interp * GetInterp _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *pathPtr)); +static Tcl_Interp * GetInterp2 _ANSI_ARGS_((Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static void InterpInfoDeleteProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp)); +static Tcl_Interp * SlaveCreate _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *pathPtr, int safe)); +static int SlaveEval _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *slaveInterp, int objc, + Tcl_Obj *CONST objv[])); +static int SlaveExpose _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *slaveInterp, int objc, + Tcl_Obj *CONST objv[])); +static int SlaveHide _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *slaveInterp, int objc, + Tcl_Obj *CONST objv[])); +static int SlaveHidden _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *slaveInterp)); +static int SlaveInvokeHidden _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *slaveInterp, int global, int objc, + Tcl_Obj *CONST objv[])); +static int SlaveMarkTrusted _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *slaveInterp)); +static int SlaveObjCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static void SlaveObjectDeleteProc _ANSI_ARGS_(( +static void SlaveObjCmdDeleteProc _ANSI_ARGS_(( ClientData clientData)); -static void SlaveRecordDeleteProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp)); + +/* + *--------------------------------------------------------------------------- + * + * 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(interp) + Tcl_Interp *interp; /* Interpreter to initialize. */ +{ + InterpInfo *interpInfoPtr; + Master *masterPtr; + Slave *slavePtr; + + interpInfoPtr = (InterpInfo *) ckalloc(sizeof(InterpInfo)); + ((Interp *) interp)->interpInfo = (ClientData) interpInfoPtr; + + masterPtr = &interpInfoPtr->master; + Tcl_InitHashTable(&masterPtr->slaveTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&masterPtr->targetTable, TCL_ONE_WORD_KEYS); + + slavePtr = &interpInfoPtr->slave; + slavePtr->masterInterp = NULL; + slavePtr->slaveEntryPtr = NULL; + slavePtr->slaveInterp = interp; + slavePtr->interpCmd = NULL; + Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS); + + Tcl_CreateObjCommand(interp, "interp", Tcl_InterpObjCmd, 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, interp) + ClientData clientData; /* Ignored. */ + Tcl_Interp *interp; /* Interp being deleted. All commands for + * slave interps should already be deleted. */ +{ + InterpInfo *interpInfoPtr; + Slave *slavePtr; + Master *masterPtr; + Tcl_HashSearch hSearch; + Tcl_HashEntry *hPtr; + Target *targetPtr; + + interpInfoPtr = (InterpInfo *) ((Interp *) interp)->interpInfo; + + /* + * There shouldn't be any commands left. + */ + + masterPtr = &interpInfoPtr->master; + if (masterPtr->slaveTable.numEntries != 0) { + 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. + */ + + hPtr = Tcl_FirstHashEntry(&masterPtr->targetTable, &hSearch); + while (hPtr != NULL) { + targetPtr = (Target *) Tcl_GetHashValue(hPtr); + Tcl_DeleteCommandFromToken(targetPtr->slaveInterp, + targetPtr->slaveCmd); + hPtr = Tcl_NextHashEntry(&hSearch); + } + Tcl_DeleteHashTable(&masterPtr->targetTable); + + 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) { + panic("InterpInfoDeleteProc: still exist aliases"); + } + Tcl_DeleteHashTable(&slavePtr->aliasTable); + + ckfree((char *) interpInfoPtr); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_InterpObjCmd -- + * + * This procedure 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, interp, objc, objv) + ClientData clientData; /* Unused. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + int index; + static char *options[] = { + "alias", "aliases", "create", "delete", + "eval", "exists", "expose", "hide", + "hidden", "issafe", "invokehidden", "marktrusted", + "slaves", "share", "target", "transfer", + NULL + }; + enum option { + OPT_ALIAS, OPT_ALIASES, OPT_CREATE, OPT_DELETE, + OPT_EVAL, OPT_EXISTS, OPT_EXPOSE, OPT_HIDE, + OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHID, OPT_MARKTRUSTED, + 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 *slaveInterp, *masterInterp; + + if (objc < 4) { + aliasArgs: + Tcl_WrongNumArgs(interp, 2, objv, + "slavePath slaveCmd ?masterPath masterCmd? ?args ..?"); + return TCL_ERROR; + } + slaveInterp = GetInterp(interp, objv[2]); + if (slaveInterp == (Tcl_Interp *) NULL) { + return TCL_ERROR; + } + if (objc == 4) { + return AliasDescribe(interp, slaveInterp, objv[3]); + } + if ((objc == 5) && (Tcl_GetString(objv[4])[0] == '\0')) { + return AliasDelete(interp, slaveInterp, objv[3]); + } + if (objc > 5) { + masterInterp = GetInterp(interp, objv[4]); + if (masterInterp == (Tcl_Interp *) NULL) { + return TCL_ERROR; + } + if (Tcl_GetString(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: { + Tcl_Interp *slaveInterp; + + slaveInterp = GetInterp2(interp, objc, objv); + if (slaveInterp == NULL) { + return TCL_ERROR; + } + return AliasList(interp, slaveInterp); + } + case OPT_CREATE: { + int i, last, safe; + Tcl_Obj *slavePtr; + char buf[16 + TCL_INTEGER_SPACE]; + static char *options[] = { + "-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], options, "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; + } + 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_DELETE: { + int i; + InterpInfo *iiPtr; + Tcl_Interp *slaveInterp; + + for (i = 2; i < objc; i++) { + slaveInterp = GetInterp(interp, objv[i]); + if (slaveInterp == NULL) { + return TCL_ERROR; + } else if (slaveInterp == interp) { + Tcl_ResetResult(interp); + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "cannot delete the current interpreter", + (char *) NULL); + return TCL_ERROR; + } + iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo; + Tcl_DeleteCommandFromToken(iiPtr->slave.masterInterp, + iiPtr->slave.interpCmd); + } + return TCL_OK; + } + case OPT_EVAL: { + Tcl_Interp *slaveInterp; + + 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; + Tcl_Interp *slaveInterp; + + exists = 1; + slaveInterp = GetInterp2(interp, objc, objv); + if (slaveInterp == NULL) { + if (objc > 3) { + return TCL_ERROR; + } + Tcl_ResetResult(interp); + exists = 0; + } + Tcl_SetIntObj(Tcl_GetObjResult(interp), exists); + return TCL_OK; + } + case OPT_EXPOSE: { + Tcl_Interp *slaveInterp; + + 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: { + Tcl_Interp *slaveInterp; /* A slave. */ + + if ((objc < 4) || (objc > 5)) { + Tcl_WrongNumArgs(interp, 2, objv, + "path cmdName ?hiddenCmdName?"); + return TCL_ERROR; + } + slaveInterp = GetInterp(interp, objv[2]); + if (slaveInterp == (Tcl_Interp *) NULL) { + return TCL_ERROR; + } + return SlaveHide(interp, slaveInterp, objc - 3, objv + 3); + } + case OPT_HIDDEN: { + Tcl_Interp *slaveInterp; /* A slave. */ + + slaveInterp = GetInterp2(interp, objc, objv); + if (slaveInterp == NULL) { + return TCL_ERROR; + } + return SlaveHidden(interp, slaveInterp); + } + case OPT_ISSAFE: { + Tcl_Interp *slaveInterp; + + slaveInterp = GetInterp2(interp, objc, objv); + if (slaveInterp == NULL) { + return TCL_ERROR; + } + Tcl_SetIntObj(Tcl_GetObjResult(interp), Tcl_IsSafe(slaveInterp)); + return TCL_OK; + } + case OPT_INVOKEHID: { + int i, index, global; + Tcl_Interp *slaveInterp; + static char *hiddenOptions[] = { + "-global", "--", NULL + }; + enum hiddenOption { + OPT_GLOBAL, OPT_LAST + }; + + global = 0; + for (i = 3; i < objc; i++) { + if (Tcl_GetString(objv[i])[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, + "option", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == OPT_GLOBAL) { + global = 1; + } else { + i++; + break; + } + } + if (objc - i < 1) { + Tcl_WrongNumArgs(interp, 2, objv, + "path ?-global? ?--? cmd ?arg ..?"); + return TCL_ERROR; + } + slaveInterp = GetInterp(interp, objv[2]); + if (slaveInterp == (Tcl_Interp *) NULL) { + return TCL_ERROR; + } + return SlaveInvokeHidden(interp, slaveInterp, global, objc - i, + objv + i); + } + case OPT_MARKTRUSTED: { + Tcl_Interp *slaveInterp; + + 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_SLAVES: { + Tcl_Interp *slaveInterp; + 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_GetObjResult(interp); + 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)); + } + return TCL_OK; + } + case OPT_SHARE: { + Tcl_Interp *slaveInterp; /* A slave. */ + Tcl_Interp *masterInterp; /* Its master. */ + 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, Tcl_GetString(objv[3]), + NULL); + if (chan == NULL) { + TclTransferResult(masterInterp, TCL_OK, interp); + return TCL_ERROR; + } + slaveInterp = GetInterp(interp, objv[4]); + if (slaveInterp == NULL) { + return TCL_ERROR; + } + Tcl_RegisterChannel(slaveInterp, chan); + return TCL_OK; + } + case OPT_TARGET: { + Tcl_Interp *slaveInterp; + InterpInfo *iiPtr; + Tcl_HashEntry *hPtr; + Alias *aliasPtr; + 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 = Tcl_GetString(objv[3]); + + iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo; + hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName); + if (hPtr == NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "alias \"", aliasName, "\" in path \"", + Tcl_GetString(objv[2]), "\" not found", + (char *) NULL); + return TCL_ERROR; + } + aliasPtr = (Alias *) Tcl_GetHashValue(hPtr); + if (Tcl_GetInterpPath(interp, aliasPtr->targetInterp) != TCL_OK) { + Tcl_ResetResult(interp); + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "target interpreter for alias \"", aliasName, + "\" in path \"", Tcl_GetString(objv[2]), + "\" is not my descendant", (char *) NULL); + return TCL_ERROR; + } + return TCL_OK; + } + case OPT_TRANSFER: { + Tcl_Interp *slaveInterp; /* A slave. */ + Tcl_Interp *masterInterp; /* Its master. */ + 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, Tcl_GetString(objv[3]), NULL); + if (chan == NULL) { + TclTransferResult(masterInterp, TCL_OK, interp); + return TCL_ERROR; + } + slaveInterp = GetInterp(interp, objv[4]); + if (slaveInterp == NULL) { + return TCL_ERROR; + } + Tcl_RegisterChannel(slaveInterp, chan); + if (Tcl_UnregisterChannel(masterInterp, chan) != TCL_OK) { + TclTransferResult(masterInterp, TCL_OK, interp); + 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(interp, objc, objv) + 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(slaveInterp, slaveCmd, targetInterp, targetCmd, argc, argv) + Tcl_Interp *slaveInterp; /* Interpreter for source command. */ + char *slaveCmd; /* Command to install in slave. */ + Tcl_Interp *targetInterp; /* Interpreter for target command. */ + char *targetCmd; /* Name of target command. */ + int argc; /* How many additional arguments? */ + char **argv; /* These are the additional args. */ +{ + Tcl_Obj *slaveObjPtr, *targetObjPtr; + Tcl_Obj **objv; + int i; + int result; + + objv = (Tcl_Obj **) ckalloc((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]); + } + ckfree((char *) 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(slaveInterp, slaveCmd, targetInterp, targetCmd, objc, objv) + Tcl_Interp *slaveInterp; /* Interpreter for source command. */ + char *slaveCmd; /* Command to install in slave. */ + Tcl_Interp *targetInterp; /* Interpreter for target command. */ + 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(interp, aliasName, targetInterpPtr, targetNamePtr, argcPtr, + argvPtr) + Tcl_Interp *interp; /* Interp to start search from. */ + char *aliasName; /* Name of alias to find. */ + Tcl_Interp **targetInterpPtr; /* (Return) target interpreter. */ + char **targetNamePtr; /* (Return) name of target command. */ + int *argcPtr; /* (Return) count of addnl args. */ + char ***argvPtr; /* (Return) additional arguments. */ +{ + InterpInfo *iiPtr; + Tcl_HashEntry *hPtr; + Alias *aliasPtr; + int i, objc; + Tcl_Obj **objv; + + iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo; + hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName); + if (hPtr == NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "alias \"", aliasName, "\" not found", (char *) NULL); + return TCL_ERROR; + } + aliasPtr = (Alias *) Tcl_GetHashValue(hPtr); + Tcl_ListObjGetElements(NULL, aliasPtr->prefixPtr, &objc, &objv); + + if (targetInterpPtr != NULL) { + *targetInterpPtr = aliasPtr->targetInterp; + } + if (targetNamePtr != NULL) { + *targetNamePtr = Tcl_GetString(objv[0]); + } + if (argcPtr != NULL) { + *argcPtr = objc - 1; + } + if (argvPtr != NULL) { + *argvPtr = (char **) ckalloc((unsigned) sizeof(char *) * (objc - 1)); + for (i = 1; i < objc; i++) { + *argvPtr[i - 1] = Tcl_GetString(objv[i]); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_ObjGetAlias -- + * + * Object version: Gets information about an alias. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_GetAliasObj(interp, aliasName, targetInterpPtr, targetNamePtr, objcPtr, + objvPtr) + Tcl_Interp *interp; /* Interp to start search from. */ + char *aliasName; /* Name of alias to find. */ + Tcl_Interp **targetInterpPtr; /* (Return) target interpreter. */ + char **targetNamePtr; /* (Return) name of target command. */ + int *objcPtr; /* (Return) count of addnl args. */ + Tcl_Obj ***objvPtr; /* (Return) additional args. */ +{ + InterpInfo *iiPtr; + Tcl_HashEntry *hPtr; + Alias *aliasPtr; + int objc; + Tcl_Obj **objv; + + iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo; + hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName); + if (hPtr == (Tcl_HashEntry *) NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "alias \"", aliasName, "\" not found", (char *) NULL); + return TCL_ERROR; + } + aliasPtr = (Alias *) Tcl_GetHashValue(hPtr); + Tcl_ListObjGetElements(NULL, aliasPtr->prefixPtr, &objc, &objv); + + if (targetInterpPtr != (Tcl_Interp **) NULL) { + *targetInterpPtr = aliasPtr->targetInterp; + } + if (targetNamePtr != (char **) NULL) { + *targetNamePtr = Tcl_GetString(objv[0]); + } + if (objcPtr != (int *) NULL) { + *objcPtr = objc - 1; + } + if (objvPtr != (Tcl_Obj ***) NULL) { + *objvPtr = objv + 1; + } + return TCL_OK; +} /* *---------------------------------------------------------------------- * * TclPreventAliasLoop -- @@ -270,11 +1041,11 @@ /* * If we are not creating or renaming an alias, then it is * always OK to create or rename the command. */ - if (cmdPtr->objProc != AliasCmd) { + if (cmdPtr->objProc != AliasObjCmd) { return TCL_OK; } /* * OK, we are dealing with an alias, so traverse the chain of aliases. @@ -283,38 +1054,42 @@ */ aliasPtr = (Alias *) cmdPtr->objClientData; nextAliasPtr = aliasPtr; while (1) { + int objc; + Tcl_Obj **objv; /* * If the target of the next alias in the chain is the same as * the source alias, we have a loop. */ + Tcl_ListObjGetElements(NULL, nextAliasPtr->prefixPtr, &objc, &objv); aliasCmd = Tcl_FindCommand(nextAliasPtr->targetInterp, - nextAliasPtr->targetName, + Tcl_GetString(objv[0]), Tcl_GetGlobalNamespace(nextAliasPtr->targetInterp), /*flags*/ 0); if (aliasCmd == (Tcl_Command) NULL) { return TCL_OK; } aliasCmdPtr = (Command *) aliasCmd; if (aliasCmdPtr == cmdPtr) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "cannot define or rename alias \"", aliasPtr->aliasName, - "\": would create a loop", (char *) NULL); + "cannot define or rename alias \"", + Tcl_GetString(aliasPtr->namePtr), + "\": would create a loop", (char *) 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 != AliasCmd) { + if (aliasCmdPtr->objProc != AliasObjCmd) { return TCL_OK; } nextAliasPtr = (Alias *) aliasCmdPtr->objClientData; } @@ -322,32 +1097,1177 @@ } /* *---------------------------------------------------------------------- * - * MarkTrusted -- + * 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(interp, slaveInterp, masterInterp, namePtr, targetNamePtr, + objc, objv) + 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; + int new; + Target *targetPtr; + Slave *slavePtr; + Master *masterPtr; + + aliasPtr = (Alias *) ckalloc((unsigned) sizeof(Alias)); + aliasPtr->namePtr = namePtr; + Tcl_IncrRefCount(aliasPtr->namePtr); + aliasPtr->targetInterp = masterInterp; + aliasPtr->prefixPtr = Tcl_NewListObj(1, &targetNamePtr); + Tcl_ListObjReplace(NULL, aliasPtr->prefixPtr, 1, 0, objc, objv); + Tcl_IncrRefCount(aliasPtr->prefixPtr); + + aliasPtr->slaveCmd = Tcl_CreateObjCommand(slaveInterp, + Tcl_GetString(namePtr), AliasObjCmd, (ClientData) 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->namePtr); + Tcl_DecrRefCount(aliasPtr->prefixPtr); + + cmdPtr = (Command *) aliasPtr->slaveCmd; + cmdPtr->clientData = NULL; + cmdPtr->deleteProc = NULL; + cmdPtr->deleteData = NULL; + Tcl_DeleteCommandFromToken(slaveInterp, aliasPtr->slaveCmd); + + ckfree((char *) aliasPtr); + + /* + * The result was already set by TclPreventAliasLoop. + */ + + return TCL_ERROR; + } + + /* + * Make an entry in the alias table. If it already exists delete + * the alias command. Then retry. + */ + + slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; + while (1) { + Alias *oldAliasPtr; + char *string; + + string = Tcl_GetString(namePtr); + hPtr = Tcl_CreateHashEntry(&slavePtr->aliasTable, string, &new); + if (new != 0) { + break; + } + + oldAliasPtr = (Alias *) Tcl_GetHashValue(hPtr); + Tcl_DeleteCommandFromToken(slaveInterp, oldAliasPtr->slaveCmd); + } + + aliasPtr->aliasEntryPtr = hPtr; + Tcl_SetHashValue(hPtr, (ClientData) 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 = (Target *) ckalloc((unsigned) sizeof(Target)); + targetPtr->slaveCmd = aliasPtr->slaveCmd; + targetPtr->slaveInterp = slaveInterp; + + Tcl_MutexLock(&cntMutex); + masterPtr = &((InterpInfo *) ((Interp *) masterInterp)->interpInfo)->master; + do { + hPtr = Tcl_CreateHashEntry(&masterPtr->targetTable, + (char *) aliasCounter, &new); + aliasCounter++; + } while (new == 0); + Tcl_MutexUnlock(&cntMutex); + + Tcl_SetHashValue(hPtr, (ClientData) targetPtr); + aliasPtr->targetEntryPtr = hPtr; + + Tcl_SetObjResult(interp, namePtr); + 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(interp, slaveInterp, namePtr) + Tcl_Interp *interp; /* Interpreter for result & errors. */ + Tcl_Interp *slaveInterp; /* Interpreter containing alias. */ + Tcl_Obj *namePtr; /* Name of alias to describe. */ +{ + 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, Tcl_GetString(namePtr)); + if (hPtr == NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "alias \"", + Tcl_GetString(namePtr), "\" not found", NULL); + return TCL_ERROR; + } + aliasPtr = (Alias *) 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(interp, slaveInterp, namePtr) + 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; + + /* + * 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 = (Alias *) Tcl_GetHashValue(hPtr); + Tcl_SetObjResult(interp, aliasPtr->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(interp, slaveInterp) + Tcl_Interp *interp; /* Interp for data return. */ + Tcl_Interp *slaveInterp; /* Interp whose aliases to compute. */ +{ + Tcl_HashEntry *entryPtr; + Tcl_HashSearch hashSearch; + Tcl_Obj *resultPtr; + Alias *aliasPtr; + Slave *slavePtr; + + slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; + resultPtr = Tcl_GetObjResult(interp); + + entryPtr = Tcl_FirstHashEntry(&slavePtr->aliasTable, &hashSearch); + for ( ; entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&hashSearch)) { + aliasPtr = (Alias *) Tcl_GetHashValue(entryPtr); + Tcl_ListObjAppendElement(NULL, resultPtr, aliasPtr->namePtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * AliasObjCmd -- + * + * This is the procedure that services invocations of aliases in a + * slave interpreter. One such command exists for each alias. When + * invoked, this procedure 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 +AliasObjCmd(clientData, interp, objc, objv) + ClientData clientData; /* Alias record. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument vector. */ +{ + Tcl_Interp *targetInterp; + Alias *aliasPtr; + int result, prefc, cmdc; + Tcl_Obj *cmdPtr; + Tcl_Obj **prefv, **cmdv; + + aliasPtr = (Alias *) clientData; + targetInterp = aliasPtr->targetInterp; + + Tcl_Preserve((ClientData) targetInterp); + + ((Interp *) targetInterp)->numLevels++; + + Tcl_ResetResult(targetInterp); + Tcl_AllowExceptions(targetInterp); + + /* + * Append the arguments to the command prefix and invoke the command + * in the target interp's global namespace. + */ + + Tcl_ListObjGetElements(NULL, aliasPtr->prefixPtr, &prefc, &prefv); + cmdPtr = Tcl_NewListObj(prefc, prefv); + Tcl_ListObjReplace(NULL, cmdPtr, prefc, 0, objc - 1, objv + 1); + Tcl_ListObjGetElements(NULL, cmdPtr, &cmdc, &cmdv); + result = TclObjInvoke(targetInterp, cmdc, cmdv, + TCL_INVOKE_NO_TRACEBACK); + Tcl_DecrRefCount(cmdPtr); + + ((Interp *) targetInterp)->numLevels--; + + /* + * Check if we are at the bottom of the stack for the target interpreter. + * If so, check for special return codes. + */ + + if (((Interp *) targetInterp)->numLevels == 0) { + if (result == TCL_RETURN) { + result = TclUpdateReturnInfo((Interp *) targetInterp); + } + if ((result != TCL_OK) && (result != TCL_ERROR)) { + Tcl_ResetResult(targetInterp); + if (result == TCL_BREAK) { + Tcl_SetObjResult(targetInterp, + Tcl_NewStringObj("invoked \"break\" outside of a loop", + -1)); + } else if (result == TCL_CONTINUE) { + Tcl_SetObjResult(targetInterp, + Tcl_NewStringObj( + "invoked \"continue\" outside of a loop", + -1)); + } else { + char buf[32 + TCL_INTEGER_SPACE]; + + sprintf(buf, "command returned bad code: %d", result); + Tcl_SetObjResult(targetInterp, Tcl_NewStringObj(buf, -1)); + } + result = TCL_ERROR; + } + } + + TclTransferResult(targetInterp, result, interp); + + Tcl_Release((ClientData) targetInterp); + return result; +} + +/* + *---------------------------------------------------------------------- + * + * AliasObjCmdDeleteProc -- + * + * Is invoked when an alias command is deleted in a slave. Cleans up + * all storage associated with this alias. + * + * Results: + * None. + * + * Side effects: + * Deletes the alias record and its entry in the alias table for + * the interpreter. + * + *---------------------------------------------------------------------- + */ + +static void +AliasObjCmdDeleteProc(clientData) + ClientData clientData; /* The alias record for this alias. */ +{ + Alias *aliasPtr; + Target *targetPtr; + + aliasPtr = (Alias *) clientData; + + Tcl_DecrRefCount(aliasPtr->namePtr); + Tcl_DecrRefCount(aliasPtr->prefixPtr); + Tcl_DeleteHashEntry(aliasPtr->aliasEntryPtr); + + targetPtr = (Target *) Tcl_GetHashValue(aliasPtr->targetEntryPtr); + ckfree((char *) targetPtr); + Tcl_DeleteHashEntry(aliasPtr->targetEntryPtr); + + ckfree((char *) 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(interp, slavePath, isSafe) + Tcl_Interp *interp; /* Interpreter to start search at. */ + 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(interp, slavePath) + Tcl_Interp *interp; /* Interpreter to start search from. */ + 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(interp) + Tcl_Interp *interp; /* Get the master of this interpreter. */ +{ + Slave *slavePtr; /* Slave record of this interpreter. */ + + if (interp == (Tcl_Interp *) NULL) { + return NULL; + } + slavePtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->slave; + return slavePtr->masterInterp; +} + +/* + *---------------------------------------------------------------------- + * + * 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(askingInterp, targetInterp) + Tcl_Interp *askingInterp; /* Interpreter to start search from. */ + Tcl_Interp *targetInterp; /* Interpreter to find. */ +{ + InterpInfo *iiPtr; + + if (targetInterp == askingInterp) { + 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_AppendElement(askingInterp, + Tcl_GetHashKey(&iiPtr->master.slaveTable, + iiPtr->slave.slaveEntryPtr)); + 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(interp, pathPtr) + 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 (Tcl_ListObjGetElements(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, + Tcl_GetString(objv[i])); + if (hPtr == NULL) { + searchInterp = NULL; + break; + } + slavePtr = (Slave *) Tcl_GetHashValue(hPtr); + searchInterp = slavePtr->slaveInterp; + if (searchInterp == NULL) { + break; + } + } + if (searchInterp == NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "could not find interpreter \"", + Tcl_GetString(pathPtr), "\"", (char *) NULL); + } + return searchInterp; +} + +/* + *---------------------------------------------------------------------- + * + * 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(interp, pathPtr, safe) + 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; + char *path; + int new, objc; + Tcl_Obj **objv; + + if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) { + return NULL; + } + if (objc < 2) { + masterInterp = interp; + path = Tcl_GetString(pathPtr); + } else { + Tcl_Obj *objPtr; + + objPtr = Tcl_NewListObj(objc - 1, objv); + masterInterp = GetInterp(interp, objPtr); + Tcl_DecrRefCount(objPtr); + if (masterInterp == NULL) { + return NULL; + } + path = Tcl_GetString(objv[objc - 1]); + } + if (safe == 0) { + safe = Tcl_IsSafe(masterInterp); + } + + masterInfoPtr = (InterpInfo *) ((Interp *) masterInterp)->interpInfo; + hPtr = Tcl_CreateHashEntry(&masterInfoPtr->master.slaveTable, path, &new); + if (new == 0) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "interpreter named \"", path, + "\" already exists, cannot create", (char *) NULL); + return NULL; + } + + slaveInterp = Tcl_CreateInterp(); + slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; + slavePtr->masterInterp = masterInterp; + slavePtr->slaveEntryPtr = hPtr; + slavePtr->slaveInterp = slaveInterp; + slavePtr->interpCmd = Tcl_CreateObjCommand(masterInterp, path, + SlaveObjCmd, (ClientData) slaveInterp, SlaveObjCmdDeleteProc); + Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS); + Tcl_SetHashValue(hPtr, (ClientData) 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; + } + } + return slaveInterp; + + error: + TclTransferResult(slaveInterp, TCL_ERROR, interp); + 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, interp, objc, objv) + ClientData clientData; /* Slave interpreter. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + Tcl_Interp *slaveInterp; + int index; + static char *options[] = { + "alias", "aliases", "eval", "expose", + "hide", "hidden", "issafe", "invokehidden", + "marktrusted", NULL + }; + enum options { + OPT_ALIAS, OPT_ALIASES, OPT_EVAL, OPT_EXPOSE, + OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHIDDEN, + OPT_MARKTRUSTED + }; + + slaveInterp = (Tcl_Interp *) clientData; + if (slaveInterp == NULL) { + 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 == 3) { + return AliasDescribe(interp, slaveInterp, objv[2]); + } + if (Tcl_GetString(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? ?args..?"); + return TCL_ERROR; + } + case OPT_ALIASES: { + return AliasList(interp, slaveInterp); + } + 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: { + Tcl_SetIntObj(Tcl_GetObjResult(interp), Tcl_IsSafe(slaveInterp)); + return TCL_OK; + } + case OPT_INVOKEHIDDEN: { + int global, i, index; + static char *hiddenOptions[] = { + "-global", "--", NULL + }; + enum hiddenOption { + OPT_GLOBAL, OPT_LAST + }; + global = 0; + for (i = 2; i < objc; i++) { + if (Tcl_GetString(objv[i])[0] != '-') { + break; + } + if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, + "option", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == OPT_GLOBAL) { + global = 1; + } else { + i++; + break; + } + } + if (objc - i < 1) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-global? ?--? cmd ?arg ..?"); + return TCL_ERROR; + } + return SlaveInvokeHidden(interp, slaveInterp, global, objc - i, + objv + i); + } + case OPT_MARKTRUSTED: { + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; + } + return SlaveMarkTrusted(interp, slaveInterp); + } + } + + 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 clientData; /* The SlaveRecord for the command. */ +{ + Slave *slavePtr; /* Interim storage for Slave record. */ + Tcl_Interp *slaveInterp; /* And for a slave interp. */ + + slaveInterp = (Tcl_Interp *) clientData; + 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); + } +} + +/* + *---------------------------------------------------------------------- + * + * 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(interp, slaveInterp, objc, objv) + 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; + Tcl_Obj *objPtr; + + Tcl_Preserve((ClientData) slaveInterp); + Tcl_AllowExceptions(slaveInterp); + + if (objc == 1) { + result = Tcl_EvalObjEx(slaveInterp, objv[0], 0); + } else { + objPtr = Tcl_ConcatObj(objc, objv); + Tcl_IncrRefCount(objPtr); + result = Tcl_EvalObjEx(slaveInterp, objPtr, 0); + Tcl_DecrRefCount(objPtr); + } + TclTransferResult(slaveInterp, result, interp); + + Tcl_Release((ClientData) 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(interp, slaveInterp, objc, objv) + 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. */ +{ + char *name; + + if (Tcl_IsSafe(interp)) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "permission denied: safe interpreter cannot expose commands", + (char *) NULL); + return TCL_ERROR; + } + + name = Tcl_GetString(objv[(objc == 1) ? 0 : 1]); + if (Tcl_ExposeCommand(slaveInterp, Tcl_GetString(objv[0]), + name) != TCL_OK) { + TclTransferResult(slaveInterp, TCL_ERROR, interp); + return TCL_ERROR; + } + 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(interp, slaveInterp, objc, objv) + 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. */ +{ + char *name; + + if (Tcl_IsSafe(interp)) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "permission denied: safe interpreter cannot hide commands", + (char *) NULL); + return TCL_ERROR; + } + + name = Tcl_GetString(objv[(objc == 1) ? 0 : 1]); + if (Tcl_HideCommand(slaveInterp, Tcl_GetString(objv[0]), + name) != TCL_OK) { + TclTransferResult(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(interp, slaveInterp) + Tcl_Interp *interp; /* Interp for data return. */ + Tcl_Interp *slaveInterp; /* Interp whose hidden commands to query. */ +{ + Tcl_Obj *listObjPtr; /* Local object pointer. */ + Tcl_HashTable *hTblPtr; /* For local searches. */ + Tcl_HashEntry *hPtr; /* For local searches. */ + Tcl_HashSearch hSearch; /* For local searches. */ + + listObjPtr = Tcl_GetObjResult(interp); + hTblPtr = ((Interp *) slaveInterp)->hiddenCmdTablePtr; + if (hTblPtr != (Tcl_HashTable *) NULL) { + for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); + hPtr != (Tcl_HashEntry *) NULL; + hPtr = Tcl_NextHashEntry(&hSearch)) { + + Tcl_ListObjAppendElement(NULL, listObjPtr, + Tcl_NewStringObj(Tcl_GetHashKey(hTblPtr, hPtr), -1)); + } + } + 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(interp, slaveInterp, global, objc, objv) + Tcl_Interp *interp; /* Interp for error return. */ + Tcl_Interp *slaveInterp; /* The slave interpreter in which command + * will be invoked. */ + int global; /* Non-zero to invoke in global namespace. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + int result; + + if (Tcl_IsSafe(interp)) { + Tcl_SetStringObj(Tcl_GetObjResult(interp), + "not allowed to invoke hidden commands from safe interpreter", + -1); + return TCL_ERROR; + } + + Tcl_Preserve((ClientData) slaveInterp); + Tcl_AllowExceptions(slaveInterp); + + if (global) { + result = TclObjInvokeGlobal(slaveInterp, objc, objv, + TCL_INVOKE_HIDDEN); + } else { + result = TclObjInvoke(slaveInterp, objc, objv, TCL_INVOKE_HIDDEN); + } + + TclTransferResult(slaveInterp, result, interp); + + Tcl_Release((ClientData) slaveInterp); + return result; +} + +/* + *---------------------------------------------------------------------- + * + * SlaveMarkTrusted -- * - * Mark an interpreter as unsafe (i.e. remove the "safe" mark). + * Helper function to mark a slave interpreter as trusted (unsafe). * * Results: * A standard Tcl result. * * Side effects: - * Removes the "safe" mark from an interpreter. + * After this call the hard-wired security checks in the core no + * longer prevent the slave from performing certain operations. * *---------------------------------------------------------------------- */ static int -MarkTrusted(interp) - Tcl_Interp *interp; /* Interpreter to be marked unsafe. */ +SlaveMarkTrusted(interp, slaveInterp) + Tcl_Interp *interp; /* Interp for error return. */ + Tcl_Interp *slaveInterp; /* The slave interpreter which will be + * marked trusted. */ { - Interp *iPtr = (Interp *) interp; - - iPtr->flags &= ~SAFE_INTERP; + if (Tcl_IsSafe(interp)) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "permission denied: safe interpreter cannot mark trusted", + (char *) 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(interp) + Tcl_Interp *interp; /* Is this interpreter "safe" ? */ +{ + Interp *iPtr; + + if (interp == (Tcl_Interp *) NULL) { + return 0; + } + iPtr = (Interp *) interp; + + return ( (iPtr->flags) & SAFE_INTERP ) ? 1 : 0 ; +} /* *---------------------------------------------------------------------- * * Tcl_MakeSafe -- @@ -394,16 +2314,18 @@ */ 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 @@ -427,3408 +2349,7 @@ chan = Tcl_GetStdChannel(TCL_STDERR); if (chan != (Tcl_Channel) NULL) { Tcl_UnregisterChannel(interp, chan); } - 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(interp, masterPtr, path, masterPtrPtr) - Tcl_Interp *interp; /* Interp. to start search from. */ - Master *masterPtr; /* Its master record. */ - char *path; /* The path (name) of interp. to be found. */ - Master **masterPtrPtr; /* (Return) its master record. */ -{ - Tcl_HashEntry *hPtr; /* Search element. */ - Slave *slavePtr; /* Interim slave record. */ - char **argv; /* Split-up path (name) for interp to find. */ - int argc, i; /* Loop indices. */ - Tcl_Interp *searchInterp; /* Interim storage for interp. to find. */ - - if (masterPtrPtr != (Master **) NULL) { - *masterPtrPtr = masterPtr; - } - - if (Tcl_SplitList(interp, path, &argc, &argv) != TCL_OK) { - return (Tcl_Interp *) NULL; - } - - for (searchInterp = interp, i = 0; i < argc; i++) { - - hPtr = Tcl_FindHashEntry(&(masterPtr->slaveTable), argv[i]); - if (hPtr == (Tcl_HashEntry *) NULL) { - ckfree((char *) argv); - return (Tcl_Interp *) NULL; - } - slavePtr = (Slave *) Tcl_GetHashValue(hPtr); - searchInterp = slavePtr->slaveInterp; - if (searchInterp == (Tcl_Interp *) NULL) { - ckfree((char *) argv); - return (Tcl_Interp *) NULL; - } - masterPtr = (Master *) Tcl_GetAssocData(searchInterp, - "tclMasterRecord", NULL); - if (masterPtrPtr != (Master **) NULL) *masterPtrPtr = masterPtr; - if (masterPtr == (Master *) NULL) { - ckfree((char *) argv); - return (Tcl_Interp *) NULL; - } - } - ckfree((char *) argv); - return searchInterp; -} - -/* - *---------------------------------------------------------------------- - * - * CreateSlave -- - * - * 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 * -CreateSlave(interp, masterPtr, slavePath, safe) - Tcl_Interp *interp; /* Interp. to start search from. */ - Master *masterPtr; /* Master record. */ - char *slavePath; /* Path (name) of slave to create. */ - int safe; /* Should we make it "safe"? */ -{ - Tcl_Interp *slaveInterp; /* Ptr to slave interpreter. */ - Tcl_Interp *masterInterp; /* Ptr to master interp for slave. */ - Slave *slavePtr; /* Slave record. */ - Tcl_HashEntry *hPtr; /* Entry into interp hashtable. */ - int new; /* Indicates whether new entry. */ - int argc; /* Count of elements in slavePath. */ - char **argv; /* Elements in slavePath. */ - char *masterPath; /* Path to its master. */ - - if (Tcl_SplitList(interp, slavePath, &argc, &argv) != TCL_OK) { - return (Tcl_Interp *) NULL; - } - - if (argc < 2) { - masterInterp = interp; - if (argc == 1) { - slavePath = argv[0]; - } - } else { - masterPath = Tcl_Merge(argc-1, argv); - masterInterp = GetInterp(interp, masterPtr, masterPath, &masterPtr); - if (masterInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter named \"", masterPath, - "\" not found", (char *) NULL); - ckfree((char *) argv); - ckfree((char *) masterPath); - return (Tcl_Interp *) NULL; - } - ckfree((char *) masterPath); - slavePath = argv[argc-1]; - if (!safe) { - safe = Tcl_IsSafe(masterInterp); - } - } - hPtr = Tcl_CreateHashEntry(&(masterPtr->slaveTable), slavePath, &new); - if (new == 0) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter named \"", slavePath, - "\" already exists, cannot create", (char *) NULL); - ckfree((char *) argv); - return (Tcl_Interp *) NULL; - } - slaveInterp = Tcl_CreateInterp(); - if (slaveInterp == (Tcl_Interp *) NULL) { - panic("CreateSlave: out of memory while creating a new interpreter"); - } - slavePtr = (Slave *) Tcl_GetAssocData(slaveInterp, "tclSlaveRecord", NULL); - slavePtr->masterInterp = masterInterp; - slavePtr->slaveEntry = hPtr; - slavePtr->slaveInterp = slaveInterp; - slavePtr->interpCmd = Tcl_CreateObjCommand(masterInterp, slavePath, - SlaveObjectCmd, (ClientData) slaveInterp, SlaveObjectDeleteProc); - Tcl_InitHashTable(&(slavePtr->aliasTable), TCL_STRING_KEYS); - (void) Tcl_SetAssocData(slaveInterp, "tclSlaveRecord", - SlaveRecordDeleteProc, (ClientData) slavePtr); - Tcl_SetHashValue(hPtr, (ClientData) 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; - } - } - - ckfree((char *) argv); - return slaveInterp; - -error: - - Tcl_AddErrorInfo(interp, Tcl_GetVar2(slaveInterp, "errorInfo", (char *) - NULL, TCL_GLOBAL_ONLY)); - Tcl_SetVar2(interp, "errorCode", (char *) NULL, - Tcl_GetVar2(slaveInterp, "errorCode", (char *) NULL, - TCL_GLOBAL_ONLY), - TCL_GLOBAL_ONLY); - - Tcl_SetObjResult(interp, Tcl_GetObjResult(slaveInterp)); - Tcl_ResetResult(slaveInterp); - - (void) Tcl_DeleteCommand(masterInterp, slavePath); - - ckfree((char *) argv); - return (Tcl_Interp *) NULL; -} - -/* - *---------------------------------------------------------------------- - * - * CreateInterpObject - - * - * Helper function to do the actual work of creating a new interpreter - * and an object command. - * - * Results: - * A Tcl result. - * - * Side effects: - * See user documentation for details. - * - *---------------------------------------------------------------------- - */ - -static int -CreateInterpObject(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Invoking interpreter. */ - Master *masterPtr; /* Master record for same. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* with alias. */ -{ - int safe; /* Create a safe interpreter? */ - int moreFlags; /* Expecting more flag args? */ - char *string; /* Local pointer to object string. */ - char *slavePath; /* Name of slave. */ - char localSlaveName[200]; /* Local area for creating names. */ - int i; /* Loop counter. */ - int len; /* Length of option argument. */ - static int interpCounter = 0; /* Unique id for created names. */ - - moreFlags = 1; - slavePath = NULL; - safe = Tcl_IsSafe(interp); - - if ((objc < 2) || (objc > 5)) { - Tcl_WrongNumArgs(interp, 2, objv, "?-safe? ?--? ?path?"); - return TCL_ERROR; - } - for (i = 2; i < objc; i++) { - string = Tcl_GetStringFromObj(objv[i], &len); - if ((string[0] == '-') && (moreFlags != 0)) { - if ((string[1] == 's') && - (strncmp(string, "-safe", (size_t) len) == 0) && - (len > 1)){ - safe = 1; - } else if ((strncmp(string, "--", (size_t) len) == 0) && - (len > 1)) { - moreFlags = 0; - } else { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "bad option \"", string, "\": should be -safe", - (char *) NULL); - return TCL_ERROR; - } - } else { - slavePath = string; - } - } - if (slavePath == (char *) 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. - */ - - while (1) { - Tcl_CmdInfo cmdInfo; - - sprintf(localSlaveName, "interp%d", interpCounter); - interpCounter++; - if (!(Tcl_GetCommandInfo(interp, localSlaveName, &cmdInfo))) { - break; - } - } - slavePath = localSlaveName; - } - if (CreateSlave(interp, masterPtr, slavePath, safe) != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj(slavePath, -1)); - return TCL_OK; - } else { - /* - * CreateSlave already set the result if there was an error, - * so we do not do it here. - */ - return TCL_ERROR; - } -} - -/* - *---------------------------------------------------------------------- - * - * DeleteOneInterpObject -- - * - * Helper function for DeleteInterpObject. It deals with deleting one - * interpreter at a time. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * Deletes an interpreter and its interpreter object command. - * - *---------------------------------------------------------------------- - */ - -static int -DeleteOneInterpObject(interp, masterPtr, path) - Tcl_Interp *interp; /* Interpreter for reporting errors. */ - Master *masterPtr; /* Interim storage for master record.*/ - char *path; /* Path of interpreter to delete. */ -{ - Slave *slavePtr; /* Interim storage for slave record. */ - Tcl_Interp *masterInterp; /* Master of interp. to delete. */ - Tcl_HashEntry *hPtr; /* Search element. */ - int localArgc; /* Local copy of count of elements in - * path (name) of interp. to delete. */ - char **localArgv; /* Local copy of path. */ - char *slaveName; /* Last component in path. */ - char *masterPath; /* One-before-last component in path.*/ - - if (Tcl_SplitList(interp, path, &localArgc, &localArgv) != TCL_OK) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "bad interpreter path \"", path, "\"", (char *) NULL); - return TCL_ERROR; - } - if (localArgc < 2) { - masterInterp = interp; - if (localArgc == 0) { - slaveName = ""; - } else { - slaveName = localArgv[0]; - } - } else { - masterPath = Tcl_Merge(localArgc-1, localArgv); - masterInterp = GetInterp(interp, masterPtr, masterPath, &masterPtr); - if (masterInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter named \"", masterPath, "\" not found", - (char *) NULL); - ckfree((char *) localArgv); - ckfree((char *) masterPath); - return TCL_ERROR; - } - ckfree((char *) masterPath); - slaveName = localArgv[localArgc-1]; - } - hPtr = Tcl_FindHashEntry(&(masterPtr->slaveTable), slaveName); - if (hPtr == (Tcl_HashEntry *) NULL) { - ckfree((char *) localArgv); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter named \"", path, "\" not found", (char *) NULL); - return TCL_ERROR; - } - slavePtr = (Slave *) Tcl_GetHashValue(hPtr); - if (Tcl_DeleteCommandFromToken(masterInterp, slavePtr->interpCmd) != 0) { - ckfree((char *) localArgv); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter named \"", path, "\" not found", (char *) NULL); - return TCL_ERROR; - } - ckfree((char *) localArgv); - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * DeleteInterpObject -- - * - * Helper function to do the work of deleting zero or more - * interpreters and their interpreter object commands. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * Deletes interpreters and their interpreter object command. - * - *---------------------------------------------------------------------- - */ - -static int -DeleteInterpObject(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Interpreter start search from. */ - Master *masterPtr; /* Interim storage for master record.*/ - int objc; /* Number of arguments in vector. */ - Tcl_Obj *CONST objv[]; /* with alias. */ -{ - int i; - int len; - - for (i = 2; i < objc; i++) { - if (DeleteOneInterpObject(interp, masterPtr, - Tcl_GetStringFromObj(objv[i], &len)) - != TCL_OK) { - return TCL_ERROR; - } - } - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * AliasCreationHelper -- - * - * Helper function to do the work to actually create an alias or - * delete 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 -AliasCreationHelper(curInterp, slaveInterp, masterInterp, masterPtr, - aliasName, targetName, objc, objv) - Tcl_Interp *curInterp; /* Interp that invoked this proc. */ - Tcl_Interp *slaveInterp; /* Interp where alias cmd will live - * or from which alias will be - * deleted. */ - Tcl_Interp *masterInterp; /* Interp where target cmd will be. */ - Master *masterPtr; /* Master record for target interp. */ - char *aliasName; /* Name of alias cmd. */ - char *targetName; /* Name of target cmd. */ - int objc; /* Additional arguments to store */ - Tcl_Obj *CONST objv[]; /* with alias. */ -{ - Alias *aliasPtr; /* Storage for alias data. */ - Alias *tmpAliasPtr; /* Temp storage for alias to delete. */ - Tcl_HashEntry *hPtr; /* Entry into interp hashtable. */ - int i; /* Loop index. */ - int new; /* Is it a new hash entry? */ - Target *targetPtr; /* Maps from target command in master - * to source command in slave. */ - Slave *slavePtr; /* Maps from source command in slave - * to target command in master. */ - - slavePtr = (Slave *) Tcl_GetAssocData(slaveInterp, "tclSlaveRecord", NULL); - - /* - * Slave record should be always present because it is created when - * the interpreter is created. - */ - - if (slavePtr == (Slave *) NULL) { - panic("AliasCreationHelper: could not find slave record"); - } - - if ((targetName == (char *) NULL) || (targetName[0] == '\0')) { - if (objc != 0) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(curInterp), - "malformed command: should be", - " \"alias ", aliasName, " {}\"", (char *) NULL); - return TCL_ERROR; - } - - return DeleteAlias(curInterp, slaveInterp, aliasName); - } - - aliasPtr = (Alias *) ckalloc((unsigned) sizeof(Alias)); - aliasPtr->aliasName = (char *) ckalloc((unsigned) strlen(aliasName)+1); - aliasPtr->targetName = (char *) ckalloc((unsigned) strlen(targetName)+1); - strcpy(aliasPtr->aliasName, aliasName); - strcpy(aliasPtr->targetName, targetName); - aliasPtr->targetInterp = masterInterp; - - aliasPtr->objv = NULL; - aliasPtr->objc = objc; - - if (aliasPtr->objc > 0) { - aliasPtr->objv = - (Tcl_Obj **) ckalloc((unsigned) sizeof(Tcl_Obj *) * - aliasPtr->objc); - for (i = 0; i < objc; i++) { - aliasPtr->objv[i] = objv[i]; - Tcl_IncrRefCount(objv[i]); - } - } - - aliasPtr->slaveCmd = Tcl_CreateObjCommand(slaveInterp, aliasName, - AliasCmd, (ClientData) aliasPtr, AliasCmdDeleteProc); - - if (TclPreventAliasLoop(curInterp, 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 = (Command*) aliasPtr->slaveCmd; - cmdPtr->clientData = NULL; - cmdPtr->deleteProc = NULL; - cmdPtr->deleteData = NULL; - Tcl_DeleteCommandFromToken(slaveInterp, aliasPtr->slaveCmd); - - for (i = 0; i < objc; i++) { - Tcl_DecrRefCount(aliasPtr->objv[i]); - } - if (aliasPtr->objv != (Tcl_Obj *CONST *) NULL) { - ckfree((char *) aliasPtr->objv); - } - ckfree(aliasPtr->aliasName); - ckfree(aliasPtr->targetName); - ckfree((char *) aliasPtr); - - /* - * The result was already set by TclPreventAliasLoop. - */ - - return TCL_ERROR; - } - - /* - * Make an entry in the alias table. If it already exists delete - * the alias command. Then retry. - */ - - do { - hPtr = Tcl_CreateHashEntry(&(slavePtr->aliasTable), aliasName, &new); - if (!new) { - tmpAliasPtr = (Alias *) Tcl_GetHashValue(hPtr); - (void) Tcl_DeleteCommandFromToken(slaveInterp, - tmpAliasPtr->slaveCmd); - - /* - * The hash entry should be deleted by the Tcl_DeleteCommand - * above, in its command deletion callback (most likely this - * will be AliasCmdDeleteProc, which does the deletion). - */ - } - } while (new == 0); - aliasPtr->aliasEntry = hPtr; - Tcl_SetHashValue(hPtr, (ClientData) 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 = (Target *) ckalloc((unsigned) sizeof(Target)); - targetPtr->slaveCmd = aliasPtr->slaveCmd; - targetPtr->slaveInterp = slaveInterp; - - do { - hPtr = Tcl_CreateHashEntry(&(masterPtr->targetTable), - (char *) aliasCounter, &new); - aliasCounter++; - } while (new == 0); - - Tcl_SetHashValue(hPtr, (ClientData) targetPtr); - - aliasPtr->targetEntry = hPtr; - - /* - * Make sure we clear out the object result when setting the string - * result. - */ - - Tcl_SetObjResult(curInterp, Tcl_NewStringObj(aliasPtr->aliasName, -1)); - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * InterpAliasesHelper -- - * - * Computes a list of aliases defined in an interpreter. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -InterpAliasesHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Invoking interpreter. */ - Master *masterPtr; /* Master record for current interp. */ - int objc; /* How many arguments? */ - Tcl_Obj *CONST objv[]; /* Actual arguments. */ -{ - Tcl_Interp *slaveInterp; /* A slave. */ - Slave *slavePtr; /* Record for slave interp. */ - Tcl_HashEntry *hPtr; /* Search variable. */ - Tcl_HashSearch hSearch; /* Iteration variable. */ - int len; /* Dummy length variable. */ - Tcl_Obj *listObjPtr, *elemObjPtr; /* Local object pointers. */ - - if ((objc != 2) && (objc != 3)) { - Tcl_WrongNumArgs(interp, 2, objv, "?path?"); - return TCL_ERROR; - } - if (objc == 3) { - slaveInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), NULL); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", Tcl_GetStringFromObj(objv[2], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - } else { - slaveInterp = interp; - } - slavePtr = (Slave *) Tcl_GetAssocData(slaveInterp, - "tclSlaveRecord", NULL); - if (slavePtr == (Slave *) NULL) { - return TCL_OK; - } - - /* - * Build a list to return the aliases: - */ - - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - for (hPtr = Tcl_FirstHashEntry(&(slavePtr->aliasTable), &hSearch); - hPtr != NULL; - hPtr = Tcl_NextHashEntry(&hSearch)) { - - elemObjPtr = Tcl_NewStringObj( - Tcl_GetHashKey(&(slavePtr->aliasTable), hPtr), -1); - Tcl_ListObjAppendElement(interp, listObjPtr, elemObjPtr); - } - Tcl_SetObjResult(interp, listObjPtr); - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * InterpAliasHelper - - * - * Handles the different forms of the "interp alias" command: - * - interp alias slavePath aliasName - * Describes an alias. - * - interp alias slavePath aliasName {} - * Deletes an alias. - * - interp alias slavePath srcCmd masterPath targetCmd args... - * Creates an alias. - * - * Results: - * A Tcl result. - * - * Side effects: - * See user documentation for details. - * - *---------------------------------------------------------------------- - */ - -static int -InterpAliasHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for current interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - Tcl_Interp *slaveInterp, /* Interpreters used when */ - *masterInterp; /* creating an alias btn siblings. */ - Master *masterMasterPtr; /* Master record for master interp. */ - int len; - - if (objc < 4) { - Tcl_WrongNumArgs(interp, 2, objv, - "slavePath slaveCmd masterPath masterCmd ?args ..?"); - return TCL_ERROR; - } - slaveInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), NULL); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "could not find interpreter \"", - Tcl_GetStringFromObj(objv[2], &len), "\"", - (char *) NULL); - return TCL_ERROR; - } - if (objc == 4) { - return DescribeAlias(interp, slaveInterp, - Tcl_GetStringFromObj(objv[3], &len)); - } - if (objc == 5 && strcmp(Tcl_GetStringFromObj(objv[4], &len), "") == 0) { - return DeleteAlias(interp, slaveInterp, - Tcl_GetStringFromObj(objv[3], &len)); - } - if (objc < 6) { - Tcl_WrongNumArgs(interp, 2, objv, - "slavePath slaveCmd masterPath masterCmd ?args ..?"); - return TCL_ERROR; - } - masterInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[4], &len), &masterMasterPtr); - if (masterInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "could not find interpreter \"", - Tcl_GetStringFromObj(objv[4], &len), "\"", (char *) NULL); - return TCL_ERROR; - } - return AliasCreationHelper(interp, slaveInterp, masterInterp, - masterMasterPtr, Tcl_GetStringFromObj(objv[3], &len), - Tcl_GetStringFromObj(objv[5], &len), - objc-6, objv+6); -} - -/* - *---------------------------------------------------------------------- - * - * InterpExistsHelper -- - * - * Computes whether a named interpreter exists or not. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -InterpExistsHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for current interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - Tcl_Obj *objPtr; - int len; - - if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?path?"); - return TCL_ERROR; - } - if (objc == 3) { - if (GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), NULL) == - (Tcl_Interp *) NULL) { - objPtr = Tcl_NewIntObj(0); - } else { - objPtr = Tcl_NewIntObj(1); - } - } else { - objPtr = Tcl_NewIntObj(1); - } - Tcl_SetObjResult(interp, objPtr); - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * InterpEvalHelper -- - * - * Helper function to handle all the details of evaluating a - * command in another interpreter. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * Whatever the command itself does. - * - *---------------------------------------------------------------------- - */ - -static int -InterpEvalHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for current interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - Tcl_Interp *slaveInterp; /* A slave. */ - Interp *iPtr; /* Internal data type for slave. */ - int len; /* Dummy length variable. */ - int result; - Tcl_Obj *namePtr, *objPtr; /* Local object pointer. */ - char *string; - - if (objc < 4) { - Tcl_WrongNumArgs(interp, 2, objv, "path arg ?arg ...?"); - return TCL_ERROR; - } - slaveInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), NULL); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter named \"", Tcl_GetStringFromObj(objv[2], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - objPtr = Tcl_ConcatObj(objc-3, objv+3); - Tcl_IncrRefCount(objPtr); - - Tcl_Preserve((ClientData) slaveInterp); - result = Tcl_EvalObj(slaveInterp, objPtr); - - Tcl_DecrRefCount(objPtr); - - /* - * Now make the result and any error information accessible. We - * have to be careful because the slave interpreter and the current - * interpreter can be the same - do not destroy the result.. This - * can happen if an interpreter contains an alias which is directed - * at a target command in the same interpreter. - */ - - if (interp != slaveInterp) { - if (result == TCL_ERROR) { - - /* - * An error occurred, so transfer error information from - * the target interpreter back to our interpreter. - */ - - iPtr = (Interp *) slaveInterp; - if (!(iPtr->flags & ERR_ALREADY_LOGGED)) { - Tcl_AddErrorInfo(slaveInterp, ""); - } - iPtr->flags &= (~(ERR_ALREADY_LOGGED)); - - Tcl_ResetResult(interp); - namePtr = Tcl_NewStringObj("errorInfo", -1); - objPtr = Tcl_ObjGetVar2(slaveInterp, namePtr, - (Tcl_Obj *) NULL, TCL_GLOBAL_ONLY); - string = Tcl_GetStringFromObj(objPtr, &len); - Tcl_AddObjErrorInfo(interp, string, len); - Tcl_SetVar2(interp, "errorCode", (char *) NULL, - Tcl_GetVar2(slaveInterp, "errorCode", (char *) - NULL, TCL_GLOBAL_ONLY), - TCL_GLOBAL_ONLY); - Tcl_DecrRefCount(namePtr); - } - - /* - * Move the result object from one interpreter to the - * other. - */ - - Tcl_SetObjResult(interp, Tcl_GetObjResult(slaveInterp)); - Tcl_ResetResult(slaveInterp); - - } - Tcl_Release((ClientData) slaveInterp); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * InterpExposeHelper -- - * - * Helper function to handle the details of exposing a command in - * another interpreter. - * - * Results: - * Standard Tcl result. - * - * Side effects: - * Exposes a command. From now on the command can be called by scripts - * in the interpreter in which it was exposed. - * - *---------------------------------------------------------------------- - */ - -static int -InterpExposeHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for current interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - Tcl_Interp *slaveInterp; /* A slave. */ - int len; /* Dummy length variable. */ - - if ((objc != 4) && (objc != 5)) { - Tcl_WrongNumArgs(interp, 2, objv, - "path hiddenCmdName ?cmdName?"); - return TCL_ERROR; - } - if (Tcl_IsSafe(interp)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "permission denied: safe interpreter cannot expose commands", - (char *) NULL); - return TCL_ERROR; - } - slaveInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), &masterPtr); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", Tcl_GetStringFromObj(objv[2], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - if (Tcl_ExposeCommand(slaveInterp, - Tcl_GetStringFromObj(objv[3], &len), - (objc == 5 ? - Tcl_GetStringFromObj(objv[4], &len) : - Tcl_GetStringFromObj(objv[3], &len))) - == TCL_ERROR) { - if (interp != slaveInterp) { - Tcl_SetObjResult(interp, Tcl_GetObjResult(slaveInterp)); - Tcl_ResetResult(slaveInterp); - } - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * InterpHideHelper -- - * - * Helper function that handles the details of hiding a command in - * another interpreter. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * Hides a command. From now on the command cannot be called by - * scripts in that interpreter. - * - *---------------------------------------------------------------------- - */ - -static int -InterpHideHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - Tcl_Interp *slaveInterp; /* A slave. */ - int len; /* Dummy length variable. */ - - if ((objc != 4) && (objc != 5)) { - Tcl_WrongNumArgs(interp, 2, objv, - "path cmdName ?hiddenCmdName?"); - return TCL_ERROR; - } - if (Tcl_IsSafe(interp)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "permission denied: safe interpreter cannot hide commands", - (char *) NULL); - return TCL_ERROR; - } - slaveInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), &masterPtr); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", Tcl_GetStringFromObj(objv[2], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - if (Tcl_HideCommand(slaveInterp, Tcl_GetStringFromObj(objv[3], &len), - (objc == 5 ? - Tcl_GetStringFromObj(objv[4], &len) : - Tcl_GetStringFromObj(objv[3], &len))) - == TCL_ERROR) { - if (interp != slaveInterp) { - Tcl_SetObjResult(interp, Tcl_GetObjResult(slaveInterp)); - Tcl_ResetResult(slaveInterp); - } - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * InterpHiddenHelper -- - * - * Computes the list of hidden commands in a named interpreter. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -InterpHiddenHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - Tcl_Interp *slaveInterp; /* A slave. */ - int len; - Tcl_HashTable *hTblPtr; /* Hidden command table. */ - Tcl_HashEntry *hPtr; /* Search variable. */ - Tcl_HashSearch hSearch; /* Iteration variable. */ - Tcl_Obj *listObjPtr; /* Local object pointer. */ - - if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?path?"); - return TCL_ERROR; - } - if (objc == 3) { - slaveInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), - &masterPtr); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", Tcl_GetStringFromObj(objv[2], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - } else { - slaveInterp = interp; - } - - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(slaveInterp, - "tclHiddenCmds", NULL); - if (hTblPtr != (Tcl_HashTable *) NULL) { - for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); - hPtr != (Tcl_HashEntry *) NULL; - hPtr = Tcl_NextHashEntry(&hSearch)) { - - Tcl_ListObjAppendElement(interp, listObjPtr, - Tcl_NewStringObj(Tcl_GetHashKey(hTblPtr, hPtr), -1)); - } - } - Tcl_SetObjResult(interp, listObjPtr); - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * InterpInvokeHiddenHelper -- - * - * Helper routine to handle the details of invoking a hidden - * command in another interpreter. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * Whatever the hidden command does. - * - *---------------------------------------------------------------------- - */ - -static int -InterpInvokeHiddenHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - int doGlobal = 0; - int len; - int result; - Tcl_Obj *namePtr, *objPtr; - Tcl_Interp *slaveInterp; - Interp *iPtr; - char *string; - - if (objc < 4) { - Tcl_WrongNumArgs(interp, 2, objv, - "path ?-global? cmd ?arg ..?"); - return TCL_ERROR; - } - if (Tcl_IsSafe(interp)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "not allowed to invoke hidden commands from safe interpreter", - (char *) NULL); - return TCL_ERROR; - } - if (strcmp(Tcl_GetStringFromObj(objv[3], &len), "-global") == 0) { - doGlobal = 1; - if (objc < 5) { - Tcl_WrongNumArgs(interp, 2, objv, - "path ?-global? cmd ?arg ..?"); - return TCL_ERROR; - } - } - slaveInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), &masterPtr); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", Tcl_GetStringFromObj(objv[2], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - Tcl_Preserve((ClientData) slaveInterp); - if (doGlobal) { - result = TclObjInvokeGlobal(slaveInterp, objc-4, objv+4, - TCL_INVOKE_HIDDEN); - } else { - result = TclObjInvoke(slaveInterp, objc-3, objv+3, TCL_INVOKE_HIDDEN); - } - - /* - * Now make the result and any error information accessible. We - * have to be careful because the slave interpreter and the current - * interpreter can be the same - do not destroy the result.. This - * can happen if an interpreter contains an alias which is directed - * at a target command in the same interpreter. - */ - - if (interp != slaveInterp) { - if (result == TCL_ERROR) { - - /* - * An error occurred, so transfer error information from - * the target interpreter back to our interpreter. - */ - - iPtr = (Interp *) slaveInterp; - if (!(iPtr->flags & ERR_ALREADY_LOGGED)) { - Tcl_AddErrorInfo(slaveInterp, ""); - } - iPtr->flags &= (~(ERR_ALREADY_LOGGED)); - - Tcl_ResetResult(interp); - namePtr = Tcl_NewStringObj("errorInfo", -1); - objPtr = Tcl_ObjGetVar2(slaveInterp, namePtr, - (Tcl_Obj *) NULL, TCL_GLOBAL_ONLY); - Tcl_DecrRefCount(namePtr); - string = Tcl_GetStringFromObj(objPtr, &len); - Tcl_AddObjErrorInfo(interp, string, len); - Tcl_SetVar2(interp, "errorCode", (char *) NULL, - Tcl_GetVar2(slaveInterp, "errorCode", (char *) - NULL, TCL_GLOBAL_ONLY), - TCL_GLOBAL_ONLY); - } - - /* - * Move the result object from the slave to the master. - */ - - Tcl_SetObjResult(interp, Tcl_GetObjResult(slaveInterp)); - Tcl_ResetResult(slaveInterp); - } - Tcl_Release((ClientData) slaveInterp); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * InterpMarkTrustedHelper -- - * - * Helper function to handle the details of marking another - * interpreter as trusted (unsafe). - * - * Results: - * A standard Tcl result. - * - * Side effects: - * Henceforth the hard-wired checks for safety will not prevent - * this interpreter from performing certain operations. - * - *---------------------------------------------------------------------- - */ - -static int -InterpMarkTrustedHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - Tcl_Interp *slaveInterp; /* A slave. */ - int len; /* Dummy length variable. */ - - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "path"); - return TCL_ERROR; - } - if (Tcl_IsSafe(interp)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "\"", Tcl_GetStringFromObj(objv[0], &len), - " marktrusted\" can only", - " be invoked from a trusted interpreter", - (char *) NULL); - return TCL_ERROR; - } - - slaveInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), &masterPtr); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", Tcl_GetStringFromObj(objv[2], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - return MarkTrusted(slaveInterp); -} - -/* - *---------------------------------------------------------------------- - * - * InterpIsSafeHelper -- - * - * Computes whether a named interpreter is safe. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -InterpIsSafeHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - Tcl_Interp *slaveInterp; /* A slave. */ - int len; /* Dummy length variable. */ - Tcl_Obj *objPtr; /* Local object pointer. */ - - if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?path?"); - return TCL_ERROR; - } - if (objc == 3) { - slaveInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), &masterPtr); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", - Tcl_GetStringFromObj(objv[2], &len), "\" not found", - (char *) NULL); - return TCL_ERROR; - } - objPtr = Tcl_NewIntObj(Tcl_IsSafe(slaveInterp)); - } else { - objPtr = Tcl_NewIntObj(Tcl_IsSafe(interp)); - } - Tcl_SetObjResult(interp, objPtr); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * InterpSlavesHelper -- - * - * Computes a list of slave interpreters of a named interpreter. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -InterpSlavesHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - int len; - Tcl_HashEntry *hPtr; /* Search variable. */ - Tcl_HashSearch hSearch; /* Iteration variable. */ - Tcl_Obj *listObjPtr; /* Local object pointers. */ - - if ((objc != 2) && (objc != 3)) { - Tcl_WrongNumArgs(interp, 2, objv, "?path?"); - return TCL_ERROR; - } - if (objc == 3) { - if (GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), &masterPtr) == - (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", Tcl_GetStringFromObj(objv[2], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - } - - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - for (hPtr = Tcl_FirstHashEntry(&(masterPtr->slaveTable), &hSearch); - hPtr != NULL; - hPtr = Tcl_NextHashEntry(&hSearch)) { - - Tcl_ListObjAppendElement(interp, listObjPtr, - Tcl_NewStringObj( - Tcl_GetHashKey(&(masterPtr->slaveTable), hPtr), -1)); - } - Tcl_SetObjResult(interp, listObjPtr); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * InterpShareHelper -- - * - * Helper function to handle the details of sharing a channel between - * interpreters. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * After this call the named channel will be shared between the - * interpreters named in the arguments. - * - *---------------------------------------------------------------------- - */ - -static int -InterpShareHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - Tcl_Interp *slaveInterp; /* A slave. */ - Tcl_Interp *masterInterp; /* Its master. */ - int len; - Tcl_Channel chan; - - if (objc != 5) { - Tcl_WrongNumArgs(interp, 2, objv, "srcPath channelId destPath"); - return TCL_ERROR; - } - masterInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), NULL); - if (masterInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", Tcl_GetStringFromObj(objv[2], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - slaveInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[4], &len), NULL); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", Tcl_GetStringFromObj(objv[4], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - chan = Tcl_GetChannel(masterInterp, Tcl_GetStringFromObj(objv[3], &len), - NULL); - if (chan == (Tcl_Channel) NULL) { - if (interp != masterInterp) { - Tcl_SetObjResult(interp, Tcl_GetObjResult(masterInterp)); - Tcl_ResetResult(masterInterp); - } - return TCL_ERROR; - } - Tcl_RegisterChannel(slaveInterp, chan); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * InterpTargetHelper -- - * - * Helper function to compute the target of an alias. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -InterpTargetHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - int len; - - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "path alias"); - return TCL_ERROR; - } - return GetTarget(interp, - Tcl_GetStringFromObj(objv[2], &len), - Tcl_GetStringFromObj(objv[3], &len)); -} - -/* - *---------------------------------------------------------------------- - * - * InterpTransferHelper -- - * - * Helper function to handle the details of transferring ownership - * of a channel between interpreters. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * After the call, the named channel will be registered in the target - * interpreter and no longer available for use in the source interpreter. - * - *---------------------------------------------------------------------- - */ - -static int -InterpTransferHelper(interp, masterPtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Master *masterPtr; /* Master record for interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - Tcl_Interp *slaveInterp; /* A slave. */ - Tcl_Interp *masterInterp; /* Its master. */ - int len; - Tcl_Channel chan; - - if (objc != 5) { - Tcl_WrongNumArgs(interp, 2, objv, - "srcPath channelId destPath"); - return TCL_ERROR; - } - masterInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[2], &len), NULL); - if (masterInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", Tcl_GetStringFromObj(objv[2], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - slaveInterp = GetInterp(interp, masterPtr, - Tcl_GetStringFromObj(objv[4], &len), NULL); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter \"", Tcl_GetStringFromObj(objv[4], &len), - "\" not found", (char *) NULL); - return TCL_ERROR; - } - chan = Tcl_GetChannel(masterInterp, - Tcl_GetStringFromObj(objv[3], &len), NULL); - if (chan == (Tcl_Channel) NULL) { - if (interp != masterInterp) { - - /* - * After fixing objresult, this code will change to: - * Tcl_SetObjResult(interp, Tcl_GetObjResult(masterInterp)); - */ - - Tcl_SetObjResult(interp, Tcl_GetObjResult(masterInterp)); - Tcl_ResetResult(masterInterp); - } - return TCL_ERROR; - } - Tcl_RegisterChannel(slaveInterp, chan); - if (Tcl_UnregisterChannel(masterInterp, chan) != TCL_OK) { - if (interp != masterInterp) { - Tcl_SetObjResult(interp, Tcl_GetObjResult(masterInterp)); - Tcl_ResetResult(masterInterp); - } - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * DescribeAlias -- - * - * 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 -DescribeAlias(interp, slaveInterp, aliasName) - Tcl_Interp *interp; /* Interpreter for result & errors. */ - Tcl_Interp *slaveInterp; /* Interpreter defining alias. */ - char *aliasName; /* Name of alias to describe. */ -{ - Slave *slavePtr; /* Slave interp slave record. */ - Tcl_HashEntry *hPtr; /* Search variable. */ - Alias *aliasPtr; /* Structure describing alias. */ - int i; /* Loop variable. */ - Tcl_Obj *listObjPtr; /* Local object pointer. */ - - slavePtr = (Slave *) Tcl_GetAssocData(slaveInterp, "tclSlaveRecord", - NULL); - - /* - * The slave record should always be present because it is created - * by Tcl_CreateInterp. - */ - - if (slavePtr == (Slave *) NULL) { - panic("DescribeAlias: could not find slave record"); - } - hPtr = Tcl_FindHashEntry(&(slavePtr->aliasTable), aliasName); - if (hPtr == (Tcl_HashEntry *) NULL) { - return TCL_OK; - } - aliasPtr = (Alias *) Tcl_GetHashValue(hPtr); - - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - Tcl_ListObjAppendElement(interp, listObjPtr, - Tcl_NewStringObj(aliasPtr->targetName, -1)); - for (i = 0; i < aliasPtr->objc; i++) { - Tcl_ListObjAppendElement(interp, listObjPtr, aliasPtr->objv[i]); - } - Tcl_SetObjResult(interp, listObjPtr); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * DeleteAlias -- - * - * 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 -DeleteAlias(interp, slaveInterp, aliasName) - Tcl_Interp *interp; /* Interpreter for result and errors. */ - Tcl_Interp *slaveInterp; /* Interpreter defining alias. */ - char *aliasName; /* Name of alias to delete. */ -{ - Slave *slavePtr; /* Slave record for slave interpreter. */ - Alias *aliasPtr; /* Points at alias structure to delete. */ - Tcl_HashEntry *hPtr; /* Search variable. */ - char *tmpPtr, *namePtr; /* Local pointers to name of command to - * be deleted. */ - - slavePtr = (Slave *) Tcl_GetAssocData(slaveInterp, "tclSlaveRecord", - NULL); - if (slavePtr == (Slave *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "alias \"", aliasName, "\" not found", (char *) NULL); - return TCL_ERROR; - } - - /* - * Get the alias from the alias table, then delete the command. The - * deleteProc on the alias command will take care of removing the entry - * from the alias table. - */ - - hPtr = Tcl_FindHashEntry(&(slavePtr->aliasTable), aliasName); - if (hPtr == (Tcl_HashEntry *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "alias \"", aliasName, "\" not found", (char *) NULL); - return TCL_ERROR; - } - aliasPtr = (Alias *) Tcl_GetHashValue(hPtr); - - /* - * Get a copy of the real name of the command -- it might have - * been renamed, and we want to delete the renamed command, not - * the current command (if any) by the name of the original alias. - * We need the local copy because the name may get smashed when the - * command to delete is exposed, if it was hidden. - */ - - tmpPtr = Tcl_GetCommandName(slaveInterp, aliasPtr->slaveCmd); - namePtr = (char *) ckalloc((unsigned) strlen(tmpPtr) + 1); - strcpy(namePtr, tmpPtr); - - /* - * NOTE: The deleteProc for this command will delete the - * alias from the hash table. The deleteProc will also - * delete the target information from the master interpreter - * target table. - */ - - if (Tcl_DeleteCommand(slaveInterp, namePtr) != 0) { - if (Tcl_ExposeCommand(slaveInterp, namePtr, namePtr) != TCL_OK) { - panic("DeleteAlias: did not find alias to be deleted"); - } - if (Tcl_DeleteCommand(slaveInterp, namePtr) != 0) { - panic("DeleteAlias: did not find alias to be deleted"); - } - } - ckfree(namePtr); - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * 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(askingInterp, targetInterp) - Tcl_Interp *askingInterp; /* Interpreter to start search from. */ - Tcl_Interp *targetInterp; /* Interpreter to find. */ -{ - Master *masterPtr; /* Interim storage for Master record. */ - Slave *slavePtr; /* Interim storage for Slave record. */ - - if (targetInterp == askingInterp) { - return TCL_OK; - } - if (targetInterp == (Tcl_Interp *) NULL) { - return TCL_ERROR; - } - slavePtr = (Slave *) Tcl_GetAssocData(targetInterp, "tclSlaveRecord", - NULL); - if (slavePtr == (Slave *) NULL) { - return TCL_ERROR; - } - if (Tcl_GetInterpPath(askingInterp, slavePtr->masterInterp) == TCL_ERROR) { - - /* - * The result of askingInterp was set by recursive call. - */ - - return TCL_ERROR; - } - masterPtr = (Master *) Tcl_GetAssocData(slavePtr->masterInterp, - "tclMasterRecord", NULL); - if (masterPtr == (Master *) NULL) { - panic("Tcl_GetInterpPath: could not find master record"); - } - Tcl_AppendElement(askingInterp, Tcl_GetHashKey(&(masterPtr->slaveTable), - slavePtr->slaveEntry)); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * GetTarget -- - * - * Sets the result of the invoking interpreter to a path name for - * the target interpreter of an alias in one of the slaves. - * - * Results: - * TCL_OK if the target interpreter of the alias is a slave of the - * invoking interpreter, TCL_ERROR else. - * - * Side effects: - * Sets the result of the invoking interpreter. - * - *---------------------------------------------------------------------- - */ - -static int -GetTarget(askingInterp, path, aliasName) - Tcl_Interp *askingInterp; /* Interpreter to start search from. */ - char *path; /* The path of the interp to find. */ - char *aliasName; /* The target of this allias. */ -{ - Tcl_Interp *slaveInterp; /* Interim storage for slave. */ - Slave *slaveSlavePtr; /* Its Slave record. */ - Master *masterPtr; /* Interim storage for Master record. */ - Tcl_HashEntry *hPtr; /* Search element. */ - Alias *aliasPtr; /* Data describing the alias. */ - - Tcl_ResetResult(askingInterp); - masterPtr = (Master *) Tcl_GetAssocData(askingInterp, "tclMasterRecord", - NULL); - if (masterPtr == (Master *) NULL) { - panic("GetTarget: could not find master record"); - } - slaveInterp = GetInterp(askingInterp, masterPtr, path, NULL); - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(askingInterp), - "could not find interpreter \"", path, "\"", (char *) NULL); - return TCL_ERROR; - } - slaveSlavePtr = (Slave *) Tcl_GetAssocData(slaveInterp, "tclSlaveRecord", - NULL); - if (slaveSlavePtr == (Slave *) NULL) { - panic("GetTarget: could not find slave record"); - } - hPtr = Tcl_FindHashEntry(&(slaveSlavePtr->aliasTable), aliasName); - if (hPtr == (Tcl_HashEntry *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(askingInterp), - "alias \"", aliasName, "\" in path \"", path, "\" not found", - (char *) NULL); - return TCL_ERROR; - } - aliasPtr = (Alias *) Tcl_GetHashValue(hPtr); - if (aliasPtr == (Alias *) NULL) { - panic("GetTarget: could not find alias record"); - } - - if (Tcl_GetInterpPath(askingInterp, aliasPtr->targetInterp) == TCL_ERROR) { - Tcl_ResetResult(askingInterp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(askingInterp), - "target interpreter for alias \"", - aliasName, "\" in path \"", path, "\" is not my descendant", - (char *) NULL); - return TCL_ERROR; - } - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_InterpCmd -- - * - * This procedure 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, interp, objc, objv) - ClientData clientData; /* Unused. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - Master *masterPtr; /* Master record for current interp. */ - int result; /* Local result variable. */ - - /* - * These are all the different subcommands for this command: - */ - - static char *subCmds[] = { - "alias", "aliases", "create", "delete", "eval", "exists", - "expose", "hide", "hidden", "issafe", "invokehidden", - "marktrusted", "slaves", "share", "target", "transfer", - (char *) NULL}; - enum ISubCmdIdx { - IAliasIdx, IAliasesIdx, ICreateIdx, IDeleteIdx, IEvalIdx, - IExistsIdx, IExposeIdx, IHideIdx, IHiddenIdx, IIsSafeIdx, - IInvokeHiddenIdx, IMarkTrustedIdx, ISlavesIdx, IShareIdx, - ITargetIdx, ITransferIdx - } index; - - if (objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?"); - return TCL_ERROR; - } - - masterPtr = (Master *) Tcl_GetAssocData(interp, "tclMasterRecord", NULL); - if (masterPtr == (Master *) NULL) { - panic("Tcl_InterpCmd: could not find master record"); - } - - result = Tcl_GetIndexFromObj(interp, objv[1], subCmds, "option", - 0, (int *) &index); - if (result != TCL_OK) { - return result; - } - - switch (index) { - case IAliasIdx: - return InterpAliasHelper(interp, masterPtr, objc, objv); - case IAliasesIdx: - return InterpAliasesHelper(interp, masterPtr, objc, objv); - case ICreateIdx: - return CreateInterpObject(interp, masterPtr, objc, objv); - case IDeleteIdx: - return DeleteInterpObject(interp, masterPtr, objc, objv); - case IEvalIdx: - return InterpEvalHelper(interp, masterPtr, objc, objv); - case IExistsIdx: - return InterpExistsHelper(interp, masterPtr, objc, objv); - case IExposeIdx: - return InterpExposeHelper(interp, masterPtr, objc, objv); - case IHideIdx: - return InterpHideHelper(interp, masterPtr, objc, objv); - case IHiddenIdx: - return InterpHiddenHelper(interp, masterPtr, objc, objv); - case IIsSafeIdx: - return InterpIsSafeHelper(interp, masterPtr, objc, objv); - case IInvokeHiddenIdx: - return InterpInvokeHiddenHelper(interp, masterPtr, objc, objv); - case IMarkTrustedIdx: - return InterpMarkTrustedHelper(interp, masterPtr, objc, objv); - case ISlavesIdx: - return InterpSlavesHelper(interp, masterPtr, objc, objv); - case IShareIdx: - return InterpShareHelper(interp, masterPtr, objc, objv); - case ITargetIdx: - return InterpTargetHelper(interp, masterPtr, objc, objv); - case ITransferIdx: - return InterpTransferHelper(interp, masterPtr, objc, objv); - } - - return TCL_ERROR; -} - -/* - *---------------------------------------------------------------------- - * - * SlaveAliasHelper -- - * - * Helper function to construct or query an alias for a slave - * interpreter. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * Potentially creates a new alias. - * - *---------------------------------------------------------------------- - */ - -static int -SlaveAliasHelper(interp, slaveInterp, slavePtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Tcl_Interp *slaveInterp; /* The slave interpreter. */ - Slave *slavePtr; /* Its slave record. */ - int objc; /* Count of arguments. */ - Tcl_Obj *CONST objv[]; /* Vector of arguments. */ -{ - Master *masterPtr; - int len; - - switch (objc-2) { - case 0: - Tcl_WrongNumArgs(interp, 2, objv, - "aliasName ?targetName? ?args..?"); - return TCL_ERROR; - - case 1: - - /* - * Return the name of the command in the current - * interpreter for which the argument is an alias in the - * slave interpreter, and the list of saved arguments - */ - - return DescribeAlias(interp, slaveInterp, - Tcl_GetStringFromObj(objv[2], &len)); - - default: - masterPtr = (Master *) Tcl_GetAssocData(interp, - "tclMasterRecord", NULL); - if (masterPtr == (Master *) NULL) { - panic("SlaveObjectCmd: could not find master record"); - } - return AliasCreationHelper(interp, slaveInterp, interp, - masterPtr, - Tcl_GetStringFromObj(objv[2], &len), - Tcl_GetStringFromObj(objv[3], &len), - objc-4, objv+4); - } -} - -/* - *---------------------------------------------------------------------- - * - * SlaveAliasesHelper -- - * - * Computes a list of aliases defined in a slave interpreter. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -SlaveAliasesHelper(interp, slaveInterp, slavePtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Tcl_Interp *slaveInterp; /* The slave interpreter. */ - Slave *slavePtr; /* Its slave record. */ - int objc; /* Count of arguments. */ - Tcl_Obj *CONST objv[]; /* Vector of arguments. */ -{ - Tcl_HashEntry *hPtr; /* For local searches. */ - Tcl_HashSearch hSearch; /* For local searches. */ - Tcl_Obj *listObjPtr; /* Local object pointer. */ - Alias *aliasPtr; /* Alias information. */ - - /* - * Return the names of all the aliases created in the - * slave interpreter. - */ - - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - for (hPtr = Tcl_FirstHashEntry(&(slavePtr->aliasTable), - &hSearch); - hPtr != (Tcl_HashEntry *) NULL; - hPtr = Tcl_NextHashEntry(&hSearch)) { - aliasPtr = (Alias *) Tcl_GetHashValue(hPtr); - Tcl_ListObjAppendElement(interp, listObjPtr, - Tcl_NewStringObj(aliasPtr->aliasName, -1)); - } - Tcl_SetObjResult(interp, listObjPtr); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * SlaveEvalHelper -- - * - * Helper function to evaluate a command in a slave interpreter. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * Whatever the command does. - * - *---------------------------------------------------------------------- - */ - -static int -SlaveEvalHelper(interp, slaveInterp, slavePtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Tcl_Interp *slaveInterp; /* The slave interpreter. */ - Slave *slavePtr; /* Its slave record. */ - int objc; /* Count of arguments. */ - Tcl_Obj *CONST objv[]; /* Vector of arguments. */ -{ - Interp *iPtr; /* Internal data type for slave. */ - Tcl_Obj *objPtr; /* Local object pointer. */ - Tcl_Obj *namePtr; /* Local object pointer. */ - int len; - char *string; - int result; - - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "arg ?arg ...?"); - return TCL_ERROR; - } - - objPtr = Tcl_ConcatObj(objc-2, objv+2); - Tcl_IncrRefCount(objPtr); - - Tcl_Preserve((ClientData) slaveInterp); - result = Tcl_EvalObj(slaveInterp, objPtr); - - Tcl_DecrRefCount(objPtr); - - /* - * Make the result and any error information accessible. We have - * to be careful because the slave interpreter and the current - * interpreter can be the same - do not destroy the result.. This - * can happen if an interpreter contains an alias which is directed - * at a target command in the same interpreter. - */ - - if (interp != slaveInterp) { - if (result == TCL_ERROR) { - - /* - * An error occurred, so transfer error information from the - * destination interpreter back to our interpreter. - */ - - iPtr = (Interp *) slaveInterp; - if (!(iPtr->flags & ERR_ALREADY_LOGGED)) { - Tcl_AddErrorInfo(slaveInterp, ""); - } - iPtr->flags &= (~(ERR_ALREADY_LOGGED)); - - Tcl_ResetResult(interp); - namePtr = Tcl_NewStringObj("errorInfo", -1); - objPtr = Tcl_ObjGetVar2(slaveInterp, namePtr, - (Tcl_Obj *) NULL, TCL_GLOBAL_ONLY); - string = Tcl_GetStringFromObj(objPtr, &len); - Tcl_AddObjErrorInfo(interp, string, len); - Tcl_SetVar2(interp, "errorCode", (char *) NULL, - Tcl_GetVar2(slaveInterp, "errorCode", (char *) - NULL, TCL_GLOBAL_ONLY), - TCL_GLOBAL_ONLY); - Tcl_DecrRefCount(namePtr); - } - - /* - * Move the result object from one interpreter to the - * other. - */ - - Tcl_SetObjResult(interp, Tcl_GetObjResult(slaveInterp)); - Tcl_ResetResult(slaveInterp); - } - Tcl_Release((ClientData) slaveInterp); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * SlaveExposeHelper -- - * - * 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 -SlaveExposeHelper(interp, slaveInterp, slavePtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Tcl_Interp *slaveInterp; /* The slave interpreter. */ - Slave *slavePtr; /* Its slave record. */ - int objc; /* Count of arguments. */ - Tcl_Obj *CONST objv[]; /* Vector of arguments. */ -{ - int len; - - if ((objc != 3) && (objc != 4)) { - Tcl_WrongNumArgs(interp, 2, objv, "hiddenCmdName ?cmdName?"); - return TCL_ERROR; - } - if (Tcl_IsSafe(interp)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "permission denied: safe interpreter cannot expose commands", - (char *) NULL); - return TCL_ERROR; - } - if (Tcl_ExposeCommand(slaveInterp, Tcl_GetStringFromObj(objv[2], &len), - (objc == 4 ? - Tcl_GetStringFromObj(objv[3], &len) : - Tcl_GetStringFromObj(objv[2], &len))) - == TCL_ERROR) { - Tcl_SetObjResult(interp, Tcl_GetObjResult(slaveInterp)); - Tcl_ResetResult(slaveInterp); - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * SlaveHideHelper -- - * - * 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 -SlaveHideHelper(interp, slaveInterp, slavePtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Tcl_Interp *slaveInterp; /* The slave interpreter. */ - Slave *slavePtr; /* Its slave record. */ - int objc; /* Count of arguments. */ - Tcl_Obj *CONST objv[]; /* Vector of arguments. */ -{ - int len; - - if ((objc != 3) && (objc != 4)) { - Tcl_WrongNumArgs(interp, 2, objv, "cmdName ?hiddenCmdName?"); - return TCL_ERROR; - } - if (Tcl_IsSafe(interp)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "permission denied: safe interpreter cannot hide commands", - (char *) NULL); - return TCL_ERROR; - } - if (Tcl_HideCommand(slaveInterp, Tcl_GetStringFromObj(objv[2], &len), - (objc == 4 ? - Tcl_GetStringFromObj(objv[3], &len) : - Tcl_GetStringFromObj(objv[2], &len))) - == TCL_ERROR) { - Tcl_SetObjResult(interp, Tcl_GetObjResult(slaveInterp)); - Tcl_ResetResult(slaveInterp); - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * SlaveHiddenHelper -- - * - * Helper function to compute list of hidden commands in a slave - * interpreter. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -SlaveHiddenHelper(interp, slaveInterp, slavePtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Tcl_Interp *slaveInterp; /* The slave interpreter. */ - Slave *slavePtr; /* Its slave record. */ - int objc; /* Count of arguments. */ - Tcl_Obj *CONST objv[]; /* Vector of arguments. */ -{ - Tcl_Obj *listObjPtr; /* Local object pointer. */ - Tcl_HashTable *hTblPtr; /* For local searches. */ - Tcl_HashEntry *hPtr; /* For local searches. */ - Tcl_HashSearch hSearch; /* For local searches. */ - - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return TCL_ERROR; - } - - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(slaveInterp, - "tclHiddenCmds", NULL); - if (hTblPtr != (Tcl_HashTable *) NULL) { - for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); - hPtr != (Tcl_HashEntry *) NULL; - hPtr = Tcl_NextHashEntry(&hSearch)) { - Tcl_ListObjAppendElement(interp, listObjPtr, - Tcl_NewStringObj(Tcl_GetHashKey(hTblPtr, hPtr), -1)); - } - } - Tcl_SetObjResult(interp, listObjPtr); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * SlaveIsSafeHelper -- - * - * Helper function to compute whether a slave interpreter is safe. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -SlaveIsSafeHelper(interp, slaveInterp, slavePtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Tcl_Interp *slaveInterp; /* The slave interpreter. */ - Slave *slavePtr; /* Its slave record. */ - int objc; /* Count of arguments. */ - Tcl_Obj *CONST objv[]; /* Vector of arguments. */ -{ - Tcl_Obj *resultPtr; /* Local object pointer. */ - - if (objc > 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return TCL_ERROR; - } - resultPtr = Tcl_NewIntObj(Tcl_IsSafe(slaveInterp)); - - Tcl_SetObjResult(interp, resultPtr); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * SlaveInvokeHiddenHelper -- - * - * 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 -SlaveInvokeHiddenHelper(interp, slaveInterp, slavePtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Tcl_Interp *slaveInterp; /* The slave interpreter. */ - Slave *slavePtr; /* Its slave record. */ - int objc; /* Count of arguments. */ - Tcl_Obj *CONST objv[]; /* Vector of arguments. */ -{ - Interp *iPtr; - Master *masterPtr; - int doGlobal = 0; - int result; - int len; - char *string; - Tcl_Obj *namePtr, *objPtr; - - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, - "?-global? cmd ?arg ..?"); - return TCL_ERROR; - } - if (Tcl_IsSafe(interp)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "not allowed to invoke hidden commands from safe interpreter", - (char *) NULL); - return TCL_ERROR; - } - if (strcmp(Tcl_GetStringFromObj(objv[2], &len), "-global") == 0) { - doGlobal = 1; - if (objc < 4) { - Tcl_WrongNumArgs(interp, 2, objv, - "path ?-global? cmd ?arg ..?"); - return TCL_ERROR; - } - } - masterPtr = (Master *) Tcl_GetAssocData(slaveInterp, - "tclMasterRecord", NULL); - if (masterPtr == (Master *) NULL) { - panic("SlaveObjectCmd: could not find master record"); - } - Tcl_Preserve((ClientData) slaveInterp); - if (doGlobal) { - result = TclObjInvokeGlobal(slaveInterp, objc-3, objv+3, - TCL_INVOKE_HIDDEN); - } else { - result = TclObjInvoke(slaveInterp, objc-2, objv+2, - TCL_INVOKE_HIDDEN); - } - - /* - * Now make the result and any error information accessible. We - * have to be careful because the slave interpreter and the current - * interpreter can be the same - do not destroy the result.. This - * can happen if an interpreter contains an alias which is directed - * at a target command in the same interpreter. - */ - - if (interp != slaveInterp) { - if (result == TCL_ERROR) { - - /* - * An error occurred, so transfer error information from - * the target interpreter back to our interpreter. - */ - - iPtr = (Interp *) slaveInterp; - if (!(iPtr->flags & ERR_ALREADY_LOGGED)) { - Tcl_AddErrorInfo(slaveInterp, ""); - } - iPtr->flags &= (~(ERR_ALREADY_LOGGED)); - - Tcl_ResetResult(interp); - namePtr = Tcl_NewStringObj("errorInfo", -1); - objPtr = Tcl_ObjGetVar2(slaveInterp, namePtr, - (Tcl_Obj *) NULL, TCL_GLOBAL_ONLY); - string = Tcl_GetStringFromObj(objPtr, &len); - Tcl_AddObjErrorInfo(interp, string, len); - Tcl_SetVar2(interp, "errorCode", (char *) NULL, - Tcl_GetVar2(slaveInterp, "errorCode", (char *) - NULL, TCL_GLOBAL_ONLY), - TCL_GLOBAL_ONLY); - Tcl_DecrRefCount(namePtr); - } - - /* - * Move the result object from the slave to the master. - */ - - Tcl_SetObjResult(interp, Tcl_GetObjResult(slaveInterp)); - Tcl_ResetResult(slaveInterp); - } - Tcl_Release((ClientData) slaveInterp); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * SlaveMarkTrustedHelper -- - * - * 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 -SlaveMarkTrustedHelper(interp, slaveInterp, slavePtr, objc, objv) - Tcl_Interp *interp; /* Current interpreter. */ - Tcl_Interp *slaveInterp; /* The slave interpreter. */ - Slave *slavePtr; /* Its slave record. */ - int objc; /* Count of arguments. */ - Tcl_Obj *CONST objv[]; /* Vector of arguments. */ -{ - int len; - - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return TCL_ERROR; - } - if (Tcl_IsSafe(interp)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "\"", Tcl_GetStringFromObj(objv[0], &len), " marktrusted\"", - " can only be invoked from a trusted interpreter", - (char *) NULL); - return TCL_ERROR; - } - return MarkTrusted(slaveInterp); -} - -/* - *---------------------------------------------------------------------- - * - * SlaveObjectCmd -- - * - * 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 -SlaveObjectCmd(clientData, interp, objc, objv) - ClientData clientData; /* Slave interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* The argument vector. */ -{ - Slave *slavePtr; /* Slave record. */ - Tcl_Interp *slaveInterp; /* Slave interpreter. */ - int result; /* Loop counter, status return. */ - int len; /* Length of command name. */ - - /* - * These are all the different subcommands for this command: - */ - - static char *subCmds[] = { - "alias", "aliases", - "eval", "expose", - "hide", "hidden", - "issafe", "invokehidden", - "marktrusted", - (char *) NULL}; - enum ISubCmdIdx { - IAliasIdx, IAliasesIdx, - IEvalIdx, IExposeIdx, - IHideIdx, IHiddenIdx, - IIsSafeIdx, IInvokeHiddenIdx, - IMarkTrustedIdx - } index; - - if (objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?"); - return TCL_ERROR; - } - - slaveInterp = (Tcl_Interp *) clientData; - if (slaveInterp == (Tcl_Interp *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "interpreter ", Tcl_GetStringFromObj(objv[0], &len), - " has been deleted", (char *) NULL); - return TCL_ERROR; - } - - slavePtr = (Slave *) Tcl_GetAssocData(slaveInterp, - "tclSlaveRecord", NULL); - if (slavePtr == (Slave *) NULL) { - panic("SlaveObjectCmd: could not find slave record"); - } - - result = Tcl_GetIndexFromObj(interp, objv[1], subCmds, "option", - 0, (int *) &index); - if (result != TCL_OK) { - return result; - } - - switch (index) { - case IAliasIdx: - return SlaveAliasHelper(interp, slaveInterp, slavePtr, objc, objv); - case IAliasesIdx: - return SlaveAliasesHelper(interp, slaveInterp, slavePtr, - objc, objv); - case IEvalIdx: - return SlaveEvalHelper(interp, slaveInterp, slavePtr, objc, objv); - case IExposeIdx: - return SlaveExposeHelper(interp, slaveInterp, slavePtr, - objc, objv); - case IHideIdx: - return SlaveHideHelper(interp, slaveInterp, slavePtr, - objc, objv); - case IHiddenIdx: - return SlaveHiddenHelper(interp, slaveInterp, slavePtr, - objc, objv); - case IIsSafeIdx: - return SlaveIsSafeHelper(interp, slaveInterp, slavePtr, - objc, objv); - case IInvokeHiddenIdx: - return SlaveInvokeHiddenHelper(interp, slaveInterp, slavePtr, - objc, objv); - case IMarkTrustedIdx: - return SlaveMarkTrustedHelper(interp, slaveInterp, slavePtr, - objc, objv); - } - - return TCL_ERROR; -} - -/* - *---------------------------------------------------------------------- - * - * SlaveObjectDeleteProc -- - * - * 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 -SlaveObjectDeleteProc(clientData) - ClientData clientData; /* The SlaveRecord for the command. */ -{ - Slave *slavePtr; /* Interim storage for Slave record. */ - Tcl_Interp *slaveInterp; /* And for a slave interp. */ - - slaveInterp = (Tcl_Interp *) clientData; - slavePtr = (Slave *) Tcl_GetAssocData(slaveInterp, "tclSlaveRecord",NULL); - if (slavePtr == (Slave *) NULL) { - panic("SlaveObjectDeleteProc: could not find slave record"); - } - - /* - * Delete the entry in the slave table in the master interpreter now. - * This is to avoid an infinite loop in the Master hash table cleanup in - * the master interpreter. This can happen if this slave is being deleted - * because the master is being deleted and the slave deletion is deferred - * because it is still active. - */ - - Tcl_DeleteHashEntry(slavePtr->slaveEntry); - - /* - * Set to NULL so that when the slave record is cleaned up in the slave - * it does not try to delete the command causing all sorts of grief. - * See SlaveRecordDeleteProc(). - */ - - slavePtr->interpCmd = NULL; - - /* - * Destroy the interpreter - this will cause all the deleteProcs for - * all commands (including aliases) to run. - * - * NOTE: WE ASSUME THAT THE INTERPRETER HAS NOT BEEN DELETED YET!! - */ - - Tcl_DeleteInterp(slavePtr->slaveInterp); -} - -/* - *---------------------------------------------------------------------- - * - * AliasCmd -- - * - * This is the procedure that services invocations of aliases in a - * slave interpreter. One such command exists for each alias. When - * invoked, this procedure 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 -AliasCmd(clientData, interp, objc, objv) - ClientData clientData; /* Alias record. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument vector. */ -{ - Tcl_Interp *targetInterp; /* Target for alias exec. */ - Interp *iPtr; /* Internal type of target. */ - Alias *aliasPtr; /* Describes the alias. */ - Tcl_Command cmd; /* The target command. */ - Command *cmdPtr; /* Points to target command. */ - Tcl_Namespace *targetNsPtr; /* Target command's namespace. */ - int result; /* Result of execution. */ - int i, j, addObjc; /* Loop counters. */ - int localObjc; /* Local argument count. */ - Tcl_Obj **localObjv; /* Local argument vector. */ - Tcl_Obj *namePtr, *objPtr; /* Local object pointers. */ - char *string; /* Local object string rep. */ - int len; /* Dummy length arg. */ - - aliasPtr = (Alias *) clientData; - targetInterp = aliasPtr->targetInterp; - - /* - * Look for the target command in the global namespace of the target - * interpreter. - */ - - cmdPtr = NULL; - targetNsPtr = Tcl_GetGlobalNamespace(aliasPtr->targetInterp); - cmd = Tcl_FindCommand(targetInterp, aliasPtr->targetName, - targetNsPtr, /*flags*/ 0); - if (cmd != (Tcl_Command) NULL) { - cmdPtr = (Command *) cmd; - } - - iPtr = (Interp *) targetInterp; - - /* - * If the command does not exist, invoke "unknown" in the master. - */ - - if (cmdPtr == NULL) { - addObjc = aliasPtr->objc; - localObjc = addObjc + objc + 1; - localObjv = (Tcl_Obj **) ckalloc((unsigned) sizeof(Tcl_Obj *) - * localObjc); - - localObjv[0] = Tcl_NewStringObj("unknown", -1); - localObjv[1] = Tcl_NewStringObj(aliasPtr->targetName, -1); - Tcl_IncrRefCount(localObjv[0]); - Tcl_IncrRefCount(localObjv[1]); - - for (i = 0, j = 2; i < addObjc; i++, j++) { - localObjv[j] = aliasPtr->objv[i]; - } - for (i = 1; i < objc; i++, j++) { - localObjv[j] = objv[i]; - } - Tcl_Preserve((ClientData) targetInterp); - result = TclObjInvoke(targetInterp, localObjc, localObjv, 0); - - Tcl_DecrRefCount(localObjv[0]); - Tcl_DecrRefCount(localObjv[1]); - - ckfree((char *) localObjv); - - if (targetInterp != interp) { - if (result == TCL_ERROR) { - - /* - * An error occurred, so transfer error information from - * the target interpreter back to our interpreter. - */ - - if (!(iPtr->flags & ERR_ALREADY_LOGGED)) { - Tcl_AddErrorInfo((Tcl_Interp *) iPtr, ""); - } - iPtr->flags &= (~(ERR_ALREADY_LOGGED)); - - Tcl_ResetResult(interp); - namePtr = Tcl_NewStringObj("errorInfo", -1); - objPtr = Tcl_ObjGetVar2(targetInterp, namePtr, - (Tcl_Obj *) NULL, TCL_GLOBAL_ONLY); - string = Tcl_GetStringFromObj(objPtr, &len); - Tcl_AddObjErrorInfo(interp, string, len); - Tcl_SetVar2(interp, "errorCode", (char *) NULL, - Tcl_GetVar2(targetInterp, "errorCode", (char *) - NULL, TCL_GLOBAL_ONLY), - TCL_GLOBAL_ONLY); - Tcl_DecrRefCount(namePtr); - } - - /* - * Transfer the result from the target interpreter to the - * calling interpreter. - */ - - Tcl_SetObjResult(interp, Tcl_GetObjResult(targetInterp)); - Tcl_ResetResult(targetInterp); - } - - Tcl_Release((ClientData) targetInterp); - return result; - } - - /* - * Otherwise invoke the regular target command. - */ - - if (aliasPtr->objc <= 0) { - localObjv = (Tcl_Obj **) objv; - localObjc = objc; - } else { - addObjc = aliasPtr->objc; - localObjc = objc + addObjc; - localObjv = - (Tcl_Obj **) ckalloc((unsigned) sizeof(Tcl_Obj *) * localObjc); - localObjv[0] = objv[0]; - for (i = 0, j = 1; i < addObjc; i++, j++) { - localObjv[j] = aliasPtr->objv[i]; - } - for (i = 1; i < objc; i++, j++) { - localObjv[j] = objv[i]; - } - } - - iPtr->numLevels++; - Tcl_Preserve((ClientData) targetInterp); - - /* - * Reset the interpreter to its clean state; we do not know what state - * it is in now.. - */ - - Tcl_ResetResult(targetInterp); - result = (cmdPtr->objProc)(cmdPtr->objClientData, targetInterp, - localObjc, localObjv); - - iPtr->numLevels--; - - /* - * Check if we are at the bottom of the stack for the target interpreter. - * If so, check for special return codes. - */ - - if (iPtr->numLevels == 0) { - if (result == TCL_RETURN) { - result = TclUpdateReturnInfo(iPtr); - } - if ((result != TCL_OK) && (result != TCL_ERROR)) { - Tcl_ResetResult(targetInterp); - if (result == TCL_BREAK) { - Tcl_SetObjResult(targetInterp, - Tcl_NewStringObj("invoked \"break\" outside of a loop", - -1)); - } else if (result == TCL_CONTINUE) { - Tcl_SetObjResult(targetInterp, - Tcl_NewStringObj( - "invoked \"continue\" outside of a loop", - -1)); - } else { - char buf[128]; - - sprintf(buf, "command returned bad code: %d", result); - Tcl_SetObjResult(targetInterp, Tcl_NewStringObj(buf, -1)); - } - result = TCL_ERROR; - } - } - - /* - * Clean up any locally allocated argument vector structure. - */ - - if (localObjv != objv) { - ckfree((char *) localObjv); - } - - /* - * Move the result from the target interpreter to the invoking - * interpreter if they are different. - * - * Note: We cannot use aliasPtr any more because the alias may have - * been deleted. - */ - - if (interp != targetInterp) { - if (result == TCL_ERROR) { - - /* - * An error occurred, so transfer the error information from - * the target interpreter back to our interpreter. - */ - - if (!(iPtr->flags & ERR_ALREADY_LOGGED)) { - Tcl_AddErrorInfo(targetInterp, ""); - } - iPtr->flags &= (~(ERR_ALREADY_LOGGED)); - - Tcl_ResetResult(interp); - namePtr = Tcl_NewStringObj("errorInfo", -1); - objPtr = Tcl_ObjGetVar2(targetInterp, namePtr, (Tcl_Obj *) NULL, - TCL_GLOBAL_ONLY); - string = Tcl_GetStringFromObj(objPtr, &len); - Tcl_AddObjErrorInfo(interp, string, len); - Tcl_SetVar2(interp, "errorCode", (char *) NULL, - Tcl_GetVar2(targetInterp, "errorCode", (char *) NULL, - TCL_GLOBAL_ONLY), - TCL_GLOBAL_ONLY); - Tcl_DecrRefCount(namePtr); - } - - /* - * Move the result object from one interpreter to the - * other. - */ - - Tcl_SetObjResult(interp, Tcl_GetObjResult(targetInterp)); - Tcl_ResetResult(targetInterp); - } - Tcl_Release((ClientData) targetInterp); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * AliasCmdDeleteProc -- - * - * Is invoked when an alias command is deleted in a slave. Cleans up - * all storage associated with this alias. - * - * Results: - * None. - * - * Side effects: - * Deletes the alias record and its entry in the alias table for - * the interpreter. - * - *---------------------------------------------------------------------- - */ - -static void -AliasCmdDeleteProc(clientData) - ClientData clientData; /* The alias record for this alias. */ -{ - Alias *aliasPtr; /* Alias record for alias to delete. */ - Target *targetPtr; /* Record for target of this alias. */ - int i; /* Loop counter. */ - - aliasPtr = (Alias *) clientData; - - targetPtr = (Target *) Tcl_GetHashValue(aliasPtr->targetEntry); - ckfree((char *) targetPtr); - Tcl_DeleteHashEntry(aliasPtr->targetEntry); - - ckfree((char *) aliasPtr->targetName); - ckfree((char *) aliasPtr->aliasName); - for (i = 0; i < aliasPtr->objc; i++) { - Tcl_DecrRefCount(aliasPtr->objv[i]); - } - if (aliasPtr->objv != (Tcl_Obj **) NULL) { - ckfree((char *) aliasPtr->objv); - } - - Tcl_DeleteHashEntry(aliasPtr->aliasEntry); - - ckfree((char *) aliasPtr); -} - -/* - *---------------------------------------------------------------------- - * - * MasterRecordDeleteProc - - * - * Is invoked when an interpreter (which is using the "interp" facility) - * is deleted, and it cleans up the storage associated with the - * "tclMasterRecord" assoc-data entry. - * - * Results: - * None. - * - * Side effects: - * Cleans up storage. - * - *---------------------------------------------------------------------- - */ - -static void -MasterRecordDeleteProc(clientData, interp) - ClientData clientData; /* Master record for deleted interp. */ - Tcl_Interp *interp; /* Interpreter being deleted. */ -{ - Target *targetPtr; /* Loop variable. */ - Tcl_HashEntry *hPtr; /* Search element. */ - Tcl_HashSearch hSearch; /* Search record (internal). */ - Slave *slavePtr; /* Loop variable. */ - Master *masterPtr; /* Interim storage. */ - - masterPtr = (Master *) clientData; - for (hPtr = Tcl_FirstHashEntry(&(masterPtr->slaveTable), &hSearch); - hPtr != NULL; - hPtr = Tcl_NextHashEntry(&hSearch)) { - slavePtr = (Slave *) Tcl_GetHashValue(hPtr); - (void) Tcl_DeleteCommandFromToken(interp, slavePtr->interpCmd); - } - Tcl_DeleteHashTable(&(masterPtr->slaveTable)); - - for (hPtr = Tcl_FirstHashEntry(&(masterPtr->targetTable), &hSearch); - hPtr != NULL; - hPtr = Tcl_FirstHashEntry(&(masterPtr->targetTable), &hSearch)) { - targetPtr = (Target *) Tcl_GetHashValue(hPtr); - (void) Tcl_DeleteCommandFromToken(targetPtr->slaveInterp, - targetPtr->slaveCmd); - } - Tcl_DeleteHashTable(&(masterPtr->targetTable)); - - ckfree((char *) masterPtr); -} - -/* - *---------------------------------------------------------------------- - * - * SlaveRecordDeleteProc -- - * - * Is invoked when an interpreter (which is using the interp facility) - * is deleted, and it cleans up the storage associated with the - * tclSlaveRecord assoc-data entry. - * - * Results: - * None - * - * Side effects: - * Cleans up storage. - * - *---------------------------------------------------------------------- - */ - -static void -SlaveRecordDeleteProc(clientData, interp) - ClientData clientData; /* Slave record for deleted interp. */ - Tcl_Interp *interp; /* Interpreter being deleted. */ -{ - Slave *slavePtr; /* Interim storage. */ - Alias *aliasPtr; - Tcl_HashTable *hTblPtr; - Tcl_HashEntry *hPtr; - Tcl_HashSearch hSearch; - - slavePtr = (Slave *) clientData; - - /* - * In every case that we call SetAssocData on "tclSlaveRecord", - * slavePtr is not NULL. Otherwise we panic. - */ - - if (slavePtr == NULL) { - panic("SlaveRecordDeleteProc: NULL slavePtr"); - } - - if (slavePtr->interpCmd != (Tcl_Command) NULL) { - Command *cmdPtr = (Command *) slavePtr->interpCmd; - - /* - * The interpCmd has not been deleted in the master yet, since - * it's callback sets interpCmd to NULL. - * - * Probably Tcl_DeleteInterp() was called on this interpreter directly, - * rather than via "interp delete", or equivalent (deletion of the - * command in the master). - * - * Perform the cleanup done by SlaveObjectDeleteProc() directly, - * and turn off the callback now (since we are about to free slavePtr - * and this interpreter is going away, while the deletion of commands - * in the master may be deferred). - */ - - Tcl_DeleteHashEntry(slavePtr->slaveEntry); - cmdPtr->clientData = NULL; - cmdPtr->deleteProc = NULL; - cmdPtr->deleteData = NULL; - - Tcl_DeleteCommandFromToken(slavePtr->masterInterp, - slavePtr->interpCmd); - } - - /* - * If there are any aliases, delete those now. This removes any - * dependency on the order of deletion between commands and the - * slave record. - */ - - hTblPtr = (Tcl_HashTable *) &(slavePtr->aliasTable); - for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); - hPtr != (Tcl_HashEntry *) NULL; - hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch)) { - aliasPtr = (Alias *) Tcl_GetHashValue(hPtr); - - /* - * The call to Tcl_DeleteCommand will release the storage - * occupied by the hash entry and the alias record. - */ - - Tcl_DeleteCommandFromToken(interp, aliasPtr->slaveCmd); - } - - /* - * Finally dispose of the hash table and the slave record. - */ - - Tcl_DeleteHashTable(hTblPtr); - ckfree((char *) slavePtr); -} - -/* - *---------------------------------------------------------------------- - * - * TclInterpInit -- - * - * Initializes the invoking interpreter for using the "interp" - * facility. This is called from inside Tcl_Init. - * - * Results: - * None. - * - * Side effects: - * Adds the "interp" command to an interpreter and initializes several - * records in the associated data of the invoking interpreter. - * - *---------------------------------------------------------------------- - */ - -int -TclInterpInit(interp) - Tcl_Interp *interp; /* Interpreter to initialize. */ -{ - Master *masterPtr; /* Its Master record. */ - Slave *slavePtr; /* And its slave record. */ - - masterPtr = (Master *) ckalloc((unsigned) sizeof(Master)); - - Tcl_InitHashTable(&(masterPtr->slaveTable), TCL_STRING_KEYS); - Tcl_InitHashTable(&(masterPtr->targetTable), TCL_ONE_WORD_KEYS); - - (void) Tcl_SetAssocData(interp, "tclMasterRecord", MasterRecordDeleteProc, - (ClientData) masterPtr); - - slavePtr = (Slave *) ckalloc((unsigned) sizeof(Slave)); - - slavePtr->masterInterp = (Tcl_Interp *) NULL; - slavePtr->slaveEntry = (Tcl_HashEntry *) NULL; - slavePtr->slaveInterp = interp; - slavePtr->interpCmd = (Tcl_Command) NULL; - Tcl_InitHashTable(&(slavePtr->aliasTable), TCL_STRING_KEYS); - - (void) Tcl_SetAssocData(interp, "tclSlaveRecord", SlaveRecordDeleteProc, - (ClientData) slavePtr); - - 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(interp) - Tcl_Interp *interp; /* Is this interpreter "safe" ? */ -{ - Interp *iPtr; - - if (interp == (Tcl_Interp *) NULL) { - return 0; - } - iPtr = (Interp *) interp; - - return ( (iPtr->flags) & SAFE_INTERP ) ? 1 : 0 ; -} - -/* - *---------------------------------------------------------------------- - * - * 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(interp, slavePath, isSafe) - Tcl_Interp *interp; /* Interpreter to start search at. */ - char *slavePath; /* Name of slave to create. */ - int isSafe; /* Should new slave be "safe" ? */ -{ - Master *masterPtr; /* Master record for same. */ - - if ((interp == (Tcl_Interp *) NULL) || (slavePath == (char *) NULL)) { - return NULL; - } - masterPtr = (Master *) Tcl_GetAssocData(interp, "tclMasterRecord", - NULL); - if (masterPtr == (Master *) NULL) { - panic("CreatSlave: could not find master record"); - } - return CreateSlave(interp, masterPtr, slavePath, isSafe); -} - -/* - *---------------------------------------------------------------------- - * - * 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(interp, slavePath) - Tcl_Interp *interp; /* Interpreter to start search from. */ - char *slavePath; /* Path of slave to find. */ -{ - Master *masterPtr; /* Interim storage for Master record. */ - - if ((interp == (Tcl_Interp *) NULL) || (slavePath == (char *) NULL)) { - return NULL; - } - masterPtr = (Master *) Tcl_GetAssocData(interp, "tclMasterRecord", NULL); - if (masterPtr == (Master *) NULL) { - panic("Tcl_GetSlave: could not find master record"); - } - return GetInterp(interp, masterPtr, slavePath, NULL); -} - -/* - *---------------------------------------------------------------------- - * - * 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(interp) - Tcl_Interp *interp; /* Get the master of this interpreter. */ -{ - Slave *slavePtr; /* Slave record of this interpreter. */ - - if (interp == (Tcl_Interp *) NULL) { - return NULL; - } - slavePtr = (Slave *) Tcl_GetAssocData(interp, "tclSlaveRecord", NULL); - if (slavePtr == (Slave *) NULL) { - return NULL; - } - return slavePtr->masterInterp; -} - -/* - *---------------------------------------------------------------------- - * - * 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(slaveInterp, slaveCmd, targetInterp, targetCmd, argc, argv) - Tcl_Interp *slaveInterp; /* Interpreter for source command. */ - char *slaveCmd; /* Command to install in slave. */ - Tcl_Interp *targetInterp; /* Interpreter for target command. */ - char *targetCmd; /* Name of target command. */ - int argc; /* How many additional arguments? */ - char **argv; /* These are the additional args. */ -{ - Master *masterPtr; /* Master record for target interp. */ - Tcl_Obj **objv; - int i; - int result; - - if ((slaveInterp == (Tcl_Interp *) NULL) || - (targetInterp == (Tcl_Interp *) NULL) || - (slaveCmd == (char *) NULL) || - (targetCmd == (char *) NULL)) { - return TCL_ERROR; - } - masterPtr = (Master *) Tcl_GetAssocData(targetInterp, "tclMasterRecord", - NULL); - if (masterPtr == (Master *) NULL) { - panic("Tcl_CreateAlias: could not find master record"); - } - objv = (Tcl_Obj **) ckalloc((unsigned) sizeof(Tcl_Obj *) * argc); - for (i = 0; i < argc; i++) { - objv[i] = Tcl_NewStringObj(argv[i], -1); - Tcl_IncrRefCount(objv[i]); - } - - result = AliasCreationHelper(slaveInterp, slaveInterp, targetInterp, - masterPtr, slaveCmd, targetCmd, argc, objv); - - ckfree((char *) objv); - - 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(slaveInterp, slaveCmd, targetInterp, targetCmd, objc, objv) - Tcl_Interp *slaveInterp; /* Interpreter for source command. */ - char *slaveCmd; /* Command to install in slave. */ - Tcl_Interp *targetInterp; /* Interpreter for target command. */ - char *targetCmd; /* Name of target command. */ - int objc; /* How many additional arguments? */ - Tcl_Obj *CONST objv[]; /* Argument vector. */ -{ - Master *masterPtr; /* Master record for target interp. */ - - if ((slaveInterp == (Tcl_Interp *) NULL) || - (targetInterp == (Tcl_Interp *) NULL) || - (slaveCmd == (char *) NULL) || - (targetCmd == (char *) NULL)) { - return TCL_ERROR; - } - masterPtr = (Master *) Tcl_GetAssocData(targetInterp, "tclMasterRecord", - NULL); - if (masterPtr == (Master *) NULL) { - panic("Tcl_CreateAlias: could not find master record"); - } - return AliasCreationHelper(slaveInterp, slaveInterp, targetInterp, - masterPtr, slaveCmd, targetCmd, objc, objv); -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_GetAlias -- - * - * Gets information about an alias. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -Tcl_GetAlias(interp, aliasName, targetInterpPtr, targetNamePtr, argcPtr, - argvPtr) - Tcl_Interp *interp; /* Interp to start search from. */ - char *aliasName; /* Name of alias to find. */ - Tcl_Interp **targetInterpPtr; /* (Return) target interpreter. */ - char **targetNamePtr; /* (Return) name of target command. */ - int *argcPtr; /* (Return) count of addnl args. */ - char ***argvPtr; /* (Return) additional arguments. */ -{ - Slave *slavePtr; /* Slave record for slave interp. */ - Tcl_HashEntry *hPtr; /* Search element. */ - Alias *aliasPtr; /* Storage for alias found. */ - int len; - int i; - - if ((interp == (Tcl_Interp *) NULL) || (aliasName == (char *) NULL)) { - return TCL_ERROR; - } - slavePtr = (Slave *) Tcl_GetAssocData(interp, "tclSlaveRecord", NULL); - if (slavePtr == (Slave *) NULL) { - panic("Tcl_GetAlias: could not find slave record"); - } - hPtr = Tcl_FindHashEntry(&(slavePtr->aliasTable), aliasName); - if (hPtr == (Tcl_HashEntry *) NULL) { - Tcl_AppendResult(interp, "alias \"", aliasName, "\" not found", - (char *) NULL); - return TCL_ERROR; - } - aliasPtr = (Alias *) Tcl_GetHashValue(hPtr); - if (targetInterpPtr != (Tcl_Interp **) NULL) { - *targetInterpPtr = aliasPtr->targetInterp; - } - if (targetNamePtr != (char **) NULL) { - *targetNamePtr = aliasPtr->targetName; - } - if (argcPtr != (int *) NULL) { - *argcPtr = aliasPtr->objc; - } - if (argvPtr != (char ***) NULL) { - *argvPtr = (char **) ckalloc((unsigned) sizeof(char *) * - aliasPtr->objc); - for (i = 0; i < aliasPtr->objc; i++) { - *argvPtr[i] = Tcl_GetStringFromObj(aliasPtr->objv[i], &len); - } - } - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_ObjGetAlias -- - * - * Object version: Gets information about an alias. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -Tcl_GetAliasObj(interp, aliasName, targetInterpPtr, targetNamePtr, objcPtr, - objvPtr) - Tcl_Interp *interp; /* Interp to start search from. */ - char *aliasName; /* Name of alias to find. */ - Tcl_Interp **targetInterpPtr; /* (Return) target interpreter. */ - char **targetNamePtr; /* (Return) name of target command. */ - int *objcPtr; /* (Return) count of addnl args. */ - Tcl_Obj ***objvPtr; /* (Return) additional args. */ -{ - Slave *slavePtr; /* Slave record for slave interp. */ - Tcl_HashEntry *hPtr; /* Search element. */ - Alias *aliasPtr; /* Storage for alias found. */ - - if ((interp == (Tcl_Interp *) NULL) || (aliasName == (char *) NULL)) { - return TCL_ERROR; - } - slavePtr = (Slave *) Tcl_GetAssocData(interp, "tclSlaveRecord", NULL); - if (slavePtr == (Slave *) NULL) { - panic("Tcl_GetAlias: could not find slave record"); - } - hPtr = Tcl_FindHashEntry(&(slavePtr->aliasTable), aliasName); - if (hPtr == (Tcl_HashEntry *) NULL) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "alias \"", aliasName, "\" not found", (char *) NULL); - return TCL_ERROR; - } - aliasPtr = (Alias *) Tcl_GetHashValue(hPtr); - if (targetInterpPtr != (Tcl_Interp **) NULL) { - *targetInterpPtr = aliasPtr->targetInterp; - } - if (targetNamePtr != (char **) NULL) { - *targetNamePtr = aliasPtr->targetName; - } - if (objcPtr != (int *) NULL) { - *objcPtr = aliasPtr->objc; - } - if (objvPtr != (Tcl_Obj ***) NULL) { - *objvPtr = aliasPtr->objv; - } return TCL_OK; } Index: generic/tclLink.c ================================================================== --- generic/tclLink.c +++ generic/tclLink.c @@ -6,16 +6,16 @@ * 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-1996 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclLink.c 1.15 97/01/21 21:51:42 + * RCS: @(#) $Id: tclLink.c,v 1.1.2.2 1998/09/24 23:58:55 stanton Exp $ */ #include "tclInt.h" /* @@ -72,11 +72,12 @@ * 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 (interp->result is also set after errors). + * 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. @@ -232,12 +233,12 @@ int flags; /* Miscellaneous additional information. */ { Link *linkPtr = (Link *) clientData; int changed; char buffer[TCL_DOUBLE_SPACE]; - char *value, **pp; - Tcl_DString savedResult; + char *value, **pp, *result; + Tcl_Obj *objPtr; /* * If the variable is being unset, then just re-create it (with a * trace) unless the whole interpreter is going away. */ @@ -313,40 +314,46 @@ /* * This shouldn't ever happen. */ return "internal error: linked variable couldn't be read"; } - Tcl_DStringInit(&savedResult); - Tcl_DStringAppend(&savedResult, interp->result, -1); + + objPtr = Tcl_GetObjResult(interp); + Tcl_IncrRefCount(objPtr); Tcl_ResetResult(interp); + result = NULL; + switch (linkPtr->type) { case TCL_LINK_INT: if (Tcl_GetInt(interp, value, &linkPtr->lastValue.i) != TCL_OK) { - Tcl_DStringResult(interp, &savedResult); + Tcl_SetObjResult(interp, objPtr); Tcl_SetVar(interp, linkPtr->varName, StringValue(linkPtr, buffer), TCL_GLOBAL_ONLY); - return "variable must have integer value"; + result = "variable must have integer value"; + goto end; } *(int *)(linkPtr->addr) = linkPtr->lastValue.i; break; case TCL_LINK_DOUBLE: if (Tcl_GetDouble(interp, value, &linkPtr->lastValue.d) != TCL_OK) { - Tcl_DStringResult(interp, &savedResult); + Tcl_SetObjResult(interp, objPtr); Tcl_SetVar(interp, linkPtr->varName, StringValue(linkPtr, buffer), TCL_GLOBAL_ONLY); - return "variable must have real value"; + result = "variable must have real value"; + goto end; } *(double *)(linkPtr->addr) = linkPtr->lastValue.d; break; case TCL_LINK_BOOLEAN: if (Tcl_GetBoolean(interp, value, &linkPtr->lastValue.i) != TCL_OK) { - Tcl_DStringResult(interp, &savedResult); + Tcl_SetObjResult(interp, objPtr); Tcl_SetVar(interp, linkPtr->varName, StringValue(linkPtr, buffer), TCL_GLOBAL_ONLY); - return "variable must have boolean value"; + result = "variable must have boolean value"; + goto end; } *(int *)(linkPtr->addr) = linkPtr->lastValue.i; break; case TCL_LINK_STRING: pp = (char **)(linkPtr->addr); @@ -357,12 +364,13 @@ strcpy(*pp, value); break; default: return "internal error: bad linked variable type"; } - Tcl_DStringResult(interp, &savedResult); - return NULL; + end: + Tcl_DecrRefCount(objPtr); + return result; } /* *---------------------------------------------------------------------- * @@ -370,12 +378,11 @@ * * Converts the value of a C variable to a string for use in a * Tcl variable to which it is linked. * * Results: - * The return value is a pointer - to a string that represents + * The return value is a pointer to a string that represents * the value of the C variable given by linkPtr. * * Side effects: * None. * Index: generic/tclListObj.c ================================================================== --- generic/tclListObj.c +++ generic/tclListObj.c @@ -3,15 +3,16 @@ * * This file contains procedures that implement the Tcl list object * type. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright (c) 1998 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclListObj.c 1.47 97/08/12 19:02:02 + * RCS: @(#) $Id: tclListObj.c,v 1.1.2.3 1998/11/11 04:08:22 stanton Exp $ */ #include "tclInt.h" /* @@ -236,15 +237,17 @@ */ Tcl_InvalidateStringRep(objPtr); if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) { oldTypePtr->freeIntRepProc(objPtr); - objPtr->typePtr = NULL; } + objPtr->typePtr = NULL; /* * 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) { elemPtrs = (Tcl_Obj **) ckalloc((unsigned) (objc * sizeof(Tcl_Obj *))); @@ -258,10 +261,12 @@ listRepPtr->elemCount = objc; listRepPtr->elements = elemPtrs; objPtr->internalRep.otherValuePtr = (VOID *) listRepPtr; objPtr->typePtr = &tclListType; + } else { + objPtr->bytes = tclEmptyStringRep; } } /* *---------------------------------------------------------------------- @@ -872,23 +877,24 @@ SetListFromAny(interp, objPtr) Tcl_Interp *interp; /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr; /* The object to convert. */ { Tcl_ObjType *oldTypePtr = objPtr->typePtr; - char *string, *elemStart, *nextElem, *s; + char *string, *s; + CONST char *elemStart, *nextElem; int lenRemain, length, estCount, elemSize, hasBrace, i, j, result; char *limit; /* Points just after string's last byte. */ - register char *p; + register CONST char *p; register Tcl_Obj **elemPtrs; register Tcl_Obj *elemPtr; List *listRepPtr; /* * Get the string representation. Make it up-to-date if necessary. */ - string = TclGetStringFromObj(objPtr, &length); + string = Tcl_GetStringFromObj(objPtr, &length); /* * Parse the string into separate string objects, and create a List * structure that points to the element string objects. We use a * modified version of Tcl_SplitList's implementation to avoid one @@ -898,11 +904,11 @@ */ limit = (string + length); estCount = 1; for (p = string; p < limit; p++) { - if (isspace(UCHAR(*p))) { + if (isspace(UCHAR(*p))) { /* INTL: ISO space. */ estCount++; } } /* ADDED generic/tclLiteral.c Index: generic/tclLiteral.c ================================================================== --- /dev/null +++ generic/tclLiteral.c @@ -0,0 +1,929 @@ +/* + * 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. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclLiteral.c,v 1.1.2.2 1998/10/03 01:56:41 stanton Exp $ + */ + +#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 + +/* + * Procedure prototypes for static procedures in this file: + */ + +static int AddLocalLiteralEntry _ANSI_ARGS_(( + CompileEnv *envPtr, LiteralEntry *globalPtr, + int localHash)); +static void ExpandLocalLiteralArray _ANSI_ARGS_(( + CompileEnv *envPtr)); +static unsigned int HashString _ANSI_ARGS_((CONST char *bytes, + int length)); +static void RebuildLiteralTable _ANSI_ARGS_(( + LiteralTable *tablePtr)); + +/* + *---------------------------------------------------------------------- + * + * TclInitLiteralTable -- + * + * This procedure 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(tablePtr) + register LiteralTable *tablePtr; /* Pointer to table structure, which + * is supplied by the caller. */ +{ +#if (TCL_SMALL_HASH_TABLE != 4) + panic("TclInitLiteralTable: TCL_SMALL_HASH_TABLE is %d, not 4\n", + 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 procedure frees up everything associated with a literal table + * except for the table's structure itself. + * + * 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(interp, tablePtr) + Tcl_Interp *interp; /* Interpreter containing shared literals + * referenced by the table to delete. */ + LiteralTable *tablePtr; /* Points to the literal table to delete. */ +{ + LiteralEntry *entryPtr; + int i, start; + + /* + * 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*/ + + start = 0; + while (tablePtr->numEntries > 0) { + for (i = start; i < tablePtr->numBuckets; i++) { + entryPtr = tablePtr->buckets[i]; + if (entryPtr != NULL) { + TclReleaseLiteral(interp, entryPtr->objPtr); + start = i; + break; + } + } + } + + /* + * Free up the table's bucket array if it was dynamically allocated. + */ + + if (tablePtr->buckets != tablePtr->staticBuckets) { + ckfree((char *) tablePtr->buckets); + } +} + +/* + *---------------------------------------------------------------------- + * + * 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 onHeap is 1, this procedure 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 + * onHeap 1 if "string" is an already heap-allocated buffer holding the + * result of backslash substitutions. + * + *---------------------------------------------------------------------- + */ + +int +TclRegisterLiteral(envPtr, bytes, length, onHeap) + CompileEnv *envPtr; /* 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 onHeap; /* If 1 then the caller already malloc'd + * bytes and ownership is passed to this + * procedure. */ +{ + Interp *iPtr = envPtr->iPtr; + LiteralTable *globalTablePtr = &(iPtr->literalTable); + LiteralTable *localTablePtr = &(envPtr->localLitTable); + register LiteralEntry *globalPtr, *localPtr; + register Tcl_Obj *objPtr; + unsigned int hash; + int localHash, globalHash, objIndex; + long n; + char buf[TCL_INTEGER_SPACE]; + + 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 (onHeap) { + 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. Is it in the interpreter's + * global literal table? + */ + + globalHash = (hash & globalTablePtr->mask); + for (globalPtr = globalTablePtr->buckets[globalHash]; + globalPtr != NULL; globalPtr = globalPtr->nextPtr) { + objPtr = globalPtr->objPtr; + if ((objPtr->length == length) && ((length == 0) + || ((objPtr->bytes[0] == bytes[0]) + && (memcmp(objPtr->bytes, bytes, (unsigned) length) + == 0)))) { + /* + * A global literal was found. Add an entry to the CompileEnv's + * local literal array. + */ + + if (onHeap) { + ckfree(bytes); + } + objIndex = AddLocalLiteralEntry(envPtr, globalPtr, localHash); +#ifdef TCL_COMPILE_DEBUG + if (globalPtr->refCount < 1) { + panic("TclRegisterLiteral: global literal \"%.*s\" had bad refCount %d", + (length>60? 60 : length), bytes, + globalPtr->refCount); + } + TclVerifyLocalLiteralTable(envPtr); +#endif /*TCL_COMPILE_DEBUG*/ + return objIndex; + } + } + + /* + * The literal is new to the interpreter. Add it to the global literal + * table then add an entry to the CompileEnv's local literal array. + * Convert the object to an integer object if possible. + */ + + TclNewObj(objPtr); + Tcl_IncrRefCount(objPtr); + if (onHeap) { + objPtr->bytes = bytes; + objPtr->length = length; + } else { + TclInitStringRep(objPtr, bytes, length); + } + if (TclLooksLikeInt(bytes, length)) { + if (TclGetLong((Tcl_Interp *) NULL, bytes, &n) == TCL_OK) { + TclFormatInt(buf, n); + if (strcmp(bytes, buf) == 0) { + objPtr->internalRep.longValue = n; + objPtr->typePtr = &tclIntType; + } + } + } + +#ifdef TCL_COMPILE_DEBUG + if (TclLookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) { + panic("TclRegisterLiteral: literal \"%.*s\" found globally but shouldn't be", + (length>60? 60 : length), bytes); + } +#endif + + globalPtr = (LiteralEntry *) ckalloc((unsigned) sizeof(LiteralEntry)); + globalPtr->objPtr = objPtr; + globalPtr->refCount = 0; + 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); + } + + objIndex = AddLocalLiteralEntry(envPtr, globalPtr, localHash); + +#ifdef TCL_COMPILE_DEBUG + TclVerifyGlobalLiteralTable(iPtr); + TclVerifyLocalLiteralTable(envPtr); + { + LiteralEntry *entryPtr; + int found, i; + found = 0; + for (i = 0; i < globalTablePtr->numBuckets; i++) { + for (entryPtr = globalTablePtr->buckets[i]; + entryPtr != NULL; entryPtr = entryPtr->nextPtr) { + if ((entryPtr == globalPtr) + && (entryPtr->objPtr == objPtr)) { + found = 1; + } + } + } + if (!found) { + panic("TclRegisterLiteral: literal \"%.*s\" wasn't global", + (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*/ + return objIndex; +} + +/* + *---------------------------------------------------------------------- + * + * TclLookupLiteralEntry -- + * + * 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. + * + *---------------------------------------------------------------------- + */ + +LiteralEntry * +TclLookupLiteralEntry(interp, objPtr) + 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; + char *bytes; + int length, globalHash; + + bytes = Tcl_GetStringFromObj(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; +} + +/* + *---------------------------------------------------------------------- + * + * 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: + * Increments the ref count of the global LiteralEntry since the + * CompileEnv now refers to the literal. 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(envPtr, globalPtr, localHash) + register CompileEnv *envPtr; /* Points to CompileEnv in whose literal + * array the object is to be inserted. */ + LiteralEntry *globalPtr; /* Points to the global LiteralEntry for + * the literal to add to the CompileEnv. */ + int localHash; /* Hash value for the literal's string. */ +{ + register LiteralTable *localTablePtr = &(envPtr->localLitTable); + register LiteralEntry *localPtr; + int objIndex; + + if (envPtr->literalArrayNext >= envPtr->literalArrayEnd) { + ExpandLocalLiteralArray(envPtr); + } + objIndex = envPtr->literalArrayNext; + envPtr->literalArrayNext++; + + localPtr = &(envPtr->literalArrayPtr[objIndex]); + localPtr->objPtr = globalPtr->objPtr; + localPtr->refCount = -1; /* i.e., unused */ + localPtr->nextPtr = localTablePtr->buckets[localHash]; + localTablePtr->buckets[localHash] = localPtr; + localTablePtr->numEntries++; + + globalPtr->refCount++; + + /* + * 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; i < localTablePtr->numBuckets; i++) { + for (localPtr = localTablePtr->buckets[i]; + localPtr != NULL; localPtr = localPtr->nextPtr) { + if (localPtr->objPtr == globalPtr->objPtr) { + found = 1; + } + } + } + if (!found) { + bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length); + panic("AddLocalLiteralEntry: literal \"%.*s\" wasn't found locally", + (length>60? 60 : length), bytes); + } + } +#endif /*TCL_COMPILE_DEBUG*/ + return objIndex; +} + +/* + *---------------------------------------------------------------------- + * + * ExpandLocalLiteralArray -- + * + * Procedure 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(envPtr) + 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)); + register LiteralEntry *currArrayPtr = envPtr->literalArrayPtr; + register LiteralEntry *newArrayPtr = + (LiteralEntry *) ckalloc((unsigned) (2 * currBytes)); + int i; + + /* + * Copy from the old literal array to the new, then update the local + * literal table's bucket array. + */ + + memcpy((VOID *) newArrayPtr, (VOID *) currArrayPtr, currBytes); + for (i = 0; i < currElems; i++) { + if (currArrayPtr[i].nextPtr == NULL) { + newArrayPtr[i].nextPtr = NULL; + } else { + newArrayPtr[i].nextPtr = newArrayPtr + + (currArrayPtr[i].nextPtr - currArrayPtr); + } + } + for (i = 0; i < localTablePtr->numBuckets; i++) { + if (localTablePtr->buckets[i] != NULL) { + localTablePtr->buckets[i] = newArrayPtr + + (localTablePtr->buckets[i] - currArrayPtr); + } + } + + /* + * Free the old literal array if needed, and mark the new literal + * array as malloced. + */ + + if (envPtr->mallocedLiteralArray) { + ckfree((char *) currArrayPtr); + } + envPtr->literalArrayPtr = newArrayPtr; + envPtr->literalArrayEnd = (2 * currElems); + envPtr->mallocedLiteralArray = 1; +} + +/* + *---------------------------------------------------------------------- + * + * TclReleaseLiteral -- + * + * This procedure 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(interp, objPtr) + 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 = &(iPtr->literalTable); + register LiteralEntry *entryPtr, *prevPtr; + ByteCode* codePtr; + char *bytes; + int length, index; + + bytes = Tcl_GetStringFromObj(objPtr, &length); + index = (HashString(bytes, length) & globalTablePtr->mask); + for (prevPtr = NULL, entryPtr = globalTablePtr->buckets[index]; + entryPtr != NULL; + prevPtr = entryPtr, entryPtr = entryPtr->nextPtr) { + if (entryPtr->objPtr == objPtr) { + entryPtr->refCount--; + + /* + * We found the matching LiteralEntry. Check if it's only being + * kept alive only by a circular reference from a ByteCode + * stored as its internal rep. + */ + + if ((entryPtr->refCount == 1) + && (objPtr->typePtr == &tclByteCodeType)) { + codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; + if ((codePtr->numLitObjects == 1) + && (codePtr->objArrayPtr[0] == objPtr)) { + entryPtr->refCount = 0; + + /* + * Set the ByteCode object array entry NULL to signal + * to TclCleanupByteCode to not try to release this + * about to be freed literal again. + */ + + codePtr->objArrayPtr[0] = NULL; + } + } + + /* + * If the literal is no longer being used by any ByteCode, + * delete the entry then decrement the ref count of its object. + */ + + if (entryPtr->refCount == 0) { + if (prevPtr == NULL) { + globalTablePtr->buckets[index] = entryPtr->nextPtr; + } else { + prevPtr->nextPtr = entryPtr->nextPtr; + } +#ifdef TCL_COMPILE_STATS + iPtr->stats.currentLitStringBytes -= (double) (length + 1); +#endif /*TCL_COMPILE_STATS*/ + ckfree((char *) entryPtr); + globalTablePtr->numEntries--; + TclDecrRefCount(objPtr); + } + return; + } + } +#ifdef TCL_COMPILE_DEBUG + panic("TclReleaseLiteral: literal \"%.*s\" not found", + (length>60? 60 : length), bytes); +#endif /*TCL_COMPILE_DEBUG*/ +} + +/* + *---------------------------------------------------------------------- + * + * 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 int +HashString(bytes, length) + register CONST char *bytes; /* String for which to compute hash + * value. */ + int length; /* Number of bytes in the string. */ +{ + register unsigned int result; + register int i; + + /* + * 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. + */ + + result = 0; + for (i = 0; i < length; i++) { + result += (result<<3) + *bytes++; + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * RebuildLiteralTable -- + * + * This procedure 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(tablePtr) + register LiteralTable *tablePtr; /* Local or global table to enlarge. */ +{ + LiteralEntry **oldBuckets; + register LiteralEntry **oldChainPtr, **newChainPtr; + register LiteralEntry *entryPtr; + LiteralEntry **bucketPtr; + char *bytes; + int oldSize, 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. + */ + + tablePtr->numBuckets *= 4; + tablePtr->buckets = (LiteralEntry **) ckalloc((unsigned) + (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 = Tcl_GetStringFromObj(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((char *) oldBuckets); + } +} + +#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(tablePtr) + 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; i < NUM_COUNTERS; i++) { + count[i] = 0; + } + overflow = 0; + average = 0.0; + for (i = 0; i < tablePtr->numBuckets; 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 = (char *) ckalloc((unsigned) ((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; +} +#endif /*TCL_COMPILE_STATS*/ + +#ifdef TCL_COMPILE_DEBUG +/* + *---------------------------------------------------------------------- + * + * TclVerifyLocalLiteralTable -- + * + * Check a CompileEnv's local literal table for consistency. + * + * Results: + * None. + * + * Side effects: + * Panics if problems are found. + * + *---------------------------------------------------------------------- + */ + +void +TclVerifyLocalLiteralTable(envPtr) + CompileEnv *envPtr; /* Points to CompileEnv whose literal + * table is to be validated. */ +{ + register LiteralTable *localTablePtr = &(envPtr->localLitTable); + register LiteralEntry *localPtr; + char *bytes; + register int i; + int length, count; + + count = 0; + for (i = 0; i < localTablePtr->numBuckets; i++) { + for (localPtr = localTablePtr->buckets[i]; + localPtr != NULL; localPtr = localPtr->nextPtr) { + count++; + if (localPtr->refCount != -1) { + bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length); + panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" had bad refCount %d", + (length>60? 60 : length), bytes, + localPtr->refCount); + } + if (TclLookupLiteralEntry((Tcl_Interp *) envPtr->iPtr, + localPtr->objPtr) == NULL) { + bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length); + panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" is not global", + (length>60? 60 : length), bytes); + } + if (localPtr->objPtr->bytes == NULL) { + panic("TclVerifyLocalLiteralTable: literal has NULL string rep"); + } + } + } + if (count != localTablePtr->numEntries) { + panic("TclVerifyLocalLiteralTable: local literal table had %d entries, should be %d", + count, localTablePtr->numEntries); + } +} + +/* + *---------------------------------------------------------------------- + * + * TclVerifyGlobalLiteralTable -- + * + * Check an interpreter's global literal table literal for consistency. + * + * Results: + * None. + * + * Side effects: + * Panics if problems are found. + * + *---------------------------------------------------------------------- + */ + +void +TclVerifyGlobalLiteralTable(iPtr) + 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; i < globalTablePtr->numBuckets; i++) { + for (globalPtr = globalTablePtr->buckets[i]; + globalPtr != NULL; globalPtr = globalPtr->nextPtr) { + count++; + if (globalPtr->refCount < 1) { + bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length); + panic("TclVerifyGlobalLiteralTable: global literal \"%.*s\" had bad refCount %d", + (length>60? 60 : length), bytes, + globalPtr->refCount); + } + if (globalPtr->objPtr->bytes == NULL) { + panic("TclVerifyGlobalLiteralTable: literal has NULL string rep"); + } + } + } + if (count != globalTablePtr->numEntries) { + panic("TclVerifyGlobalLiteralTable: global literal table had %d entries, should be %d", + count, globalTablePtr->numEntries); + } +} +#endif /*TCL_COMPILE_DEBUG*/ Index: generic/tclLoad.c ================================================================== --- generic/tclLoad.c +++ generic/tclLoad.c @@ -2,24 +2,24 @@ * 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 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclLoad.c 1.17 97/07/24 20:05:04 + * RCS: @(#) $Id: tclLoad.c,v 1.1.2.6 1999/04/14 00:33:24 surles Exp $ */ #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 Tcl_PackageLoaded). All such packages + * indicated by a call to TclGetLoadedPackages). All such packages * are linked together into a single list for the process. Packages * are never unloaded, so these structures are never freed. */ typedef struct LoadedPackage { @@ -29,10 +29,14 @@ * Malloc-ed. */ char *packageName; /* Name of package prefix for the package, * properly capitalized (first letter UC, * others LC), no "_", as in "Net". * Malloc-ed. */ + ClientData clientData; /* Token for the loaded file which should be + * passed to TclpUnloadFile() when the file + * is no longer needed. If fileName is NULL, + * then this field is irrelevant. */ Tcl_PackageInitProc *initProc; /* Initialization procedure to call to * incorporate this package into a trusted * interpreter. */ Tcl_PackageInitProc *safeInitProc; @@ -46,13 +50,21 @@ /* 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 procedure). There is a list of these structures for @@ -72,16 +84,15 @@ * Prototypes for procedures that are private to this file: */ static void LoadCleanupProc _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp)); -static void LoadExitProc _ANSI_ARGS_((ClientData clientData)); /* *---------------------------------------------------------------------- * - * Tcl_LoadCmd -- + * Tcl_LoadObjCmd -- * * This procedure is invoked to process the "load" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -92,42 +103,49 @@ * *---------------------------------------------------------------------- */ int -Tcl_LoadCmd(dummy, interp, argc, argv) - ClientData dummy; /* Not used. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ +Tcl_LoadObjCmd(dummy, interp, objc, objv) + 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, initName, safeInitName, fileName; + Tcl_DString pkgName, tmp, initName, safeInitName, fileName; Tcl_PackageInitProc *initProc, *safeInitProc; InterpPackage *ipFirstPtr, *ipPtr; - int code, c, gotPkgName, namesMatch, filesMatch; - char *p, *fullFileName, *p1, *p2; + int code, namesMatch, filesMatch; + char *p, *tempString, *fullFileName, *packageName; + ClientData clientData; + Tcl_UniChar ch; + int offset; - if ((argc < 2) || (argc > 4)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " fileName ?packageName? ?interp?\"", (char *) NULL); + if ((objc < 2) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 1, objv, "fileName ?packageName? ?interp?"); return TCL_ERROR; } - fullFileName = Tcl_TranslateFileName(interp, argv[1], &fileName); + tempString = Tcl_GetString(objv[1]); + fullFileName = Tcl_TranslateFileName(interp, tempString, &fileName); if (fullFileName == NULL) { return TCL_ERROR; } Tcl_DStringInit(&pkgName); Tcl_DStringInit(&initName); Tcl_DStringInit(&safeInitName); - if ((argc >= 3) && (argv[2][0] != 0)) { - gotPkgName = 1; - } else { - gotPkgName = 0; + Tcl_DStringInit(&tmp); + + packageName = NULL; + if (objc >= 3) { + packageName = Tcl_GetString(objv[2]); + if (packageName[0] == '\0') { + packageName = NULL; + } } - if ((fullFileName[0] == 0) && !gotPkgName) { + if ((fullFileName[0] == 0) && (packageName == NULL)) { Tcl_SetResult(interp, "must specify either file name or package name", TCL_STATIC); code = TCL_ERROR; goto done; @@ -136,15 +154,15 @@ /* * Figure out which interpreter we're going to load the package into. */ target = interp; - if (argc == 4) { - target = Tcl_GetSlave(interp, argv[3]); + if (objc == 4) { + char *slaveIntName; + slaveIntName = Tcl_GetString(objv[3]); + target = Tcl_GetSlave(interp, slaveIntName); if (target == NULL) { - Tcl_AppendResult(interp, "couldn't find slave interpreter named \"", - argv[3], "\"", (char *) NULL); return TCL_ERROR; } } /* @@ -154,30 +172,34 @@ * - 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 (!gotPkgName) { + if (packageName == NULL) { namesMatch = 0; } else { - namesMatch = 1; - for (p1 = argv[2], p2 = pkgPtr->packageName; ; p1++, p2++) { - if ((isupper(UCHAR(*p1)) ? tolower(UCHAR(*p1)) : *p1) - != (isupper(UCHAR(*p2)) ? tolower(UCHAR(*p2)) : *p2)) { - namesMatch = 0; - break; - } - if (*p1 == 0) { - break; - } + Tcl_DStringSetLength(&pkgName, 0); + Tcl_DStringAppend(&pkgName, packageName, -1); + Tcl_DStringSetLength(&tmp, 0); + 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; } } + Tcl_DStringSetLength(&pkgName, 0); + filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0); - if (filesMatch && (namesMatch || !gotPkgName)) { + if (filesMatch && (namesMatch || (packageName == NULL))) { break; } if (namesMatch && (fullFileName[0] == 0)) { defaultPtr = pkgPtr; } @@ -189,13 +211,15 @@ Tcl_AppendResult(interp, "file \"", fullFileName, "\" is already loaded for package \"", pkgPtr->packageName, "\"", (char *) NULL); code = TCL_ERROR; + Tcl_MutexUnlock(&packageMutex); goto done; } } + Tcl_MutexUnlock(&packageMutex); if (pkgPtr == NULL) { pkgPtr = defaultPtr; } /* @@ -220,24 +244,29 @@ * 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_AppendResult(interp, "package \"", argv[2], + Tcl_AppendResult(interp, "package \"", packageName, "\" isn't loaded statically", (char *) NULL); code = TCL_ERROR; goto done; } /* * Figure out the module name if it wasn't provided explicitly. */ - if (gotPkgName) { - Tcl_DStringAppend(&pkgName, argv[2], -1); + if (packageName != NULL) { + Tcl_DStringAppend(&pkgName, packageName, -1); } else { - if (!TclGuessPackageName(fullFileName, &pkgName)) { + int retc; + /* + * Threading note - this call used to be protected by a mutex. + */ + retc = TclGuessPackageName(fullFileName, &pkgName); + if (!retc) { int pargc; char **pargv, *pkgGuess; /* * The platform-specific code couldn't figure out the @@ -251,12 +280,17 @@ pkgGuess = pargv[pargc-1]; if ((pkgGuess[0] == 'l') && (pkgGuess[1] == 'i') && (pkgGuess[2] == 'b')) { pkgGuess += 3; } - for (p = pkgGuess; isalpha(UCHAR(*p)) || (*p == '_'); p++) { - /* Empty loop body. */ + 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) { ckfree((char *)pargv); Tcl_AppendResult(interp, "couldn't figure out package name for ", @@ -269,31 +303,16 @@ } } /* * Fix the capitalization in the package name so that the first - * character is in caps but the others are all lower-case. + * character is in caps (or title case) but the others are all + * lower-case. */ - p = Tcl_DStringValue(&pkgName); - c = UCHAR(*p); - if (c != 0) { - if (islower(c)) { - *p = (char) toupper(c); - } - p++; - while (1) { - c = UCHAR(*p); - if (c == 0) { - break; - } - if (isupper(c)) { - *p = (char) tolower(c); - } - p++; - } - } + Tcl_DStringSetLength(&pkgName, + Tcl_UtfToTitle(Tcl_DStringValue(&pkgName))); /* * Compute the names of the two initialization procedures, * based on the package name. */ @@ -300,46 +319,50 @@ Tcl_DStringAppend(&initName, Tcl_DStringValue(&pkgName), -1); Tcl_DStringAppend(&initName, "_Init", 5); Tcl_DStringAppend(&safeInitName, Tcl_DStringValue(&pkgName), -1); Tcl_DStringAppend(&safeInitName, "_SafeInit", 9); - + /* * Call platform-specific code to load the package and find the * two initialization procedures. */ - - code = TclLoadFile(interp, fullFileName, Tcl_DStringValue(&initName), - Tcl_DStringValue(&safeInitName), &initProc, &safeInitProc); + + Tcl_MutexLock(&packageMutex); + code = TclpLoadFile(interp, fullFileName, Tcl_DStringValue(&initName), + Tcl_DStringValue(&safeInitName), &initProc, &safeInitProc, + &clientData); + Tcl_MutexUnlock(&packageMutex); if (code != TCL_OK) { goto done; } - if (initProc == NULL) { + if (initProc == NULL) { Tcl_AppendResult(interp, "couldn't find procedure ", Tcl_DStringValue(&initName), (char *) NULL); + TclpUnloadFile(clientData); code = TCL_ERROR; goto done; } /* * Create a new record to describe this package. */ - if (firstPackagePtr == NULL) { - Tcl_CreateExitHandler(LoadExitProc, (ClientData) NULL); - } pkgPtr = (LoadedPackage *) ckalloc(sizeof(LoadedPackage)); - pkgPtr->fileName = (char *) ckalloc((unsigned) + pkgPtr->fileName = (char *) ckalloc((unsigned) (strlen(fullFileName) + 1)); strcpy(pkgPtr->fileName, fullFileName); - pkgPtr->packageName = (char *) ckalloc((unsigned) + pkgPtr->packageName = (char *) ckalloc((unsigned) (Tcl_DStringLength(&pkgName) + 1)); strcpy(pkgPtr->packageName, Tcl_DStringValue(&pkgName)); - pkgPtr->initProc = initProc; - pkgPtr->safeInitProc = safeInitProc; - pkgPtr->nextPtr = firstPackagePtr; - firstPackagePtr = pkgPtr; + pkgPtr->clientData = clientData; + pkgPtr->initProc = initProc; + pkgPtr->safeInitProc = safeInitProc; + Tcl_MutexLock(&packageMutex); + pkgPtr->nextPtr = firstPackagePtr; + firstPackagePtr = pkgPtr; + Tcl_MutexUnlock(&packageMutex); } /* * Invoke the package's initialization procedure (either the * normal one or the safe one, depending on whether or not the @@ -358,32 +381,10 @@ goto done; } } else { code = (*pkgPtr->initProc)(target); } - if ((code == TCL_ERROR) && (target != interp)) { - /* - * An error occurred, so transfer error information from the - * destination interpreter back to our interpreter. Must clear - * interp's result before calling Tcl_AddErrorInfo, since - * Tcl_AddErrorInfo will store the interp's result in errorInfo - * before appending target's $errorInfo; we've already got - * everything we need in target's $errorInfo. - */ - - /* - * It is (abusively) assumed that errorInfo and errorCode vars exists. - * we changed SetVar2 to accept NULL values to avoid crashes. --dl - */ - Tcl_ResetResult(interp); - Tcl_AddErrorInfo(interp, Tcl_GetVar2(target, - "errorInfo", (char *) NULL, TCL_GLOBAL_ONLY)); - Tcl_SetVar2(interp, "errorCode", (char *) NULL, - Tcl_GetVar2(target, "errorCode", (char *) NULL, - TCL_GLOBAL_ONLY), TCL_GLOBAL_ONLY); - Tcl_SetResult(interp, target->result, TCL_VOLATILE); - } /* * Record the fact that the package has been loaded in the * target interpreter. */ @@ -399,17 +400,20 @@ ipPtr = (InterpPackage *) ckalloc(sizeof(InterpPackage)); ipPtr->pkgPtr = pkgPtr; ipPtr->nextPtr = ipFirstPtr; Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, (ClientData) ipPtr); + } else { + TclTransferResult(target, code, interp); } done: Tcl_DStringFree(&pkgName); Tcl_DStringFree(&initName); Tcl_DStringFree(&safeInitName); Tcl_DStringFree(&fileName); + Tcl_DStringFree(&tmp); return code; } /* *---------------------------------------------------------------------- @@ -454,31 +458,35 @@ /* * Check to see if someone else has already reported this package as * statically loaded. If this call is redundant then just return. */ + Tcl_MutexLock(&packageMutex); for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) { if ((pkgPtr->initProc == initProc) && (pkgPtr->safeInitProc == safeInitProc) && (strcmp(pkgPtr->packageName, pkgName) == 0)) { + Tcl_MutexUnlock(&packageMutex); return; } } - if (firstPackagePtr == NULL) { - Tcl_CreateExitHandler(LoadExitProc, (ClientData) NULL); - } + Tcl_MutexUnlock(&packageMutex); + pkgPtr = (LoadedPackage *) ckalloc(sizeof(LoadedPackage)); - pkgPtr->fileName = (char *) ckalloc((unsigned) 1); - pkgPtr->fileName[0] = 0; - pkgPtr->packageName = (char *) ckalloc((unsigned) + pkgPtr->fileName = (char *) ckalloc((unsigned) 1); + pkgPtr->fileName[0] = 0; + pkgPtr->packageName = (char *) ckalloc((unsigned) (strlen(pkgName) + 1)); strcpy(pkgPtr->packageName, pkgName); - pkgPtr->initProc = initProc; - pkgPtr->safeInitProc = safeInitProc; - pkgPtr->nextPtr = firstPackagePtr; - firstPackagePtr = pkgPtr; + pkgPtr->clientData = NULL; + pkgPtr->initProc = initProc; + pkgPtr->safeInitProc = safeInitProc; + Tcl_MutexLock(&packageMutex); + pkgPtr->nextPtr = firstPackagePtr; + firstPackagePtr = pkgPtr; + Tcl_MutexUnlock(&packageMutex); if (interp != NULL) { ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(interp, "tclLoad", (Tcl_InterpDeleteProc **) NULL); ipPtr = (InterpPackage *) ckalloc(sizeof(InterpPackage)); @@ -498,11 +506,11 @@ * 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 interp->result. + * 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. * @@ -530,18 +538,20 @@ /* * Return information about all of the available packages. */ prefix = "{"; + Tcl_MutexLock(&packageMutex); for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) { Tcl_AppendResult(interp, prefix, (char *) NULL); Tcl_AppendElement(interp, pkgPtr->fileName); Tcl_AppendElement(interp, pkgPtr->packageName); Tcl_AppendResult(interp, "}", (char *) NULL); prefix = " {"; } + Tcl_MutexUnlock(&packageMutex); return TCL_OK; } /* * Return information about only the packages that are loaded in @@ -548,12 +558,10 @@ * a given interpreter. */ target = Tcl_GetSlave(interp, targetName); if (target == NULL) { - Tcl_AppendResult(interp, "couldn't find slave interpreter named \"", - targetName, "\"", (char *) NULL); return TCL_ERROR; } ipPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad", (Tcl_InterpDeleteProc **) NULL); prefix = "{"; @@ -604,11 +612,11 @@ } /* *---------------------------------------------------------------------- * - * LoadExitProc -- + * TclFinalizeLoad -- * * This procedure is invoked just before the application exits. * It frees all of the LoadedPackage structures. * * Results: @@ -618,19 +626,30 @@ * Memory is freed. * *---------------------------------------------------------------------- */ -static void -LoadExitProc(clientData) - ClientData clientData; /* Not used. */ +void +TclFinalizeLoad() { 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 (pkgPtr->fileName[0] != '\0') { + TclpUnloadFile(pkgPtr->clientData); + } ckfree(pkgPtr->fileName); ckfree(pkgPtr->packageName); ckfree((char *) pkgPtr); } } Index: generic/tclLoadNone.c ================================================================== --- generic/tclLoadNone.c +++ generic/tclLoadNone.c @@ -3,16 +3,16 @@ * * This procedure provides a version of the TclLoadFile for use * in systems that don't support dynamic loading; it just returns * an error. * - * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclLoadNone.c 1.6 97/05/14 13:23:38 + * RCS: @(#) $Id: tclLoadNone.c,v 1.1.2.2 1998/09/24 23:58:56 stanton Exp $ */ #include "tclInt.h" /* @@ -24,11 +24,11 @@ * 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 - * interp->result. + * the interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- Index: generic/tclMain.c ================================================================== --- generic/tclMain.c +++ generic/tclMain.c @@ -2,21 +2,24 @@ * tclMain.c -- * * Main program for Tcl shells and other Tcl-based applications. * * Copyright (c) 1988-1994 The Regents of the University of California. - * Copyright (c) 1994-1996 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclMain.c 1.54 97/08/07 19:04:43 + * RCS: @(#) $Id: tclMain.c,v 1.1.2.4 1999/02/10 23:31:17 stanton Exp $ */ #include "tcl.h" #include "tclInt.h" +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT + /* * The following code ensures that tclLink.c is linked whenever * Tcl is linked. Without this code there's no reference to the * code in that file from anywhere in Tcl, so it may not be * linked into the application. @@ -35,28 +38,10 @@ */ extern int isatty _ANSI_ARGS_((int fd)); extern char * strcpy _ANSI_ARGS_((char *dst, CONST char *src)); -static Tcl_Interp *interp; /* Interpreter for application. */ - -#ifdef TCL_MEM_DEBUG -static char dumpFile[100]; /* Records where to dump memory allocation - * information. */ -static int quitFlag = 0; /* 1 means "checkmem" command was called, - * so the application should quit and dump - * memory allocation information. */ -#endif - -/* - * Forward references for procedures defined later in this file: - */ - -#ifdef TCL_MEM_DEBUG -static int CheckmemCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char *argv[])); -#endif /* *---------------------------------------------------------------------- * * Tcl_Main -- @@ -83,25 +68,23 @@ /* Application-specific initialization * procedure to call after most * initialization but before starting to * execute commands. */ { - Tcl_Obj *prompt1NamePtr = NULL; - Tcl_Obj *prompt2NamePtr = NULL; Tcl_Obj *resultPtr; Tcl_Obj *commandPtr = NULL; - char buffer[1000], *args, *fileName, *bytes; + char buffer[1000], *args, *fileName; int code, gotPartial, tty, length; int exitCode = 0; Tcl_Channel inChannel, outChannel, errChannel; + Tcl_Interp *interp; + Tcl_DString argString; Tcl_FindExecutable(argv[0]); interp = Tcl_CreateInterp(); #ifdef TCL_MEM_DEBUG Tcl_InitMemory(interp); - Tcl_CreateCommand(interp, "checkmem", CheckmemCmd, (ClientData) 0, - (Tcl_CmdDeleteProc *) NULL); #endif /* * Make command-line arguments available in the Tcl variables "argc" * and "argv". If the first argument doesn't start with a "-" then @@ -113,16 +96,24 @@ fileName = argv[1]; argc--; argv++; } args = Tcl_Merge(argc-1, argv+1); - Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY); + Tcl_ExternalToUtfDString(NULL, args, -1, &argString); + Tcl_SetVar(interp, "argv", Tcl_DStringValue(&argString), TCL_GLOBAL_ONLY); + Tcl_DStringFree(&argString); ckfree(args); + + if (fileName == NULL) { + Tcl_ExternalToUtfDString(NULL, argv[0], -1, &argString); + } else { + fileName = Tcl_ExternalToUtfDString(NULL, fileName, -1, &argString); + } + TclFormatInt(buffer, argc-1); Tcl_SetVar(interp, "argc", buffer, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "argv0", (fileName != NULL) ? fileName : argv[0], - TCL_GLOBAL_ONLY); + Tcl_SetVar(interp, "argv0", Tcl_DStringValue(&argString), TCL_GLOBAL_ONLY); /* * Set the "tcl_interactive" variable. */ @@ -135,14 +126,14 @@ */ if ((*appInitProc)(interp) != TCL_OK) { errChannel = Tcl_GetStdChannel(TCL_STDERR); if (errChannel) { - Tcl_Write(errChannel, + Tcl_WriteChars(errChannel, "application-specific initialization failed: ", -1); - Tcl_Write(errChannel, interp->result, -1); - Tcl_Write(errChannel, "\n", 1); + Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)); + Tcl_WriteChars(errChannel, "\n", 1); } } /* * If a script file was specified then just source that file @@ -158,18 +149,19 @@ * The following statement guarantees that the errorInfo * variable is set properly. */ Tcl_AddErrorInfo(interp, ""); - Tcl_Write(errChannel, - Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY), -1); - Tcl_Write(errChannel, "\n", 1); + Tcl_WriteObj(errChannel, Tcl_GetVar2Ex(interp, "errorInfo", + NULL, TCL_GLOBAL_ONLY)); + Tcl_WriteChars(errChannel, "\n", 1); } exitCode = 1; } goto done; } + Tcl_DStringFree(&argString); /* * We're running interactively. Source a user-specific startup * file if the application specified one and if the file exists. */ @@ -182,41 +174,35 @@ * eval, since they may have been changed. */ commandPtr = Tcl_NewObj(); Tcl_IncrRefCount(commandPtr); - prompt1NamePtr = Tcl_NewStringObj("tcl_prompt1", -1); - Tcl_IncrRefCount(prompt1NamePtr); - prompt2NamePtr = Tcl_NewStringObj("tcl_prompt2", -1); - Tcl_IncrRefCount(prompt2NamePtr); - + inChannel = Tcl_GetStdChannel(TCL_STDIN); outChannel = Tcl_GetStdChannel(TCL_STDOUT); gotPartial = 0; while (1) { if (tty) { Tcl_Obj *promptCmdPtr; - promptCmdPtr = Tcl_ObjGetVar2(interp, - (gotPartial? prompt2NamePtr : prompt1NamePtr), - (Tcl_Obj *) NULL, TCL_GLOBAL_ONLY); + promptCmdPtr = Tcl_GetVar2Ex(interp, + (gotPartial ? "tcl_prompt2" : "tcl_prompt1"), + NULL, TCL_GLOBAL_ONLY); if (promptCmdPtr == NULL) { defaultPrompt: if (!gotPartial && outChannel) { - Tcl_Write(outChannel, "% ", 2); + Tcl_WriteChars(outChannel, "% ", 2); } } else { - code = Tcl_EvalObj(interp, promptCmdPtr); + code = Tcl_EvalObjEx(interp, promptCmdPtr, 0); inChannel = Tcl_GetStdChannel(TCL_STDIN); outChannel = Tcl_GetStdChannel(TCL_STDOUT); errChannel = Tcl_GetStdChannel(TCL_STDERR); if (code != TCL_OK) { if (errChannel) { - resultPtr = Tcl_GetObjResult(interp); - bytes = Tcl_GetStringFromObj(resultPtr, &length); - Tcl_Write(errChannel, bytes, length); - Tcl_Write(errChannel, "\n", 1); + Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)); + Tcl_WriteChars(errChannel, "\n", 1); } Tcl_AddErrorInfo(interp, "\n (script that generates prompt)"); goto defaultPrompt; } @@ -252,28 +238,24 @@ outChannel = Tcl_GetStdChannel(TCL_STDOUT); errChannel = Tcl_GetStdChannel(TCL_STDERR); Tcl_SetObjLength(commandPtr, 0); if (code != TCL_OK) { if (errChannel) { - resultPtr = Tcl_GetObjResult(interp); - bytes = Tcl_GetStringFromObj(resultPtr, &length); - Tcl_Write(errChannel, bytes, length); - Tcl_Write(errChannel, "\n", 1); + Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)); + Tcl_WriteChars(errChannel, "\n", 1); } } else if (tty) { resultPtr = Tcl_GetObjResult(interp); - bytes = Tcl_GetStringFromObj(resultPtr, &length); + Tcl_GetStringFromObj(resultPtr, &length); if ((length > 0) && outChannel) { - Tcl_Write(outChannel, bytes, length); - Tcl_Write(outChannel, "\n", 1); + Tcl_WriteObj(outChannel, resultPtr); + Tcl_WriteChars(outChannel, "\n", 1); } } #ifdef TCL_MEM_DEBUG - if (quitFlag) { + if (tclMemDumpFileName != NULL) { Tcl_DecrRefCount(commandPtr); - Tcl_DecrRefCount(prompt1NamePtr); - Tcl_DecrRefCount(prompt2NamePtr); Tcl_DeleteInterp(interp); Tcl_Exit(0); } #endif } @@ -286,55 +268,8 @@ done: if (commandPtr != NULL) { Tcl_DecrRefCount(commandPtr); } - if (prompt1NamePtr != NULL) { - Tcl_DecrRefCount(prompt1NamePtr); - } - if (prompt2NamePtr != NULL) { - Tcl_DecrRefCount(prompt2NamePtr); - } sprintf(buffer, "exit %d", exitCode); Tcl_Eval(interp, buffer); } - -/* - *---------------------------------------------------------------------- - * - * 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. - * - *---------------------------------------------------------------------- - */ -#ifdef TCL_MEM_DEBUG - - /* ARGSUSED */ -static int -CheckmemCmd(clientData, interp, argc, argv) - ClientData clientData; /* Not used. */ - Tcl_Interp *interp; /* Interpreter for evaluation. */ - int argc; /* Number of arguments. */ - char *argv[]; /* String values of arguments. */ -{ - extern char *tclMemDumpFileName; - if (argc != 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " fileName\"", (char *) NULL); - return TCL_ERROR; - } - strcpy(dumpFile, argv[1]); - tclMemDumpFileName = dumpFile; - quitFlag = 1; - return TCL_OK; -} -#endif Index: generic/tclMath.h ================================================================== --- generic/tclMath.h +++ generic/tclMath.h @@ -10,11 +10,11 @@ * 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. * - * SCCS: @(#) tclMath.h 1.2 97/07/23 17:39:14 + * RCS: @(#) $Id: tclMath.h,v 1.1.2.1 1998/09/24 23:58:57 stanton Exp $ */ #ifndef _TCLMATH #define _TCLMATH Index: generic/tclNamesp.c ================================================================== --- generic/tclNamesp.c +++ generic/tclNamesp.c @@ -7,20 +7,21 @@ * 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. * * Originally implemented by * Michael J. McLennan * Bell Labs Innovations for Lucent Technologies * mmclennan@lucent.com * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclNamesp.c 1.29 97/08/04 09:32:38 + * RCS: @(#) $Id: tclNamesp.c,v 1.1.2.8 1999/03/26 22:39:53 rjohnson Exp $ */ #include "tclInt.h" /* @@ -30,31 +31,24 @@ * of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, or CREATE_NS_IF_UNKNOWN. */ #define FIND_ONLY_NS 0x1000 +/* + * Initial size of stack allocated space for tail list - used when resetting + * shadowed command references in the functin: TclResetShadowedCmdRefs. + */ + +#define NUM_TRAIL_ELEMS 5 + /* * Count of the number of namespaces created. This value is used as a * unique id for each namespace. */ static long numNsCreated = 0; - -/* - * 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 { - Command *realCmdPtr; /* "Real" command that this imported command - * refers to. */ - 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; +TCL_DECLARE_MUTEX(nsMutex) /* * 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 @@ -154,43 +148,32 @@ FreeNsNameInternalRep, /* freeIntRepProc */ DupNsNameInternalRep, /* dupIntRepProc */ UpdateStringOfNsName, /* updateStringProc */ SetNsNameFromAny /* setFromAnyProc */ }; - -/* - * Boolean flag indicating whether or not the namespName object - * type has been registered with the Tcl compiler. - */ - -static int nsInitialized = 0; /* *---------------------------------------------------------------------- * - * TclInitNamespaces -- + * TclInitNamespaceSubsystem -- * - * Called when any interpreter is created to make sure that - * things are properly set up for namespaces. + * This procedure is called to initialize all the structures that + * are used by namespaces on a per-process basis. * * Results: * None. * * Side effects: - * On the first call, the namespName object type is registered - * with the Tcl compiler. + * The namespace object type is registered with the Tcl compiler. * *---------------------------------------------------------------------- */ void -TclInitNamespaces() +TclInitNamespaceSubsystem() { - if (!nsInitialized) { - Tcl_RegisterObjType(&tclNsNameType); - nsInitialized = 1; - } + Tcl_RegisterObjType(&tclNsNameType); } /* *---------------------------------------------------------------------- * @@ -303,15 +286,12 @@ if (namespacePtr == NULL) { nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); } else { nsPtr = (Namespace *) namespacePtr; if (nsPtr->flags & NS_DEAD) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "namespace \"", - nsPtr->fullName, "\" not found in context \"", - Tcl_GetCurrentNamespace(interp)->fullName, "\"", - (char *) NULL); - return TCL_ERROR; + panic("Trying to push call frame for dead namespace"); + /*NOTREACHED*/ } } nsPtr->activationCount++; framePtr->nsPtr = nsPtr; @@ -463,11 +443,11 @@ Namespace *parentPtr, *dummy1Ptr, *dummy2Ptr; Namespace *globalNsPtr = iPtr->globalNsPtr; char *simpleName; Tcl_HashEntry *entryPtr; Tcl_DString buffer1, buffer2; - int newEntry, result; + int newEntry; /* * If there is no active namespace, the interpreter is being * initialized. */ @@ -487,17 +467,13 @@ } else { /* * Find the parent for the new namespace. */ - result = TclGetNamespaceForQualName(interp, name, - (Namespace *) NULL, + TclGetNamespaceForQualName(interp, name, (Namespace *) NULL, /*flags*/ (CREATE_NS_IF_UNKNOWN | TCL_LEAVE_ERR_MSG), &parentPtr, &dummy1Ptr, &dummy2Ptr, &simpleName); - if (result != TCL_OK) { - return NULL; - } /* * 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 @@ -524,31 +500,37 @@ /* * Create the new namespace and root it in its parent. Increment the * count of namespaces created. */ - numNsCreated++; nsPtr = (Namespace *) ckalloc(sizeof(Namespace)); nsPtr->name = (char *) ckalloc((unsigned) (strlen(simpleName)+1)); strcpy(nsPtr->name, simpleName); nsPtr->fullName = NULL; /* set below */ nsPtr->clientData = clientData; nsPtr->deleteProc = deleteProc; nsPtr->parentPtr = parentPtr; Tcl_InitHashTable(&nsPtr->childTable, TCL_STRING_KEYS); + Tcl_MutexLock(&nsMutex); + numNsCreated++; nsPtr->nsId = numNsCreated; + Tcl_MutexUnlock(&nsMutex); nsPtr->interp = interp; nsPtr->flags = 0; nsPtr->activationCount = 0; nsPtr->refCount = 0; Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS); Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS); nsPtr->exportArrayPtr = NULL; nsPtr->numExportPatterns = 0; nsPtr->maxExportPatterns = 0; - nsPtr->cmdRefEpoch = 0; + nsPtr->cmdRefEpoch = 0; + nsPtr->resolverEpoch = 0; + nsPtr->cmdResProc = NULL; + nsPtr->varResProc = NULL; + nsPtr->compiledVarResProc = NULL; if (parentPtr != NULL) { entryPtr = Tcl_CreateHashEntry(&parentPtr->childTable, simpleName, &newEntry); Tcl_SetHashValue(entryPtr, (ClientData) nsPtr); @@ -882,10 +864,11 @@ ckfree(nsPtr->name); ckfree(nsPtr->fullName); ckfree((char *) nsPtr); } + /* *---------------------------------------------------------------------- * * Tcl_Export -- @@ -926,11 +909,11 @@ { #define INIT_EXPORT_PATTERNS 5 Namespace *nsPtr, *exportNsPtr, *dummyPtr; Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); char *simplePattern, *patternCpy; - int neededElems, len, i, result; + int neededElems, len, i; /* * If the specified namespace is NULL, use the current namespace. */ @@ -959,16 +942,14 @@ /* * Check that the pattern doesn't have namespace qualifiers. */ - result = TclGetNamespaceForQualName(interp, pattern, nsPtr, + TclGetNamespaceForQualName(interp, pattern, nsPtr, /*flags*/ TCL_LEAVE_ERR_MSG, &exportNsPtr, &dummyPtr, &dummyPtr, &simplePattern); - if (result != TCL_OK) { - return result; - } + if ((exportNsPtr != nsPtr) || (strcmp(pattern, simplePattern) != 0)) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "invalid export pattern \"", pattern, "\": pattern can't specify a namespace", (char *) NULL); @@ -1078,10 +1059,14 @@ * Imports all of the commands matching a pattern into the namespace * specified by contextNsPtr (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: @@ -1111,13 +1096,13 @@ Namespace *nsPtr, *importNsPtr, *dummyPtr; Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); char *simplePattern, *cmdName; register Tcl_HashEntry *hPtr; Tcl_HashSearch search; - Command *cmdPtr; + Command *cmdPtr, *realCmdPtr; ImportRef *refPtr; - Tcl_Command importedCmd; + Tcl_Command autoCmd, importedCmd; ImportedCmdData *dataPtr; int wasExported, i, result; /* * If the specified namespace is NULL, use the current namespace. @@ -1126,10 +1111,42 @@ if (namespacePtr == NULL) { nsPtr = (Namespace *) currNsPtr; } 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. + */ + + autoCmd = Tcl_FindCommand(interp, "auto_import", + (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY); + + if (autoCmd != NULL) { + Tcl_Obj *objv[2]; + + objv[0] = Tcl_NewStringObj("auto_import", -1); + Tcl_IncrRefCount(objv[0]); + objv[1] = Tcl_NewStringObj(pattern, -1); + Tcl_IncrRefCount(objv[1]); + + cmdPtr = (Command *) autoCmd; + result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, + 2, objv); + + 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. @@ -1138,16 +1155,14 @@ if (strlen(pattern) == 0) { Tcl_SetStringObj(Tcl_GetObjResult(interp), "empty import pattern", -1); return TCL_ERROR; } - result = TclGetNamespaceForQualName(interp, pattern, nsPtr, + TclGetNamespaceForQualName(interp, pattern, nsPtr, /*flags*/ TCL_LEAVE_ERR_MSG, &importNsPtr, &dummyPtr, &dummyPtr, &simplePattern); - if (result != TCL_OK) { - return TCL_ERROR; - } + if (importNsPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "unknown namespace in import pattern \"", pattern, "\"", (char *) NULL); return TCL_ERROR; @@ -1210,17 +1225,39 @@ */ Tcl_DString ds; Tcl_DStringInit(&ds); - Tcl_DStringAppend(&ds, currNsPtr->fullName, -1); - if (currNsPtr != iPtr->globalNsPtr) { + Tcl_DStringAppend(&ds, nsPtr->fullName, -1); + if (nsPtr != iPtr->globalNsPtr) { Tcl_DStringAppend(&ds, "::", 2); } Tcl_DStringAppend(&ds, cmdName, -1); - + + /* + * Check whether creating the new imported command in the + * current namespace would create a cycle of imported->real + * command references that also would destroy an existing + * "real" command already in the current namespace. + */ + cmdPtr = (Command *) Tcl_GetHashValue(hPtr); + if (cmdPtr->deleteProc == DeleteImportedCmd) { + realCmdPtr = (Command *) TclGetOriginalCommand( + (Tcl_Command) cmdPtr); + if ((realCmdPtr != NULL) + && (realCmdPtr->nsPtr == currNsPtr) + && (Tcl_FindHashEntry(&currNsPtr->cmdTable, + cmdName) != NULL)) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "import pattern \"", pattern, + "\" would create a loop containing command \"", + Tcl_DStringValue(&ds), "\"", (char *) NULL); + return TCL_ERROR; + } + } + dataPtr = (ImportedCmdData *) ckalloc(sizeof(ImportedCmdData)); importedCmd = Tcl_CreateObjCommand(interp, Tcl_DStringValue(&ds), InvokeImportedCmd, (ClientData) dataPtr, DeleteImportedCmd); @@ -1286,11 +1323,10 @@ Namespace *nsPtr, *importNsPtr, *dummyPtr, *actualCtxPtr; char *simplePattern, *cmdName; register Tcl_HashEntry *hPtr; Tcl_HashSearch search; Command *cmdPtr; - int result; /* * If the specified namespace is NULL, use the current namespace. */ @@ -1304,16 +1340,14 @@ * From the pattern, find the namespace from which we are importing * and get the simple pattern (no namespace qualifiers or ::'s) at * the end. */ - result = TclGetNamespaceForQualName(interp, pattern, nsPtr, + TclGetNamespaceForQualName(interp, pattern, nsPtr, /*flags*/ TCL_LEAVE_ERR_MSG, &importNsPtr, &dummyPtr, &actualCtxPtr, &simplePattern); - if (result != TCL_OK) { - return result; - } + if (importNsPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "unknown namespace in namespace forget pattern \"", pattern, "\"", (char *) NULL); return TCL_ERROR; @@ -1521,19 +1555,18 @@ * 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: - * Ordinarily this procedure returns TCL_OK. It sets *nsPtrPtr and - * *altNsPtrPtr to point to the two possible namespaces which represent - * the last (containing) namespace in the qualified name. If the - * procedure sets either *nsPtrPtr or *altNsPtrPtr to NULL, then the - * search along that path failed. The procedure 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 - * (FIND_ONLY_NS), the procedure stores a pointer to the - * namespace in *nsPtrPtr, NULL in *altNsPtrPtr, and sets + * It sets *nsPtrPtr and *altNsPtrPtr to point to the two possible + * namespaces which represent the last (containing) namespace in the + * qualified name. If the procedure sets either *nsPtrPtr or *altNsPtrPtr + * to NULL, then the search along that path failed. The procedure 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 (FIND_ONLY_NS), the procedure 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 procedure 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 @@ -1541,13 +1574,16 @@ * * *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_LEAVE_ERR_MSG and an error is encountered, - * the interpreter's result object will contain an error message. + * If "flags" contains CREATE_NS_IF_UNKNOWN, new namespaces may be + * created. * *---------------------------------------------------------------------- */ int @@ -1598,11 +1634,11 @@ Namespace *globalNsPtr = iPtr->globalNsPtr; register char *start, *end; char *nsName; Tcl_HashEntry *entryPtr; Tcl_DString buffer; - int len, result; + int len; /* * Determine the context namespace nsPtr in which to start the primary * search. If TCL_NAMESPACE_ONLY or FIND_ONLY_NS was specified, search * from the current namespace. If the qualName name starts with a "::" @@ -1723,22 +1759,19 @@ if (entryPtr != NULL) { nsPtr = (Namespace *) Tcl_GetHashValue(entryPtr); } else if (flags & CREATE_NS_IF_UNKNOWN) { Tcl_CallFrame frame; - result = Tcl_PushCallFrame(interp, &frame, + (void) Tcl_PushCallFrame(interp, &frame, (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 0); - if (result != TCL_OK) { - Tcl_DStringFree(&buffer); - return result; - } + nsPtr = (Namespace *) Tcl_CreateNamespace(interp, nsName, (ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL); Tcl_PopCallFrame(interp); + if (nsPtr == NULL) { - Tcl_DStringFree(&buffer); - return TCL_ERROR; + panic("Could not create namespace '%s'", nsName); } } else { /* namespace not found and wasn't created */ nsPtr = NULL; } } @@ -1792,11 +1825,11 @@ if ((flags & FIND_ONLY_NS) && (*qualName == '\0') && (nsPtr != globalNsPtr)) { nsPtr = NULL; } - + *nsPtrPtr = nsPtr; *altNsPtrPtr = altNsPtr; Tcl_DStringFree(&buffer); return TCL_OK; } @@ -1837,24 +1870,20 @@ * OR'd combination of TCL_GLOBAL_ONLY and * TCL_LEAVE_ERR_MSG flags. */ { Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr; char *dummy; - int result; /* * Find the namespace(s) that contain the specified namespace name. * Add the FIND_ONLY_NS flag to resolve the name all the way down * to its last component, a namespace. */ - result = TclGetNamespaceForQualName(interp, name, - (Namespace *) contextNsPtr, /*flags*/ (flags | FIND_ONLY_NS), - &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy); - if (result != TCL_OK) { - return NULL; - } + TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr, + (flags | FIND_ONLY_NS), &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy); + if (nsPtr != NULL) { return (Tcl_Namespace *) nsPtr; } else if (flags & TCL_LEAVE_ERR_MSG) { Tcl_ResetResult(interp); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), @@ -1903,27 +1932,70 @@ * 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; char *simpleName; register Tcl_HashEntry *entryPtr; register Command *cmdPtr; register int search; int result; + Tcl_Command cmd; + + /* + * 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 + * procedures may return a Tcl_Command value, they may signal + * to continue onward, or they may signal an error. + */ + if ((flags & TCL_GLOBAL_ONLY) != 0) { + cxtNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp); + } + else if (contextNsPtr != NULL) { + cxtNsPtr = (Namespace *) contextNsPtr; + } + else { + cxtNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); + } + + if (cxtNsPtr->cmdResProc != NULL || iPtr->resolverPtr != NULL) { + resPtr = iPtr->resolverPtr; + + 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 (Tcl_Command) NULL; + } + } /* * Find the namespace(s) that contain the command. */ - result = TclGetNamespaceForQualName(interp, name, - (Namespace *) contextNsPtr, flags, &nsPtr[0], &nsPtr[1], - &cxtNsPtr, &simpleName); - if (result != TCL_OK) { - return (Tcl_Command) NULL; - } + 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. @@ -1944,10 +2016,11 @@ } else if (flags & TCL_LEAVE_ERR_MSG) { Tcl_ResetResult(interp); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "unknown command \"", name, "\"", (char *) NULL); } + return (Tcl_Command) NULL; } /* *---------------------------------------------------------------------- @@ -1991,27 +2064,68 @@ * 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; char *simpleName; Tcl_HashEntry *entryPtr; Var *varPtr; register int search; int result; + Tcl_Var var; + + /* + * 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 *) Tcl_GetGlobalNamespace(interp); + } + else if (contextNsPtr != NULL) { + cxtNsPtr = (Namespace *) contextNsPtr; + } + else { + cxtNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); + } + + if (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 (Tcl_Var) NULL; + } + } /* * Find the namespace(s) that contain the variable. */ - result = TclGetNamespaceForQualName(interp, name, - (Namespace *) contextNsPtr, flags, &nsPtr[0], &nsPtr[1], - &cxtNsPtr, &simpleName); - if (result != TCL_OK) { - return (Tcl_Var) NULL; - } + 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. @@ -2085,11 +2199,10 @@ * This procedure generates an array used to hold the trail list. This * starts out with stack-allocated space but uses dynamically-allocated * storage if needed. */ -#define NUM_TRAIL_ELEMS 5 Namespace *(trailStorage[NUM_TRAIL_ELEMS]); Namespace **trailPtr = trailStorage; int trailFront = -1; int trailSize = NUM_TRAIL_ELEMS; @@ -2179,11 +2292,10 @@ */ if (trailPtr != trailStorage) { ckfree((char *) trailPtr); } -#undef NUM_TRAIL_ELEMS } /* *---------------------------------------------------------------------- * @@ -2324,12 +2436,12 @@ enum NSSubCmdIdx { NSChildrenIdx, NSCodeIdx, NSCurrentIdx, NSDeleteIdx, NSEvalIdx, NSExportIdx, NSForgetIdx, NSImportIdx, NSInscopeIdx, NSOriginIdx, NSParentIdx, NSQualifiersIdx, NSTailIdx, NSWhichIdx - } index; - int result; + }; + int index, result; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?"); return TCL_ERROR; } @@ -2438,12 +2550,11 @@ if (GetNamespaceFromObj(interp, objv[2], &namespacePtr) != TCL_OK) { return TCL_ERROR; } if (namespacePtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "unknown namespace \"", - Tcl_GetStringFromObj(objv[2], (int *) NULL), + "unknown namespace \"", Tcl_GetString(objv[2]), "\" in namespace children command", (char *) NULL); return TCL_ERROR; } nsPtr = (Namespace *) namespacePtr; } else { @@ -2455,11 +2566,11 @@ * Get the glob-style pattern, if any, used to narrow the search. */ Tcl_DStringInit(&buffer); if (objc == 4) { - char *name = Tcl_GetStringFromObj(objv[3], (int *) NULL); + char *name = Tcl_GetString(objv[3]); if ((*name == ':') && (*(name+1) == ':')) { pattern = name; } else { Tcl_DStringAppend(&buffer, nsPtr->fullName, -1); @@ -2689,17 +2800,16 @@ * this into two passes: first check to make sure that all namespaces on * the command line are valid, and report any errors. */ for (i = 2; i < objc; i++) { - name = Tcl_GetStringFromObj(objv[i], (int *) NULL); + name = Tcl_GetString(objv[i]); namespacePtr = Tcl_FindNamespace(interp, name, (Tcl_Namespace *) NULL, /*flags*/ 0); if (namespacePtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "unknown namespace \"", - Tcl_GetStringFromObj(objv[i], (int *) NULL), + "unknown namespace \"", Tcl_GetString(objv[i]), "\" in namespace delete command", (char *) NULL); return TCL_ERROR; } } @@ -2706,17 +2816,16 @@ /* * Okay, now delete each namespace. */ for (i = 2; i < objc; i++) { - name = Tcl_GetStringFromObj(objv[i], (int *) NULL); + name = Tcl_GetString(objv[i]); namespacePtr = Tcl_FindNamespace(interp, name, - (Tcl_Namespace *) NULL, TCL_LEAVE_ERR_MSG); - if (namespacePtr == NULL) { - return TCL_ERROR; + (Tcl_Namespace *) NULL, /* flags */ 0); + if (namespacePtr) { + Tcl_DeleteNamespace(namespacePtr); } - Tcl_DeleteNamespace(namespacePtr); } return TCL_OK; } /* @@ -2797,18 +2906,23 @@ if (result != TCL_OK) { return TCL_ERROR; } if (objc == 4) { - result = Tcl_EvalObj(interp, objv[3]); + result = Tcl_EvalObjEx(interp, objv[3], 0); } else { objPtr = Tcl_ConcatObj(objc-3, objv+3); - result = Tcl_EvalObj(interp, objPtr); - Tcl_DecrRefCount(objPtr); /* we're done with the object */ + + /* + * Tcl_EvalObj will delete the object when it decrements its + * refcount after eval'ing it. + */ + + result = Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_DIRECT); } if (result == TCL_ERROR) { - char msg[256]; + char msg[256 + TCL_INTEGER_SPACE]; sprintf(msg, "\n (in namespace eval \"%.200s\" script line %d)", namespacePtr->fullName, interp->errorLine); Tcl_AddObjErrorInfo(interp, msg, -1); } @@ -2879,11 +2993,11 @@ * Process the optional "-clear" argument. */ firstArg = 2; if (firstArg < objc) { - string = Tcl_GetStringFromObj(objv[firstArg], (int *) NULL); + string = Tcl_GetString(objv[firstArg]); if (strcmp(string, "-clear") == 0) { resetListFirst = 1; firstArg++; } } @@ -2912,11 +3026,11 @@ /* * Add each pattern to the namespace's export pattern list. */ for (i = firstArg; i < objc; i++) { - pattern = Tcl_GetStringFromObj(objv[i], (int *) NULL); + pattern = Tcl_GetString(objv[i]); result = Tcl_Export(interp, (Tcl_Namespace *) currNsPtr, pattern, ((i == firstArg)? resetListFirst : 0)); if (result != TCL_OK) { return result; } @@ -2968,11 +3082,11 @@ Tcl_WrongNumArgs(interp, 2, objv, "?pattern pattern...?"); return TCL_ERROR; } for (i = 2; i < objc; i++) { - pattern = Tcl_GetStringFromObj(objv[i], (int *) NULL); + pattern = Tcl_GetString(objv[i]); result = Tcl_ForgetImport(interp, (Tcl_Namespace *) NULL, pattern); if (result != TCL_OK) { return result; } } @@ -3038,11 +3152,11 @@ * Skip over the optional "-force" as the first argument. */ firstArg = 2; if (firstArg < objc) { - string = Tcl_GetStringFromObj(objv[firstArg], (int *) NULL); + string = Tcl_GetString(objv[firstArg]); if ((*string == '-') && (strcmp(string, "-force") == 0)) { allowOverwrite = 1; firstArg++; } } @@ -3050,11 +3164,11 @@ /* * Handle the imports for each of the patterns. */ for (i = firstArg; i < objc; i++) { - pattern = Tcl_GetStringFromObj(objv[i], (int *) NULL); + pattern = Tcl_GetString(objv[i]); result = Tcl_Import(interp, (Tcl_Namespace *) NULL, pattern, allowOverwrite); if (result != TCL_OK) { return result; } @@ -3124,12 +3238,11 @@ if (result != TCL_OK) { return result; } if (namespacePtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "unknown namespace \"", - Tcl_GetStringFromObj(objv[2], (int *) NULL), + "unknown namespace \"", Tcl_GetString(objv[2]), "\" in inscope namespace command", (char *) NULL); return TCL_ERROR; } /* @@ -3148,11 +3261,11 @@ * after the first one, then concatenate the first argument and the list * of extra arguments to form the command to evaluate. */ if (objc == 4) { - result = Tcl_EvalObj(interp, objv[3]); + result = Tcl_EvalObjEx(interp, objv[3], 0); } else { Tcl_Obj *concatObjv[2]; register Tcl_Obj *listPtr, *cmdObjPtr; listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); @@ -3165,17 +3278,15 @@ } concatObjv[0] = objv[3]; concatObjv[1] = listPtr; cmdObjPtr = Tcl_ConcatObj(2, concatObjv); - result = Tcl_EvalObj(interp, cmdObjPtr); - - Tcl_DecrRefCount(cmdObjPtr); /* we're done with the cmd object */ + result = Tcl_EvalObjEx(interp, cmdObjPtr, TCL_EVAL_DIRECT); Tcl_DecrRefCount(listPtr); /* we're done with the list object */ } if (result == TCL_ERROR) { - char msg[256]; + char msg[256 + TCL_INTEGER_SPACE]; sprintf(msg, "\n (in namespace inscope \"%.200s\" script line %d)", namespacePtr->fullName, interp->errorLine); Tcl_AddObjErrorInfo(interp, msg, -1); @@ -3233,12 +3344,11 @@ } command = Tcl_GetCommandFromObj(interp, objv[2]); if (command == (Tcl_Command) NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "invalid command name \"", - Tcl_GetStringFromObj(objv[2], (int *) NULL), + "invalid command name \"", Tcl_GetString(objv[2]), "\"", (char *) NULL); return TCL_ERROR; } origCommand = TclGetOriginalCommand(command); if (origCommand == (Tcl_Command) NULL) { @@ -3293,12 +3403,11 @@ if (result != TCL_OK) { return result; } if (nsPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "unknown namespace \"", - Tcl_GetStringFromObj(objv[2], (int *) NULL), + "unknown namespace \"", Tcl_GetString(objv[2]), "\" in namespace parent command", (char *) NULL); return TCL_ERROR; } } else { Tcl_WrongNumArgs(interp, 2, objv, "?name?"); @@ -3360,11 +3469,11 @@ /* * Find the end of the string, then work backward and find * the start of the last "::" qualifier. */ - name = Tcl_GetStringFromObj(objv[2], (int *) NULL); + name = Tcl_GetString(objv[2]); for (p = name; *p != '\0'; p++) { /* empty body */ } while (--p >= name) { if ((*p == ':') && (p > name) && (*(p-1) == ':')) { @@ -3426,11 +3535,11 @@ /* * Find the end of the string, then work backward and find the * last "::" qualifier. */ - name = Tcl_GetStringFromObj(objv[2], (int *) NULL); + name = Tcl_GetString(objv[2]); for (p = name; *p != '\0'; p++) { /* empty body */ } while (--p > name) { if ((*p == ':') && (*(p-1) == ':')) { @@ -3490,11 +3599,11 @@ * Look for a flag controlling the lookup. */ argIndex = 2; lookup = 0; /* assume command lookup by default */ - arg = Tcl_GetStringFromObj(objv[2], (int *) NULL); + arg = Tcl_GetString(objv[2]); if (*arg == '-') { if (strncmp(arg, "-command", 8) == 0) { lookup = 0; } else if (strncmp(arg, "-variable", 9) == 0) { lookup = 1; @@ -3515,11 +3624,11 @@ } Tcl_GetCommandFullName(interp, cmd, Tcl_GetObjResult(interp)); break; case 1: /* -variable */ - arg = Tcl_GetStringFromObj(objv[argIndex], (int *) NULL); + arg = Tcl_GetString(objv[argIndex]); variable = Tcl_FindNamespaceVar(interp, arg, (Tcl_Namespace *) NULL, /*flags*/ 0); if (variable != (Tcl_Var) NULL) { Tcl_GetVariableFullName(interp, variable, Tcl_GetObjResult(interp)); } @@ -3647,34 +3756,29 @@ { register Tcl_ObjType *oldTypePtr = objPtr->typePtr; char *name, *dummy; Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr; register ResolvedNsName *resNamePtr; - int flags, result; /* * Get the string representation. Make it up-to-date if necessary. */ name = objPtr->bytes; if (name == NULL) { - name = Tcl_GetStringFromObj(objPtr, (int *) NULL); + name = Tcl_GetString(objPtr); } /* * Look for the namespace "name" in the current namespace. If there is * an error parsing the (possibly qualified) name, return an error. * If the namespace isn't found, we convert the object to an nsName * object with a NULL ResolvedNsName* internal rep. */ - flags = ((interp != NULL)? TCL_LEAVE_ERR_MSG : 0) | FIND_ONLY_NS; - result = TclGetNamespaceForQualName(interp, name, (Namespace *) NULL, - flags, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy); - if (result != TCL_OK) { - return result; - } + TclGetNamespaceForQualName(interp, name, (Namespace *) NULL, + FIND_ONLY_NS, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy); /* * If we found a namespace, then create a new ResolvedNsName structure * that holds a reference to it. */ Index: generic/tclNotify.c ================================================================== --- generic/tclNotify.c +++ generic/tclNotify.c @@ -6,26 +6,21 @@ * 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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclNotify.c 1.16 97/09/15 15:12:52 + * RCS: @(#) $Id: tclNotify.c,v 1.1.2.9 1999/04/14 00:33:25 surles Exp $ */ #include "tclInt.h" #include "tclPort.h" -/* - * The following static indicates whether this module has been initialized. - */ - -static int initialized = 0; - /* * For each event source (created with Tcl_CreateEventSource) there * is a structure of the following type: */ @@ -35,25 +30,29 @@ ClientData clientData; struct EventSource *nextPtr; } EventSource; /* - * The following structure keeps track of the state of the notifier. - * 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). + * 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. */ -static struct { +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 @@ -60,67 +59,107 @@ * 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 - * global list of event sources. */ -} notifier; - -/* - * Declarations for functions used in this file. - */ - -static void InitNotifier _ANSI_ARGS_((void)); -static void NotifierExitHandler _ANSI_ARGS_((ClientData clientData)); - - -/* - *---------------------------------------------------------------------- - * - * InitNotifier -- - * - * This routine is called to initialize the notifier module. - * - * Results: - * None. - * - * Side effects: - * Creates an exit handler and initializes static data. - * - *---------------------------------------------------------------------- - */ - -static void -InitNotifier() -{ - initialized = 1; - memset(¬ifier, 0, sizeof(notifier)); - notifier.serviceMode = TCL_SERVICE_NONE; - Tcl_CreateExitHandler(NotifierExitHandler, NULL); -} - -/* - *---------------------------------------------------------------------- - * - * NotifierExitHandler -- - * - * This routine is called during Tcl finalization. - * - * Results: - * None. - * - * Side effects: - * Clears the notifier intialization flag. - * - *---------------------------------------------------------------------- - */ - -static void -NotifierExitHandler(clientData) - ClientData clientData; /* Not used. */ -{ - initialized = 0; + * list of event sources for this thread. */ + Tcl_ThreadId threadId; /* Thread that owns this notifier instance. */ + ClientData clientData; /* Opaque handle for platform specific + * notifier. */ + 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; +TCL_DECLARE_MUTEX(listLock) + +/* + * Declarations for routines used only in this file. + */ + +static void QueueEvent _ANSI_ARGS_((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() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + Tcl_MutexLock(&listLock); + + tsdPtr->threadId = Tcl_GetCurrentThread(); + tsdPtr->clientData = Tcl_InitNotifier(); + 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. + * + *---------------------------------------------------------------------- + */ + +void +TclFinalizeNotifier() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData **prevPtrPtr; + + Tcl_MutexLock(&listLock); + + Tcl_FinalizeNotifier(tsdPtr->clientData); + TclFinalizeMutex(&(tsdPtr->queueMutex)); + for (prevPtrPtr = &firstNotifierPtr; *prevPtrPtr != NULL; + prevPtrPtr = &((*prevPtrPtr)->nextPtr)) { + if (*prevPtrPtr == tsdPtr) { + *prevPtrPtr = tsdPtr->nextPtr; + break; + } + } + + Tcl_MutexUnlock(&listLock); } /* *---------------------------------------------------------------------- * @@ -137,16 +176,16 @@ * * 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_WatchFile - * or Tcl_SetMaxBlockTime to indicate what to wait for. + * 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_FileReady), and then calls + * happened (e.g. by calling Tcl_AsyncReady), and then calls * Tcl_QueueEvent to queue any events that are ready. * * Each of these procedures is passed two arguments, e.g. * (*checkProc)(ClientData clientData, int flags)); * ClientData is the same as the clientData argument here, and flags @@ -164,22 +203,18 @@ Tcl_EventCheckProc *checkProc; /* Procedure to call after waiting * to see what happened. */ ClientData clientData; /* One-word argument to pass to * setupProc and checkProc. */ { - EventSource *sourcePtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + EventSource *sourcePtr = (EventSource *) ckalloc(sizeof(EventSource)); - if (!initialized) { - InitNotifier(); - } - - sourcePtr = (EventSource *) ckalloc(sizeof(EventSource)); sourcePtr->setupProc = setupProc; sourcePtr->checkProc = checkProc; sourcePtr->clientData = clientData; - sourcePtr->nextPtr = notifier.firstEventSourcePtr; - notifier.firstEventSourcePtr = sourcePtr; + sourcePtr->nextPtr = tsdPtr->firstEventSourcePtr; + tsdPtr->firstEventSourcePtr = sourcePtr; } /* *---------------------------------------------------------------------- * @@ -206,22 +241,23 @@ Tcl_EventCheckProc *checkProc; /* Procedure 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 = notifier.firstEventSourcePtr, prevPtr = NULL; + 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) { - notifier.firstEventSourcePtr = sourcePtr->nextPtr; + tsdPtr->firstEventSourcePtr = sourcePtr->nextPtr; } else { prevPtr->nextPtr = sourcePtr->nextPtr; } ckfree((char *) sourcePtr); return; @@ -231,16 +267,12 @@ /* *---------------------------------------------------------------------- * * Tcl_QueueEvent -- * - * Insert an event into the Tk 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. + * Queue an event on the event queue associated with the + * current thread. * * Results: * None. * * Side effects: @@ -258,64 +290,151 @@ * will be freed after the event has been * handled. */ Tcl_QueuePosition position; /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, * TCL_QUEUE_MARK. */ { - if (!initialized) { - InitNotifier(); + 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(threadId, evPtr, position) + 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); } + 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(tsdPtr, evPtr, position) + 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 (notifier.firstEventPtr == NULL) { - notifier.firstEventPtr = evPtr; + if (tsdPtr->firstEventPtr == NULL) { + tsdPtr->firstEventPtr = evPtr; } else { - notifier.lastEventPtr->nextPtr = evPtr; + tsdPtr->lastEventPtr->nextPtr = evPtr; } - notifier.lastEventPtr = evPtr; + tsdPtr->lastEventPtr = evPtr; } else if (position == TCL_QUEUE_HEAD) { /* * Push the event on the head of the queue. */ - evPtr->nextPtr = notifier.firstEventPtr; - if (notifier.firstEventPtr == NULL) { - notifier.lastEventPtr = evPtr; + evPtr->nextPtr = tsdPtr->firstEventPtr; + if (tsdPtr->firstEventPtr == NULL) { + tsdPtr->lastEventPtr = evPtr; } - notifier.firstEventPtr = 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 (notifier.markerEventPtr == NULL) { - evPtr->nextPtr = notifier.firstEventPtr; - notifier.firstEventPtr = evPtr; + if (tsdPtr->markerEventPtr == NULL) { + evPtr->nextPtr = tsdPtr->firstEventPtr; + tsdPtr->firstEventPtr = evPtr; } else { - evPtr->nextPtr = notifier.markerEventPtr->nextPtr; - notifier.markerEventPtr->nextPtr = evPtr; + evPtr->nextPtr = tsdPtr->markerEventPtr->nextPtr; + tsdPtr->markerEventPtr->nextPtr = evPtr; } - notifier.markerEventPtr = evPtr; + tsdPtr->markerEventPtr = evPtr; if (evPtr->nextPtr == NULL) { - notifier.lastEventPtr = evPtr; + tsdPtr->lastEventPtr = evPtr; } } + Tcl_MutexUnlock(&(tsdPtr->queueMutex)); } /* *---------------------------------------------------------------------- * * Tcl_DeleteEvents -- * * Calls a procedure for each event in the queue and deletes those * for which the procedure returns 1. Events for which the - * procedure returns 0 are left in the queue. + * procedure returns 0 are left in the queue. Operates on the + * queue associated with the current thread. * * Results: * None. * * Side effects: @@ -328,24 +447,25 @@ Tcl_DeleteEvents(proc, clientData) Tcl_EventDeleteProc *proc; /* The procedure to call. */ ClientData clientData; /* type-specific data. */ { Tcl_Event *evPtr, *prevPtr, *hold; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - if (!initialized) { - InitNotifier(); - } - - for (prevPtr = (Tcl_Event *) NULL, evPtr = notifier.firstEventPtr; + Tcl_MutexLock(&(tsdPtr->queueMutex)); + for (prevPtr = (Tcl_Event *) NULL, evPtr = tsdPtr->firstEventPtr; evPtr != (Tcl_Event *) NULL; ) { if ((*proc) (evPtr, clientData) == 1) { - if (notifier.firstEventPtr == evPtr) { - notifier.firstEventPtr = evPtr->nextPtr; + if (tsdPtr->firstEventPtr == evPtr) { + tsdPtr->firstEventPtr = evPtr->nextPtr; if (evPtr->nextPtr == (Tcl_Event *) NULL) { - notifier.lastEventPtr = (Tcl_Event *) NULL; + tsdPtr->lastEventPtr = prevPtr; } + if (tsdPtr->markerEventPtr == evPtr) { + tsdPtr->markerEventPtr = prevPtr; + } } else { prevPtr->nextPtr = evPtr->nextPtr; } hold = evPtr; evPtr = evPtr->nextPtr; @@ -353,19 +473,21 @@ } else { prevPtr = evPtr; evPtr = evPtr->nextPtr; } } + Tcl_MutexUnlock(&(tsdPtr->queueMutex)); } /* *---------------------------------------------------------------------- * * Tcl_ServiceEvent -- * * Process one event from the event queue, or invoke an - * asynchronous event handler. + * asynchronous event handler. Operates on event queue for + * current thread. * * Results: * The return value is 1 if the procedure actually found an event * to process. If no processing occurred, then 0 is returned. * @@ -386,14 +508,12 @@ * matching this will be skipped for processing * later. */ { Tcl_Event *evPtr, *prevPtr; Tcl_EventProc *proc; - - if (!initialized) { - InitNotifier(); - } + 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. @@ -415,16 +535,17 @@ /* * Loop through all the events in the queue until we find one * that can actually be handled. */ - for (evPtr = notifier.firstEventPtr; evPtr != NULL; + 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, but stemming from the fact that the event + * 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. @@ -434,51 +555,72 @@ * can't depend on pointers found now still being valid when * the handler returns. */ proc = evPtr->proc; + if (proc == NULL) { + continue; + } evPtr->proc = NULL; - if ((proc != NULL) && (*proc)(evPtr, flags)) { - if (notifier.firstEventPtr == evPtr) { - notifier.firstEventPtr = evPtr->nextPtr; + + /* + * Release the lock before calling the event procedure. 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) { - notifier.lastEventPtr = NULL; + tsdPtr->lastEventPtr = NULL; } - if (notifier.markerEventPtr == evPtr) { - notifier.markerEventPtr = NULL; + if (tsdPtr->markerEventPtr == evPtr) { + tsdPtr->markerEventPtr = NULL; } } else { - for (prevPtr = notifier.firstEventPtr; - prevPtr->nextPtr != evPtr; prevPtr = prevPtr->nextPtr) { + for (prevPtr = tsdPtr->firstEventPtr; + prevPtr && prevPtr->nextPtr != evPtr; + prevPtr = prevPtr->nextPtr) { /* Empty loop body. */ } - prevPtr->nextPtr = evPtr->nextPtr; - if (evPtr->nextPtr == NULL) { - notifier.lastEventPtr = prevPtr; - } - if (notifier.markerEventPtr == evPtr) { - notifier.markerEventPtr = prevPtr; + if (prevPtr) { + prevPtr->nextPtr = evPtr->nextPtr; + if (evPtr->nextPtr == NULL) { + tsdPtr->lastEventPtr = prevPtr; + } + if (tsdPtr->markerEventPtr == evPtr) { + tsdPtr->markerEventPtr = prevPtr; + } + } else { + evPtr = NULL; } } - ckfree((char *) evPtr); + if (evPtr) { + ckfree((char *) 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; } - - /* - * The handler for this event asked to defer it. Just go on to - * the next event. - */ - - continue; - } + } + Tcl_MutexUnlock(&(tsdPtr->queueMutex)); return 0; } /* *---------------------------------------------------------------------- @@ -497,29 +639,27 @@ */ int Tcl_GetServiceMode() { - if (!initialized) { - InitNotifier(); - } + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - return notifier.serviceMode; + return tsdPtr->serviceMode; } /* *---------------------------------------------------------------------- * * Tcl_SetServiceMode -- * - * This routine sets the current service mode of the notifier. + * This routine sets the current service mode of the tsdPtr-> * * Results: * Returns the previous service mode. * * Side effects: - * None. + * Invokes the notifier service mode hook procedure. * *---------------------------------------------------------------------- */ int @@ -526,17 +666,15 @@ Tcl_SetServiceMode(mode) int mode; /* New service mode: TCL_SERVICE_ALL or * TCL_SERVICE_NONE */ { int oldMode; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - if (!initialized) { - InitNotifier(); - } - - oldMode = notifier.serviceMode; - notifier.serviceMode = mode; + oldMode = tsdPtr->serviceMode; + tsdPtr->serviceMode = mode; + Tcl_ServiceModeHook(mode); return oldMode; } /* *---------------------------------------------------------------------- @@ -550,40 +688,38 @@ * * Results: * None. * * Side effects: - * May reduce the length of the next sleep in the notifier. + * May reduce the length of the next sleep in the tsdPtr-> * *---------------------------------------------------------------------- */ void Tcl_SetMaxBlockTime(timePtr) Tcl_Time *timePtr; /* Specifies a maximum elapsed time for * the next blocking operation in the - * event notifier. */ -{ - if (!initialized) { - InitNotifier(); - } - - if (!notifier.blockTimeSet || (timePtr->sec < notifier.blockTime.sec) - || ((timePtr->sec == notifier.blockTime.sec) - && (timePtr->usec < notifier.blockTime.usec))) { - notifier.blockTime = *timePtr; - notifier.blockTimeSet = 1; + * 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 (!notifier.inTraversal) { - if (notifier.blockTimeSet) { - Tcl_SetTimer(¬ifier.blockTime); + if (!tsdPtr->inTraversal) { + if (tsdPtr->blockTimeSet) { + Tcl_SetTimer(&tsdPtr->blockTime); } else { Tcl_SetTimer(NULL); } } } @@ -620,14 +756,11 @@ * others defined by event sources. */ { int result = 0, oldMode; EventSource *sourcePtr; Tcl_Time *timePtr; - - if (!initialized) { - InitNotifier(); - } + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * The first thing we do is to service any asynchronous event * handlers. */ @@ -648,12 +781,12 @@ /* * Set the service mode to none so notifier event routines won't * try to service events recursively. */ - oldMode = notifier.serviceMode; - notifier.serviceMode = TCL_SERVICE_NONE; + oldMode = tsdPtr->serviceMode; + tsdPtr->serviceMode = TCL_SERVICE_NONE; /* * The core of this procedure 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. @@ -685,33 +818,33 @@ * 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) { - notifier.blockTime.sec = 0; - notifier.blockTime.usec = 0; - notifier.blockTimeSet = 1; + tsdPtr->blockTime.sec = 0; + tsdPtr->blockTime.usec = 0; + tsdPtr->blockTimeSet = 1; } else { - notifier.blockTimeSet = 0; + tsdPtr->blockTimeSet = 0; } /* * Set up all the event sources for new events. This will * cause the block time to be updated if necessary. */ - notifier.inTraversal = 1; - for (sourcePtr = notifier.firstEventSourcePtr; sourcePtr != NULL; + tsdPtr->inTraversal = 1; + for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->setupProc) { (sourcePtr->setupProc)(sourcePtr->clientData, flags); } } - notifier.inTraversal = 0; + tsdPtr->inTraversal = 0; - if ((flags & TCL_DONT_WAIT) || notifier.blockTimeSet) { - timePtr = ¬ifier.blockTime; + if ((flags & TCL_DONT_WAIT) || tsdPtr->blockTimeSet) { + timePtr = &tsdPtr->blockTime; } else { timePtr = NULL; } /* @@ -727,11 +860,11 @@ /* * Check all the event sources for new events. */ - for (sourcePtr = notifier.firstEventSourcePtr; sourcePtr != NULL; + for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->checkProc) { (sourcePtr->checkProc)(sourcePtr->clientData, flags); } } @@ -780,11 +913,11 @@ break; } } - notifier.serviceMode = oldMode; + tsdPtr->serviceMode = oldMode; return result; } /* *---------------------------------------------------------------------- @@ -810,25 +943,22 @@ int Tcl_ServiceAll() { int result = 0; EventSource *sourcePtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - if (!initialized) { - InitNotifier(); - } - - if (notifier.serviceMode == TCL_SERVICE_NONE) { + 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. */ - notifier.serviceMode = TCL_SERVICE_NONE; + tsdPtr->serviceMode = TCL_SERVICE_NONE; /* * Check async handlers first. */ @@ -840,20 +970,20 @@ * 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. */ - notifier.inTraversal = 1; - notifier.blockTimeSet = 0; + tsdPtr->inTraversal = 1; + tsdPtr->blockTimeSet = 0; - for (sourcePtr = notifier.firstEventSourcePtr; sourcePtr != NULL; + for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->setupProc) { (sourcePtr->setupProc)(sourcePtr->clientData, TCL_ALL_EVENTS); } } - for (sourcePtr = notifier.firstEventSourcePtr; sourcePtr != NULL; + for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->checkProc) { (sourcePtr->checkProc)(sourcePtr->clientData, TCL_ALL_EVENTS); } } @@ -863,14 +993,54 @@ } if (TclServiceIdle()) { result = 1; } - if (!notifier.blockTimeSet) { + if (!tsdPtr->blockTimeSet) { Tcl_SetTimer(NULL); } else { - Tcl_SetTimer(¬ifier.blockTime); + Tcl_SetTimer(&tsdPtr->blockTime); } - notifier.inTraversal = 0; - notifier.serviceMode = TCL_SERVICE_ALL; + 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(threadId) + 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); +} Index: generic/tclObj.c ================================================================== --- generic/tclObj.c +++ generic/tclObj.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) tclObj.c 1.47 97/10/30 13:39:00 + * RCS: @(#) $Id: tclObj.c,v 1.1.2.8 1999/04/14 00:33:25 surles Exp $ */ #include "tclInt.h" #include "tclPort.h" @@ -19,28 +19,39 @@ * 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_Objs we maintain. + * 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 +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 *tclEmptyStringRep = NULL; +static char emptyString; +char *tclEmptyStringRep = &emptyString; /* - * Count of the number of Tcl objects every allocated (by Tcl_NewObj) and - * freed (by TclFreeObj). + * The number of Tcl objects ever allocated (by Tcl_NewObj) and freed + * (by TclFreeObj). */ #ifdef TCL_COMPILE_STATS long tclObjsAlloced = 0; long tclObjsFreed = 0; @@ -48,19 +59,10 @@ /* * Prototypes for procedures defined later in this file: */ -static void DupBooleanInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, - Tcl_Obj *copyPtr)); -static void DupDoubleInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, - Tcl_Obj *copyPtr)); -static void DupIntInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, - Tcl_Obj *copyPtr)); -static void FinalizeTypeTable _ANSI_ARGS_((void)); -static void FinalizeFreeObjList _ANSI_ARGS_((void)); -static void InitTypeTable _ANSI_ARGS_((void)); static int SetBooleanFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr)); static int SetDoubleFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr)); static int SetIntFromAny _ANSI_ARGS_((Tcl_Interp *interp, @@ -77,35 +79,35 @@ */ Tcl_ObjType tclBooleanType = { "boolean", /* name */ (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */ - DupBooleanInternalRep, /* dupIntRepProc */ + (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */ UpdateStringOfBoolean, /* updateStringProc */ SetBooleanFromAny /* setFromAnyProc */ }; Tcl_ObjType tclDoubleType = { "double", /* name */ (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */ - DupDoubleInternalRep, /* dupIntRepProc */ + (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */ UpdateStringOfDouble, /* updateStringProc */ SetDoubleFromAny /* setFromAnyProc */ }; Tcl_ObjType tclIntType = { "int", /* name */ (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */ - DupIntInternalRep, /* dupIntRepProc */ + (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */ UpdateStringOfInt, /* updateStringProc */ SetIntFromAny /* setFromAnyProc */ }; /* - *-------------------------------------------------------------- + *------------------------------------------------------------------------- * - * InitTypeTable -- + * TclInitObjectSubsystem -- * * This procedure is invoked to perform once-only initialization of * the type table. It also registers the object types defined in * this file. * @@ -112,111 +114,73 @@ * Results: * None. * * Side effects: * Initializes the table of defined object types "typeTable" with - * builtin object types defined in this file. It also initializes the - * value of tclEmptyStringRep, which points to the heap-allocated - * string of length zero used as the string representation for - * newly-created objects. + * builtin object types defined in this file. * - *-------------------------------------------------------------- + *------------------------------------------------------------------------- */ -static void -InitTypeTable() +void +TclInitObjSubsystem() { + Tcl_MutexLock(&tableMutex); typeTableInitialized = 1; - Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS); + Tcl_MutexUnlock(&tableMutex); + Tcl_RegisterObjType(&tclBooleanType); + Tcl_RegisterObjType(&tclByteArrayType); Tcl_RegisterObjType(&tclDoubleType); Tcl_RegisterObjType(&tclIntType); Tcl_RegisterObjType(&tclStringType); Tcl_RegisterObjType(&tclListType); Tcl_RegisterObjType(&tclByteCodeType); - - tclEmptyStringRep = (char *) ckalloc((unsigned) 1); - tclEmptyStringRep[0] = '\0'; -} - -/* - *---------------------------------------------------------------------- - * - * FinalizeTypeTable -- - * - * This procedure is called by Tcl_Finalize after all exit handlers - * have been run to free up storage associated with the table of Tcl - * object types. - * - * Results: - * None. - * - * Side effects: - * Deletes all entries in the hash table of object types, "typeTable". - * Then sets "typeTableInitialized" to 0 so that the Tcl type system - * will be properly reinitialized if Tcl is restarted. Also deallocates - * the storage for tclEmptyStringRep. - * - *---------------------------------------------------------------------- - */ - -static void -FinalizeTypeTable() -{ - if (typeTableInitialized) { - Tcl_DeleteHashTable(&typeTable); - ckfree(tclEmptyStringRep); - typeTableInitialized = 0; - } -} - -/* - *---------------------------------------------------------------------- - * - * FinalizeFreeObjList -- - * - * Resets the free object list so it can later be reinitialized. - * - * Results: - * None. - * - * Side effects: - * Resets the value of tclFreeObjList. - * - *---------------------------------------------------------------------- - */ - -static void -FinalizeFreeObjList() -{ - tclFreeObjList = NULL; + Tcl_RegisterObjType(&tclProcBodyType); + +#ifdef TCL_COMPILE_STATS + Tcl_MutexLock(&tclObjMutex); + tclObjsAlloced = 0; + tclObjsFreed = 0; + Tcl_MutexUnlock(&tclObjMutex); +#endif } /* *---------------------------------------------------------------------- * * TclFinalizeCompExecEnv -- * - * Clean up the compiler execution environment so it can later be - * properly reinitialized. + * This procedure is called by Tcl_Finalize to clean up the Tcl + * compilation and execution environment so it can later be properly + * reinitialized. * * Results: * None. * * Side effects: - * Cleans up the execution environment + * Cleans up the compilation and execution environment * *---------------------------------------------------------------------- */ void TclFinalizeCompExecEnv() { - FinalizeTypeTable(); - FinalizeFreeObjList(); - TclFinalizeExecEnv(); + Tcl_MutexLock(&tableMutex); + if (typeTableInitialized) { + Tcl_DeleteHashTable(&typeTable); + typeTableInitialized = 0; + } + Tcl_MutexUnlock(&tableMutex); + Tcl_MutexLock(&tclObjMutex); + tclFreeObjList = NULL; + Tcl_MutexUnlock(&tclObjMutex); + + TclFinalizeCompilation(); + TclFinalizeExecution(); } /* *-------------------------------------------------------------- * @@ -243,18 +207,14 @@ * allocated (must live forever). */ { register Tcl_HashEntry *hPtr; int new; - if (!typeTableInitialized) { - InitTypeTable(); - } - /* * If there's already an object type with the given name, remove it. */ - + Tcl_MutexLock(&tableMutex); hPtr = Tcl_FindHashEntry(&typeTable, typePtr->name); if (hPtr != (Tcl_HashEntry *) NULL) { Tcl_DeleteHashEntry(hPtr); } @@ -264,10 +224,11 @@ hPtr = Tcl_CreateHashEntry(&typeTable, typePtr->name, &new); if (new) { Tcl_SetHashValue(hPtr, typePtr); } + Tcl_MutexUnlock(&tableMutex); } /* *---------------------------------------------------------------------- * @@ -274,11 +235,11 @@ * Tcl_AppendAllObjTypes -- * * This procedure 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_CreateObjType. These names can be used, for example, with + * 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 @@ -303,27 +264,26 @@ register Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_ObjType *typePtr; int result; - if (!typeTableInitialized) { - InitTypeTable(); - } - /* * This code assumes that types names do not contain embedded NULLs. */ + Tcl_MutexLock(&tableMutex); for (hPtr = Tcl_FirstHashEntry(&typeTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr); result = Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(typePtr->name, -1)); if (result == TCL_ERROR) { + Tcl_MutexUnlock(&tableMutex); return result; } } + Tcl_MutexUnlock(&tableMutex); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -348,19 +308,18 @@ char *typeName; /* Name of Tcl object type to look up. */ { register Tcl_HashEntry *hPtr; Tcl_ObjType *typePtr; - if (!typeTableInitialized) { - InitTypeTable(); - } - + Tcl_MutexLock(&tableMutex); hPtr = Tcl_FindHashEntry(&typeTable, typeName); if (hPtr != (Tcl_HashEntry *) NULL) { typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr); + Tcl_MutexUnlock(&tableMutex); return typePtr; } + Tcl_MutexUnlock(&tableMutex); return NULL; } /* *---------------------------------------------------------------------- @@ -442,13 +401,15 @@ Tcl_NewObj() { register Tcl_Obj *objPtr; /* - * Allocate the object using the list of free Tcl_Objs we maintain. + * Allocate the object using the list of free Tcl_Obj structs + * we maintain. */ + Tcl_MutexLock(&tclObjMutex); if (tclFreeObjList == NULL) { TclAllocateFreeObjects(); } objPtr = tclFreeObjList; tclFreeObjList = (Tcl_Obj *) tclFreeObjList->internalRep.otherValuePtr; @@ -458,10 +419,11 @@ objPtr->length = 0; objPtr->typePtr = NULL; #ifdef TCL_COMPILE_STATS tclObjsAlloced++; #endif /* TCL_COMPILE_STATS */ + Tcl_MutexUnlock(&tclObjMutex); return objPtr; } #endif /* TCL_MEM_DEBUG */ /* @@ -502,20 +464,23 @@ { register Tcl_Obj *objPtr; /* * If debugging Tcl's memory usage, allocate the object using ckalloc. - * Otherwise, allocate it using the list of free Tcl_Objs we maintain. + * Otherwise, allocate it using the list of free Tcl_Obj structs we + * maintain. */ objPtr = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), file, line); objPtr->refCount = 0; objPtr->bytes = tclEmptyStringRep; objPtr->length = 0; objPtr->typePtr = NULL; #ifdef TCL_COMPILE_STATS + Tcl_MutexLock(&tclObjMutex); tclObjsAlloced++; + Tcl_MutexUnlock(&tclObjMutex); #endif /* TCL_COMPILE_STATS */ return objPtr; } #else /* if not TCL_MEM_DEBUG */ @@ -536,10 +501,12 @@ * * TclAllocateFreeObjects -- * * Procedure 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: @@ -612,31 +579,33 @@ if ((objPtr)->refCount < -1) { panic("Reference count for %lx was negative", objPtr); } #endif /* TCL_MEM_DEBUG */ - Tcl_InvalidateStringRep(objPtr); if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { typePtr->freeIntRepProc(objPtr); } + Tcl_InvalidateStringRep(objPtr); /* * If debugging Tcl's memory usage, deallocate the object using ckfree. * Otherwise, deallocate it by adding it onto the list of free - * Tcl_Objs we maintain. + * Tcl_Obj structs we maintain. */ - + + Tcl_MutexLock(&tclObjMutex); #ifdef TCL_MEM_DEBUG ckfree((char *) objPtr); #else objPtr->internalRep.otherValuePtr = (VOID *) tclFreeObjList; tclFreeObjList = objPtr; #endif /* TCL_MEM_DEBUG */ -#ifdef TCL_COMPILE_STATS +#ifdef TCL_COMPILE_STATS tclObjsFreed++; -#endif /* TCL_COMPILE_STATS */ +#endif /* TCL_COMPILE_STATS */ + Tcl_MutexUnlock(&tclObjMutex); } /* *---------------------------------------------------------------------- * @@ -688,14 +657,57 @@ dupPtr->bytes[len] = '\0'; dupPtr->length = len; } if (typePtr != NULL) { - typePtr->dupIntRepProc(objPtr, dupPtr); + if (typePtr->dupIntRepProc == NULL) { + dupPtr->internalRep = objPtr->internalRep; + dupPtr->typePtr = typePtr; + } else { + (*typePtr->dupIntRepProc)(objPtr, dupPtr); + } } return dupPtr; } + +/* + *---------------------------------------------------------------------- + * + * 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(objPtr) + register Tcl_Obj *objPtr; /* Object whose string rep byte pointer + * should be returned. */ +{ + if (objPtr->bytes != NULL) { + return objPtr->bytes; + } + + if (objPtr->typePtr->updateStringProc == NULL) { + panic("UpdateStringProc should not be invoked for type %s", + objPtr->typePtr->name); + } + (*objPtr->typePtr->updateStringProc)(objPtr); + return objPtr->bytes; +} /* *---------------------------------------------------------------------- * * Tcl_GetStringFromObj -- @@ -731,11 +743,15 @@ *lengthPtr = objPtr->length; } return objPtr->bytes; } - objPtr->typePtr->updateStringProc(objPtr); + if (objPtr->typePtr->updateStringProc == NULL) { + panic("UpdateStringProc should not be invoked for type %s", + objPtr->typePtr->name); + } + (*objPtr->typePtr->updateStringProc)(objPtr); if (lengthPtr != NULL) { *lengthPtr = objPtr->length; } return objPtr->bytes; } @@ -956,37 +972,10 @@ } /* *---------------------------------------------------------------------- * - * DupBooleanInternalRep -- - * - * Initialize the internal representation of a boolean Tcl_Obj to a - * copy of the internal representation of an existing boolean object. - * - * Results: - * None. - * - * Side effects: - * "copyPtr"s internal rep is set to the boolean (an integer) - * corresponding to "srcPtr"s internal rep. - * - *---------------------------------------------------------------------- - */ - -static void -DupBooleanInternalRep(srcPtr, copyPtr) - register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ - register Tcl_Obj *copyPtr; /* Object with internal rep to set. */ -{ - copyPtr->internalRep.longValue = srcPtr->internalRep.longValue; - copyPtr->typePtr = &tclBooleanType; -} - -/* - *---------------------------------------------------------------------- - * * SetBooleanFromAny -- * * Attempt to generate a boolean internal form for the Tcl object * "objPtr". * @@ -1017,20 +1006,28 @@ /* * Get the string representation. Make it up-to-date if necessary. */ - string = TclGetStringFromObj(objPtr, &length); + string = Tcl_GetStringFromObj(objPtr, &length); /* * Copy the string converting its characters to lower case. */ for (i = 0; (i < 9) && (i < length); i++) { c = string[i]; - if (isupper(UCHAR(c))) { - c = (char) tolower(UCHAR(c)); + /* + * Weed out international characters so we can safely operate + * on single bytes. + */ + + if (c & 0x80) { + goto badBoolean; + } + if (isupper(UCHAR(c))) { /* INTL: ISO only. */ + c = (char) UCHAR(tolower(UCHAR(c))); /* INTL: ISO only. */ } lowerCase[i] = c; } lowerCase[i] = 0; @@ -1077,11 +1074,12 @@ /* * Make sure the string has no garbage after the end of the double. */ - while ((end < (string+length)) && isspace(UCHAR(*end))) { + while ((end < (string+length)) + && isspace(UCHAR(*end))) { /* INTL: ISO only */ end++; } if (end != (string+length)) { goto badBoolean; } @@ -1337,37 +1335,10 @@ } /* *---------------------------------------------------------------------- * - * DupDoubleInternalRep -- - * - * Initialize the internal representation of a double Tcl_Obj to a - * copy of the internal representation of an existing double object. - * - * Results: - * None. - * - * Side effects: - * "copyPtr"s internal rep is set to the double precision floating - * point number corresponding to "srcPtr"s internal rep. - * - *---------------------------------------------------------------------- - */ - -static void -DupDoubleInternalRep(srcPtr, copyPtr) - register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ - register Tcl_Obj *copyPtr; /* Object with internal rep to set. */ -{ - copyPtr->internalRep.doubleValue = srcPtr->internalRep.doubleValue; - copyPtr->typePtr = &tclDoubleType; -} - -/* - *---------------------------------------------------------------------- - * * SetDoubleFromAny -- * * Attempt to generate an double-precision floating point internal form * for the Tcl object "objPtr". * @@ -1395,11 +1366,11 @@ /* * Get the string representation. Make it up-to-date if necessary. */ - string = TclGetStringFromObj(objPtr, &length); + string = Tcl_GetStringFromObj(objPtr, &length); /* * Now parse "objPtr"s string as an double. Numbers can't have embedded * NULLs. We use an implementation here that doesn't report errors in * interp if interp is NULL. @@ -1432,11 +1403,12 @@ /* * Make sure that the string has no garbage after the end of the double. */ - while ((end < (string+length)) && isspace(UCHAR(*end))) { + while ((end < (string+length)) + && isspace(UCHAR(*end))) { /* INTL: ISO space. */ end++; } if (end != (string+length)) { goto badDouble; } @@ -1644,37 +1616,10 @@ } /* *---------------------------------------------------------------------- * - * DupIntInternalRep -- - * - * Initialize the internal representation of an int Tcl_Obj to a - * copy of the internal representation of an existing int object. - * - * Results: - * None. - * - * Side effects: - * "copyPtr"s internal rep is set to the integer corresponding to - * "srcPtr"s internal rep. - * - *---------------------------------------------------------------------- - */ - -static void -DupIntInternalRep(srcPtr, copyPtr) - register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ - register Tcl_Obj *copyPtr; /* Object with internal rep to set. */ -{ - copyPtr->internalRep.longValue = srcPtr->internalRep.longValue; - copyPtr->typePtr = &tclIntType; -} - -/* - *---------------------------------------------------------------------- - * * SetIntFromAny -- * * Attempt to generate an integer internal form for the Tcl object * "objPtr". * @@ -1703,11 +1648,11 @@ /* * Get the string representation. Make it up-to-date if necessary. */ - string = TclGetStringFromObj(objPtr, &length); + string = Tcl_GetStringFromObj(objPtr, &length); /* * Now parse "objPtr"s string as an int. We use an implementation here * that doesn't report errors in interp if interp is NULL. Note: use * strtoul instead of strtol for integer conversions to allow full-size @@ -1714,11 +1659,11 @@ * unsigned numbers, but don't depend on strtoul to handle sign * characters; it won't in some implementations. */ errno = 0; - for (p = string; isspace(UCHAR(*p)); p++) { + for (p = string; isspace(UCHAR(*p)); p++) { /* INTL: ISO space. */ /* Empty loop body. */ } if (*p == '-') { p++; newLong = -((long)strtoul(p, &end, 0)); @@ -1755,11 +1700,12 @@ /* * Make sure that the string has no garbage after the end of the int. */ - while ((end < (string+length)) && isspace(UCHAR(*end))) { + while ((end < (string+length)) + && isspace(UCHAR(*end))) { /* INTL: ISO space. */ end++; } if (end != (string+length)) { goto badInteger; } @@ -1801,11 +1747,11 @@ static void UpdateStringOfInt(objPtr) register Tcl_Obj *objPtr; /* Int object whose string rep to update. */ { - char buffer[TCL_DOUBLE_SPACE]; + char buffer[TCL_INTEGER_SPACE]; register int len; len = TclFormatInt(buffer, objPtr->internalRep.longValue); objPtr->bytes = ckalloc((unsigned) len + 1); @@ -2041,11 +1987,12 @@ *---------------------------------------------------------------------- */ void Tcl_DbIncrRefCount(objPtr, file, line) - register Tcl_Obj *objPtr; /* The object we are adding a reference to. */ + register Tcl_Obj *objPtr; /* The object we are registering a + * reference to. */ 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. */ { @@ -2064,13 +2011,13 @@ * * Tcl_DbDecrRefCount -- * * This procedure 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. + * the memory has been freed before decrementing the ref count. * - * When TCL_MEM_DEBUG is not defined, this procedure just increments + * When TCL_MEM_DEBUG is not defined, this procedure just decrements * the reference count of the object. * * Results: * None. * @@ -2080,11 +2027,12 @@ *---------------------------------------------------------------------- */ void Tcl_DbDecrRefCount(objPtr, file, line) - register Tcl_Obj *objPtr; /* The object we are adding a reference to. */ + register Tcl_Obj *objPtr; /* The object we are releasing a reference + * to. */ 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. */ { @@ -2104,29 +2052,28 @@ *---------------------------------------------------------------------- * * Tcl_DbIsShared -- * * This procedure 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. + * 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 procedure just decrements - * the reference count of the object and throws it away if the count - * is 0 or less. + * When TCL_MEM_DEBUG is not defined, this procedure just tests + * if the object has a ref count greater than one. * * Results: * None. * * Side effects: - * The object's ref count is incremented. + * None. * *---------------------------------------------------------------------- */ int Tcl_DbIsShared(objPtr, file, line) - register Tcl_Obj *objPtr; /* The object we are adding a reference to. */ + register Tcl_Obj *objPtr; /* The object to test for being shared. */ 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. */ { ADDED generic/tclPanic.c Index: generic/tclPanic.c ================================================================== --- /dev/null +++ generic/tclPanic.c @@ -0,0 +1,123 @@ +/* + * tclPanic.c -- + * + * Source code for the "Tcl_Panic" library procedure for Tcl; + * individual applications will probably override this with + * 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. + * + * RCS: @(#) $Id: tclPanic.c,v 1.2.6.1 1999/03/10 06:49:20 stanton Exp $ + */ + +#include "tclInt.h" + +/* + * The panicProc variable contains a pointer to an application + * specific panic procedure. + */ + +void (*panicProc) _ANSI_ARGS_(TCL_VARARGS(char *,format)) = NULL; + +/* + *---------------------------------------------------------------------- + * + * Tcl_SetPanicProc -- + * + * Replace the default panic behavior with the specified functiion. + * + * Results: + * None. + * + * Side effects: + * Sets the panicProc variable. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_SetPanicProc(proc) + void (*proc) _ANSI_ARGS_(TCL_VARARGS(char *,format)); +{ + 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 (format, argList) + char *format; /* Format string, suitable for passing to + * fprintf. */ + va_list argList; /* Variable argument list. */ +{ + char *arg1, *arg2, *arg3, *arg4; /* Additional arguments (variable in + * number) to pass to fprintf. */ + char *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) { + (void) (*panicProc)(format, arg1, arg2, arg3, arg4, + arg5, arg6, arg7, arg8); + } else { + (void) fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, + arg7, arg8); + (void) fprintf(stderr, "\n"); + (void) fflush(stderr); + abort(); + } +} + +/* + *---------------------------------------------------------------------- + * + * panic -- + * + * Print an error message and kill the process. + * + * Results: + * None. + * + * Side effects: + * The process dies, entering the debugger if possible. + * + *---------------------------------------------------------------------- + */ + + /* VARARGS ARGSUSED */ +void +panic TCL_VARARGS_DEF(char *,arg1) +{ + va_list argList; + char *format; + + format = TCL_VARARGS_START(char *,arg1,argList); + Tcl_PanicVA(format, argList); + va_end (argList); +} Index: generic/tclParse.c ================================================================== --- generic/tclParse.c +++ generic/tclParse.c @@ -1,729 +1,1746 @@ /* * tclParse.c -- * - * This file contains a collection of procedures that are used - * to parse Tcl commands or parts of commands (like quoted - * strings or nested sub-commands). + * This file contains procedures 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. This file also includes a few additional + * procedures such as Tcl_EvalObjv, Tcl_Eval, and Tcl_EvalEx, which + * allow scripts to be evaluated directly, without compiling. * - * Copyright (c) 1987-1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 1997 Sun Microsystems, Inc. + * Copyright (c) 1998 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclParse.c 1.56 97/07/29 18:40:03 + * RCS: @(#) $Id: tclParse.c,v 1.1.2.12 1999/04/14 00:33:26 surles Exp $ */ #include "tclInt.h" #include "tclPort.h" /* - * Function prototypes for procedures local to this file: - */ - -static char * QuoteEnd _ANSI_ARGS_((char *string, char *lastChar, - int term)); -static char * ScriptEnd _ANSI_ARGS_((char *p, char *lastChar, - int nested)); -static char * VarNameEnd _ANSI_ARGS_((char *string, char *lastChar)); - -/* - *-------------------------------------------------------------- - * - * TclParseQuotes -- - * - * This procedure parses a double-quoted string such as a - * quoted Tcl command argument or a quoted value in a Tcl - * expression. This procedure is also used to parse array - * element names within parentheses, or anything else that - * needs all the substitutions that happen in quotes. - * - * Results: - * The return value is a standard Tcl result, which is - * TCL_OK unless there was an error while parsing the - * quoted string. If an error occurs then interp->result - * contains a standard error message. *TermPtr is filled - * in with the address of the character just after the - * last one successfully processed; this is usually the - * character just after the matching close-quote. The - * fully-substituted contents of the quotes are stored in - * standard fashion in *pvPtr, null-terminated with - * pvPtr->next pointing to the terminating null character. - * - * Side effects: - * The buffer space in pvPtr may be enlarged by calling its - * expandProc. - * - *-------------------------------------------------------------- - */ - -int -TclParseQuotes(interp, string, termChar, flags, termPtr, pvPtr) - Tcl_Interp *interp; /* Interpreter to use for nested command - * evaluations and error messages. */ - char *string; /* Character just after opening double- - * quote. */ - int termChar; /* Character that terminates "quoted" string - * (usually double-quote, but sometimes - * right-paren or something else). */ - int flags; /* Flags to pass to nested Tcl_Eval calls. */ - char **termPtr; /* Store address of terminating character - * here. */ - ParseValue *pvPtr; /* Information about where to place - * fully-substituted result of parse. */ -{ - register char *src, *dst, c; - char *lastChar = string + strlen(string); - - src = string; - dst = pvPtr->next; - - while (1) { - if (dst == pvPtr->end) { - /* - * Target buffer space is about to run out. Make more space. - */ - - pvPtr->next = dst; - (*pvPtr->expandProc)(pvPtr, 1); - dst = pvPtr->next; - } - - c = *src; - src++; - if (c == termChar) { - *dst = '\0'; - pvPtr->next = dst; - *termPtr = src; - return TCL_OK; - } else if (CHAR_TYPE(src-1, lastChar) == TCL_NORMAL) { - copy: - *dst = c; - dst++; - continue; - } else if (c == '$') { - int length; - char *value; - - value = Tcl_ParseVar(interp, src-1, termPtr); - if (value == NULL) { - return TCL_ERROR; - } - src = *termPtr; - length = strlen(value); - if ((pvPtr->end - dst) <= length) { - pvPtr->next = dst; - (*pvPtr->expandProc)(pvPtr, length); - dst = pvPtr->next; - } - strcpy(dst, value); - dst += length; - continue; - } else if (c == '[') { - int result; - - pvPtr->next = dst; - result = TclParseNestedCmd(interp, src, flags, termPtr, pvPtr); - if (result != TCL_OK) { - return result; - } - src = *termPtr; - dst = pvPtr->next; - continue; - } else if (c == '\\') { - int numRead; - - src--; - *dst = Tcl_Backslash(src, &numRead); - dst++; - src += numRead; - continue; - } else if (c == '\0') { - char buf[30]; - - Tcl_ResetResult(interp); - sprintf(buf, "missing %c", termChar); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - *termPtr = string-1; - return TCL_ERROR; - } else { - goto copy; - } - } -} - -/* - *-------------------------------------------------------------- - * - * TclParseNestedCmd -- - * - * This procedure parses a nested Tcl command between - * brackets, returning the result of the command. - * - * Results: - * The return value is a standard Tcl result, which is - * TCL_OK unless there was an error while executing the - * nested command. If an error occurs then interp->result - * contains a standard error message. *TermPtr is filled - * in with the address of the character just after the - * last one processed; this is usually the character just - * after the matching close-bracket, or the null character - * at the end of the string if the close-bracket was missing - * (a missing close bracket is an error). The result returned - * by the command is stored in standard fashion in *pvPtr, - * null-terminated, with pvPtr->next pointing to the null - * character. - * - * Side effects: - * The storage space at *pvPtr may be expanded. - * - *-------------------------------------------------------------- - */ - -int -TclParseNestedCmd(interp, string, flags, termPtr, pvPtr) - Tcl_Interp *interp; /* Interpreter to use for nested command - * evaluations and error messages. */ - char *string; /* Character just after opening bracket. */ - int flags; /* Flags to pass to nested Tcl_Eval. */ - char **termPtr; /* Store address of terminating character - * here. */ - register ParseValue *pvPtr; /* Information about where to place - * result of command. */ -{ - int result, length, shortfall; - Interp *iPtr = (Interp *) interp; - - iPtr->evalFlags = flags | TCL_BRACKET_TERM; - result = Tcl_Eval(interp, string); - *termPtr = (string + iPtr->termOffset); - if (result != TCL_OK) { - /* - * The increment below results in slightly cleaner message in - * the errorInfo variable (the close-bracket will appear). - */ - - if (**termPtr == ']') { - *termPtr += 1; - } - return result; - } - (*termPtr) += 1; - length = strlen(iPtr->result); - shortfall = length + 1 - (pvPtr->end - pvPtr->next); - if (shortfall > 0) { - (*pvPtr->expandProc)(pvPtr, shortfall); - } - strcpy(pvPtr->next, iPtr->result); - pvPtr->next += length; - - Tcl_FreeResult(interp); - iPtr->result = iPtr->resultSpace; - iPtr->resultSpace[0] = '\0'; - return TCL_OK; -} - -/* - *-------------------------------------------------------------- - * - * TclParseBraces -- - * - * This procedure scans the information between matching - * curly braces. - * - * Results: - * The return value is a standard Tcl result, which is - * TCL_OK unless there was an error while parsing string. - * If an error occurs then interp->result contains a - * standard error message. *TermPtr is filled - * in with the address of the character just after the - * last one successfully processed; this is usually the - * character just after the matching close-brace. The - * information between curly braces is stored in standard - * fashion in *pvPtr, null-terminated with pvPtr->next - * pointing to the terminating null character. - * - * Side effects: - * The storage space at *pvPtr may be expanded. - * - *-------------------------------------------------------------- - */ - -int -TclParseBraces(interp, string, termPtr, pvPtr) - Tcl_Interp *interp; /* Interpreter to use for nested command - * evaluations and error messages. */ - char *string; /* Character just after opening bracket. */ - char **termPtr; /* Store address of terminating character - * here. */ - register ParseValue *pvPtr; /* Information about where to place - * result of command. */ -{ - int level; - register char *src, *dst, *end; - register char c; - char *lastChar = string + strlen(string); - - src = string; - dst = pvPtr->next; - end = pvPtr->end; - level = 1; - - /* - * Copy the characters one at a time to the result area, stopping - * when the matching close-brace is found. - */ - - while (1) { - c = *src; - src++; - if (dst == end) { - pvPtr->next = dst; - (*pvPtr->expandProc)(pvPtr, 20); - dst = pvPtr->next; - end = pvPtr->end; - } - *dst = c; - dst++; - if (CHAR_TYPE(src-1, lastChar) == TCL_NORMAL) { - continue; - } else if (c == '{') { - level++; - } else if (c == '}') { - level--; - if (level == 0) { - dst--; /* Don't copy the last close brace. */ - break; - } - } else if (c == '\\') { - int count; - - /* - * Must always squish out backslash-newlines, even when in - * braces. This is needed so that this sequence can appear - * anywhere in a command, such as the middle of an expression. - */ - - if (*src == '\n') { - dst[-1] = Tcl_Backslash(src-1, &count); - src += count - 1; - } else { - (void) Tcl_Backslash(src-1, &count); - while (count > 1) { - if (dst == end) { - pvPtr->next = dst; - (*pvPtr->expandProc)(pvPtr, 20); - dst = pvPtr->next; - end = pvPtr->end; - } - *dst = *src; - dst++; - src++; - count--; - } - } - } else if (c == '\0') { - Tcl_SetResult(interp, "missing close-brace", TCL_STATIC); - *termPtr = string-1; - return TCL_ERROR; - } - } - - *dst = '\0'; - pvPtr->next = dst; - *termPtr = src; - return TCL_OK; -} - -/* - *-------------------------------------------------------------- - * - * TclExpandParseValue -- - * - * This procedure is commonly used as the value of the - * expandProc in a ParseValue. It uses malloc to allocate - * more space for the result of a parse. - * - * Results: - * The buffer space in *pvPtr is reallocated to something - * larger, and if pvPtr->clientData is non-zero the old - * buffer is freed. Information is copied from the old - * buffer to the new one. - * - * Side effects: - * None. - * - *-------------------------------------------------------------- + * 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, open bracket, or null. + * 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). + */ + +#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) (typeTable+128)[(int)(c)] + +char typeTable[] = { + /* + * 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 procedures defined in this file: + */ + +static int CommandComplete _ANSI_ARGS_((char *script, + int length)); +static int ParseTokens _ANSI_ARGS_((char *src, int mask, + Tcl_Parse *parsePtr)); +static int EvalObjv _ANSI_ARGS_((Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[], char *command, int length, + int flags)); + +/* + *---------------------------------------------------------------------- + * + * Tcl_ParseCommand -- + * + * Given a string, this procedure 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 procedure returns TCL_OK then the caller must + * eventually invoke Tcl_FreeParse to release any additional space + * that was allocated. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr) + Tcl_Interp *interp; /* Interpreter to use for error reporting; + * if NULL, then no error message is + * provided. */ + char *string; /* First character of string containing + * one or more Tcl commands. The string + * must be in writable memory and must + * have one additional byte of space at + * string[length] where we can + * temporarily store a 0 sentinel + * character. */ + 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 char *src; /* Points to current character + * in the command. */ + int 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. */ + char utfBytes[TCL_UTF_MAX]; /* Holds result of backslash substitution. */ + int terminators; /* CHAR_TYPE bits that indicate the end + * of a command. */ + char *termPtr; /* Set by Tcl_ParseBraces/QuotedString to + * point to char after terminating one. */ + int length, savedChar; + + + if (numBytes < 0) { + numBytes = (string? strlen(string) : 0); + } + parsePtr->commentStart = NULL; + parsePtr->commentSize = 0; + parsePtr->commandStart = NULL; + parsePtr->commandSize = 0; + parsePtr->numWords = 0; + parsePtr->tokenPtr = parsePtr->staticTokens; + parsePtr->numTokens = 0; + parsePtr->tokensAvailable = NUM_STATIC_TOKENS; + parsePtr->string = string; + parsePtr->end = string + numBytes; + parsePtr->interp = interp; + parsePtr->incomplete = 0; + if (nested != 0) { + terminators = TYPE_COMMAND_END | TYPE_CLOSE_BRACK; + } else { + terminators = TYPE_COMMAND_END; + } + + /* + * Temporarily overwrite the character just after the end of the + * string with a 0 byte. This acts as a sentinel and reduces the + * number of places where we have to check for the end of the + * input string. The original value of the byte is restored at + * the end of the parse. + */ + + savedChar = string[numBytes]; + string[numBytes] = 0; + + /* + * Parse any leading space and comments before the first word of the + * command. + */ + + src = string; + while (1) { + while ((CHAR_TYPE(*src) == TYPE_SPACE) || (*src == '\n')) { + src++; + } + if ((*src == '\\') && (src[1] == '\n')) { + /* + * Skip backslash-newline sequence: it should be treated + * just like white space. + */ + + if ((src + 2) == parsePtr->end) { + parsePtr->incomplete = 1; + } + src += 2; + continue; + } + if (*src != '#') { + break; + } + if (parsePtr->commentStart == NULL) { + parsePtr->commentStart = src; + } + while (1) { + if (src == parsePtr->end) { + if (nested) { + parsePtr->incomplete = nested; + } + parsePtr->commentSize = src - parsePtr->commentStart; + break; + } else if (*src == '\\') { + if ((src[1] == '\n') && ((src + 2) == parsePtr->end)) { + parsePtr->incomplete = 1; + } + Tcl_UtfBackslash(src, &length, utfBytes); + src += length; + } else if (*src == '\n') { + src++; + parsePtr->commentSize = src - parsePtr->commentStart; + break; + } else { + src++; + } + } + } + + /* + * The following loop parses the words of the command, one word + * in each iteration through the loop. + */ + + parsePtr->commandStart = src; + while (1) { + /* + * Create the token for the word. + */ + + if (parsePtr->numTokens == parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + 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. + */ + + while (1) { + type = CHAR_TYPE(*src); + if (type == TYPE_SPACE) { + src++; + continue; + } else if ((*src == '\\') && (src[1] == '\n')) { + if ((src + 2) == parsePtr->end) { + parsePtr->incomplete = 1; + } + Tcl_UtfBackslash(src, &length, utfBytes); + src += length; + continue; + } + break; + } + if ((type & terminators) != 0) { + src++; + break; + } + if (src == parsePtr->end) { + break; + } + tokenPtr->start = src; + parsePtr->numTokens++; + parsePtr->numWords++; + + /* + * At this point the word can have one of three forms: something + * enclosed in quotes, something enclosed in braces, or an + * unquoted word (anything else). + */ + + if (*src == '"') { + if (Tcl_ParseQuotedString(interp, src, (parsePtr->end - src), + parsePtr, 1, &termPtr) != TCL_OK) { + goto error; + } + src = termPtr; + } else if (*src == '{') { + if (Tcl_ParseBraces(interp, src, (parsePtr->end - src), + parsePtr, 1, &termPtr) != TCL_OK) { + goto error; + } + src = termPtr; + } else { + /* + * This is an unquoted word. Call ParseTokens and let it do + * all of the work. + */ + + if (ParseTokens(src, TYPE_SPACE|terminators, + parsePtr) != TCL_OK) { + goto error; + } + src = parsePtr->term; + } + + /* + * 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 ((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. + */ + + type = CHAR_TYPE(*src); + if (type == TYPE_SPACE) { + src++; + continue; + } else { + /* + * Backslash-newline (and any following white space) must be + * treated as if it were a space character. + */ + + if ((*src == '\\') && (src[1] == '\n')) { + if ((src + 2) == parsePtr->end) { + parsePtr->incomplete = 1; + } + Tcl_UtfBackslash(src, &length, utfBytes); + src += length; + continue; + } + } + + if ((type & terminators) != 0) { + src++; + break; + } + if (src == parsePtr->end) { + break; + } + if (interp != NULL) { + if (src[-1] == '"') { + Tcl_SetResult(interp, "extra characters after close-quote", + TCL_STATIC); + } else { + Tcl_SetResult(interp, "extra characters after close-brace", + TCL_STATIC); + } + } + parsePtr->term = src; + goto error; + } + + + parsePtr->commandSize = src - parsePtr->commandStart; + string[numBytes] = (char) savedChar; + return TCL_OK; + + error: + string[numBytes] = (char) savedChar; + if (parsePtr->tokenPtr != parsePtr->staticTokens) { + ckfree((char *) parsePtr->tokenPtr); + parsePtr->tokenPtr = parsePtr->staticTokens; + } + if (parsePtr->commandStart == NULL) { + parsePtr->commandStart = string; + } + parsePtr->commandSize = parsePtr->term - parsePtr->commandStart; + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * ParseTokens -- + * + * This procedure 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 procedure is used to parse + * unquoted command words (those not in quotes or braces), words in + * quotes, and array indices for variables. + * + * 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 isn't NULL, then an error + * message is left in the interpreter's result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +ParseTokens(src, mask, parsePtr) + register char *src; /* First character to parse. */ + 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. */ + Tcl_Parse *parsePtr; /* Information about parse in progress. + * Updated with additional tokens and + * termination information. */ +{ + int type, originalTokens, varToken; + char utfBytes[TCL_UTF_MAX]; + Tcl_Token *tokenPtr; + Tcl_Parse nested; + + /* + * 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 (1) { + if (parsePtr->numTokens == parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens]; + tokenPtr->start = src; + tokenPtr->numComponents = 0; + + type = CHAR_TYPE(*src); + if (type & mask) { + break; + } + + if ((type & TYPE_SUBS) == 0) { + /* + * This is a simple range of characters. Scan to find the end + * of the range. + */ + + while (1) { + src++; + if (CHAR_TYPE(*src) & (mask | TYPE_SUBS)) { + break; + } + } + tokenPtr->type = TCL_TOKEN_TEXT; + tokenPtr->size = src - tokenPtr->start; + parsePtr->numTokens++; + } else if (*src == '$') { + /* + * 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, parsePtr->end - src, + parsePtr, 1) != TCL_OK) { + return TCL_ERROR; + } + src += parsePtr->tokenPtr[varToken].size; + } else if (*src == '[') { + /* + * Command substitution. Call Tcl_ParseCommand recursively + * (and repeatedly) to parse the nested command(s), then + * throw away the parse information. + */ + + src++; + while (1) { + if (Tcl_ParseCommand(parsePtr->interp, src, + parsePtr->end - src, 1, &nested) != TCL_OK) { + parsePtr->term = nested.term; + parsePtr->incomplete = nested.incomplete; + return TCL_ERROR; + } + src = nested.commandStart + nested.commandSize; + if (nested.tokenPtr != nested.staticTokens) { + ckfree((char *) nested.tokenPtr); + } + if ((src[-1] == ']') && !nested.incomplete) { + break; + } + if (src == parsePtr->end) { + if (parsePtr->interp != NULL) { + Tcl_SetResult(parsePtr->interp, + "missing close-bracket", TCL_STATIC); + } + parsePtr->term = tokenPtr->start; + parsePtr->incomplete = 1; + return TCL_ERROR; + } + } + tokenPtr->type = TCL_TOKEN_COMMAND; + tokenPtr->size = src - tokenPtr->start; + parsePtr->numTokens++; + } else if (*src == '\\') { + /* + * Backslash substitution. + */ + + if (src[1] == '\n') { + if ((src + 2) == parsePtr->end) { + 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) { + break; + } + } + tokenPtr->type = TCL_TOKEN_BS; + Tcl_UtfBackslash(src, &tokenPtr->size, utfBytes); + parsePtr->numTokens++; + src += tokenPtr->size; + } else if (*src == 0) { + /* + * We encountered a null character. If it is the null + * character at the end of the string, then return. + * Otherwise generate a text token for the single + * character. + */ + + if (src == parsePtr->end) { + break; + } + tokenPtr->type = TCL_TOKEN_TEXT; + tokenPtr->size = 1; + parsePtr->numTokens++; + src++; + } else { + 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. + */ + + tokenPtr->type = TCL_TOKEN_TEXT; + tokenPtr->size = 0; + parsePtr->numTokens++; + } + parsePtr->term = src; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_FreeParse -- + * + * This procedure 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(parsePtr) + Tcl_Parse *parsePtr; /* Structure that was filled in by a + * previous call to Tcl_ParseCommand. */ +{ + if (parsePtr->tokenPtr != parsePtr->staticTokens) { + ckfree((char *) parsePtr->tokenPtr); + parsePtr->tokenPtr = parsePtr->staticTokens; + } +} + +/* + *---------------------------------------------------------------------- + * + * TclExpandTokenArray -- + * + * This procedure is invoked when the current space for tokens in + * a Tcl_Parse structure fills up; it allocates memory to grow the + * token array + * + * Results: + * None. + * + * Side effects: + * Memory is allocated for a new larger token array; the memory + * for the old array is freed, if it had been dynamically allocated. + * + *---------------------------------------------------------------------- + */ + +void +TclExpandTokenArray(parsePtr) + Tcl_Parse *parsePtr; /* Parse structure whose token space + * has overflowed. */ +{ + int newCount; + Tcl_Token *newPtr; + + newCount = parsePtr->tokensAvailable*2; + newPtr = (Tcl_Token *) ckalloc((unsigned) (newCount * sizeof(Tcl_Token))); + memcpy((VOID *) newPtr, (VOID *) parsePtr->tokenPtr, + (size_t) (parsePtr->tokensAvailable * sizeof(Tcl_Token))); + if (parsePtr->tokenPtr != parsePtr->staticTokens) { + ckfree((char *) parsePtr->tokenPtr); + parsePtr->tokenPtr = parsePtr->staticTokens; + } + parsePtr->tokenPtr = newPtr; + parsePtr->tokensAvailable = newCount; +} + +/* + *---------------------------------------------------------------------- + * + * EvalObjv -- + * + * This procedure 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. If an error occurs, this procedure does + * NOT add any information to the errorInfo variable. + * + * Side effects: + * Depends on the command. + * + *---------------------------------------------------------------------- + */ + +static int +EvalObjv(interp, objc, objv, command, length, flags) + 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. */ + char *command; /* Points to the beginning of the string + * representation of the command; this + * is used for traces. If the string + * representation of the command is + * unknown, an empty string should be + * supplied. */ + int length; /* Number of bytes in command; if -1, all + * characters up to the first null byte are + * used. */ + int flags; /* Collection of OR-ed bits that control + * the evaluation of the script. Only + * TCL_EVAL_GLOBAL is currently + * supported. */ + +{ + Command *cmdPtr; + Interp *iPtr = (Interp *) interp; + Tcl_Obj **newObjv; + int i, code; + Trace *tracePtr, *nextPtr; + char **argv, *commandCopy; + CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr + * in case TCL_EVAL_GLOBAL was set. */ + + Tcl_ResetResult(interp); + if (objc == 0) { + return TCL_OK; + } + + /* + * If the interpreter was deleted, return an error. + */ + + if (iPtr->flags & DELETED) { + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "attempt to call eval in deleted interpreter", -1); + Tcl_SetErrorCode(interp, "CORE", "IDELETE", + "attempt to call eval in deleted interpreter", + (char *) NULL); + 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) { + iPtr->result = "too many nested calls to Tcl_Eval (infinite loop?)"; + return TCL_ERROR; + } + iPtr->numLevels++; + + /* + * On the Mac, we will never reach the default recursion limit before + * blowing the stack. So we need to do a check here. + */ + + if (TclpCheckStackSpace() == 0) { + /*NOTREACHED*/ + iPtr->numLevels--; + iPtr->result = "too many nested calls to Tcl_Eval (infinite loop?)"; + return TCL_ERROR; + } + + /* + * Find the procedure to execute this command. If there isn't one, + * then see if there is a command "unknown". If so, create a new + * word array with "unknown" as the first word and the original + * command words as arguments. Then call ourselves recursively + * to execute it. + */ + + cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]); + if (cmdPtr == NULL) { + newObjv = (Tcl_Obj **) ckalloc((unsigned) + ((objc + 1) * sizeof (Tcl_Obj *))); + for (i = objc-1; i >= 0; i--) { + newObjv[i+1] = objv[i]; + } + newObjv[0] = Tcl_NewStringObj("unknown", -1); + Tcl_IncrRefCount(newObjv[0]); + cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, newObjv[0]); + if (cmdPtr == NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "invalid command name \"", Tcl_GetString(objv[0]), "\"", + (char *) NULL); + code = TCL_ERROR; + } else { + code = EvalObjv(interp, objc+1, newObjv, command, length, 0); + } + Tcl_DecrRefCount(newObjv[0]); + ckfree((char *) newObjv); + goto done; + } + + /* + * Call trace procedures if needed. + */ + + argv = NULL; + commandCopy = command; + + for (tracePtr = iPtr->tracePtr; tracePtr != NULL; tracePtr = nextPtr) { + nextPtr = tracePtr->nextPtr; + if (iPtr->numLevels > tracePtr->level) { + continue; + } + + /* + * This is a bit messy because we have to emulate the old trace + * interface, which uses strings for everything. + */ + + if (argv == NULL) { + argv = (char **) ckalloc((unsigned) (objc + 1) * sizeof(char *)); + for (i = 0; i < objc; i++) { + argv[i] = Tcl_GetString(objv[i]); + } + argv[objc] = 0; + + if (length < 0) { + length = strlen(command); + } else if ((size_t)length < strlen(command)) { + commandCopy = (char *) ckalloc((unsigned) (length + 1)); + strncpy(commandCopy, command, (size_t) length); + commandCopy[length] = 0; + } + } + (*tracePtr->proc)(tracePtr->clientData, interp, iPtr->numLevels, + commandCopy, cmdPtr->proc, cmdPtr->clientData, + objc, argv); + } + if (argv != NULL) { + ckfree((char *) argv); + } + if (commandCopy != command) { + ckfree((char *) commandCopy); + } + + /* + * Finally, invoke the command's Tcl_ObjCmdProc. + */ + + iPtr->cmdCount++; + savedVarFramePtr = iPtr->varFramePtr; + if (flags & TCL_EVAL_GLOBAL) { + iPtr->varFramePtr = NULL; + } + code = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv); + iPtr->varFramePtr = savedVarFramePtr; + if (Tcl_AsyncReady()) { + code = Tcl_AsyncInvoke(interp, code); + } + + /* + * If the interpreter has a non-empty string result, the result + * object is either empty or stale because some procedure set + * interp->result directly. If so, move the string result to the + * result object, then reset the string result. + */ + + if (*(iPtr->result) != 0) { + (void) Tcl_GetObjResult(interp); + } + + done: + iPtr->numLevels--; + return code; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_EvalObjv -- + * + * This procedure 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: + * Depends on the command. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_EvalObjv(interp, objc, objv, flags) + 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 is currently + * supported. */ +{ + Interp *iPtr = (Interp *)interp; + Trace *tracePtr; + Tcl_DString cmdBuf; + char *cmdString = ""; + int cmdLen = 0; + int code = TCL_OK; + + for (tracePtr = iPtr->tracePtr; tracePtr; tracePtr = tracePtr->nextPtr) { + /* + * EvalObjv will increment numLevels so use "<" rather than "<=" + */ + if (iPtr->numLevels < tracePtr->level) { + int i; + /* + * The command will be needed for an execution trace or stack trace + * generate a command string. + */ + cmdtraced: + Tcl_DStringInit(&cmdBuf); + for (i = 0; i < objc; i++) { + Tcl_DStringAppendElement(&cmdBuf, Tcl_GetString(objv[i])); + } + cmdString = Tcl_DStringValue(&cmdBuf); + cmdLen = Tcl_DStringLength(&cmdBuf); + break; + } + } + + /* + * Execute the command if we have not done so already + */ + switch (code) { + case TCL_OK: + code = EvalObjv(interp, objc, objv, cmdString, cmdLen, flags); + if (code == TCL_ERROR && cmdLen == 0) + goto cmdtraced; + break; + case TCL_ERROR: + Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen); + break; + default: + /*NOTREACHED*/ + break; + } + + if (cmdLen != 0) { + Tcl_DStringFree(&cmdBuf); + } + return code; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_LogCommandInfo -- + * + * This procedure is invoked after an error occurs in an interpreter. + * It adds information to the "errorInfo" variable to describe the + * command that was being executed when the error occurred. + * + * Results: + * None. + * + * Side effects: + * Information about the command is added to errorInfo and the + * line number stored internally in the interpreter is set. If this + * is the first call to this procedure or Tcl_AddObjErrorInfo since + * an error occurred, then old information in errorInfo is + * deleted. + * + *---------------------------------------------------------------------- */ void -TclExpandParseValue(pvPtr, needed) - register ParseValue *pvPtr; /* Information about buffer that - * must be expanded. If the clientData - * in the structure is non-zero, it - * means that the current buffer is - * dynamically allocated. */ - int needed; /* Minimum amount of additional space - * to allocate. */ -{ - int newSpace; - char *new; - - /* - * Either double the size of the buffer or add enough new space - * to meet the demand, whichever produces a larger new buffer. - */ - - newSpace = (pvPtr->end - pvPtr->buffer) + 1; - if (newSpace < needed) { - newSpace += needed; - } else { - newSpace += newSpace; - } - new = (char *) ckalloc((unsigned) newSpace); - - /* - * Copy from old buffer to new, free old buffer if needed, and - * mark new buffer as malloc-ed. - */ - - memcpy((VOID *) new, (VOID *) pvPtr->buffer, - (size_t) (pvPtr->next - pvPtr->buffer)); - pvPtr->next = new + (pvPtr->next - pvPtr->buffer); - if (pvPtr->clientData != 0) { - ckfree(pvPtr->buffer); - } - pvPtr->buffer = new; - pvPtr->end = new + newSpace - 1; - pvPtr->clientData = (ClientData) 1; -} - -/* - *---------------------------------------------------------------------- - * - * TclWordEnd -- - * - * Given a pointer into a Tcl command, find the end of the next - * word of the command. - * - * Results: - * The return value is a pointer to the last character that's part - * of the word pointed to by "start". If the word doesn't end - * properly within the string then the return value is the address - * of the null character at the end of the string. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -char * -TclWordEnd(start, lastChar, nested, semiPtr) - char *start; /* Beginning of a word of a Tcl command. */ - char *lastChar; /* Terminating character in string. */ - int nested; /* Zero means this is a top-level command. - * One means this is a nested command (close - * bracket is a word terminator). */ - int *semiPtr; /* Set to 1 if word ends with a command- - * terminating semi-colon, zero otherwise. - * If NULL then ignored. */ -{ - register char *p; - int count; - - if (semiPtr != NULL) { - *semiPtr = 0; - } - - /* - * Skip leading white space (backslash-newline must be treated like - * white-space, except that it better not be the last thing in the - * command). - */ - - for (p = start; ; p++) { - if (isspace(UCHAR(*p))) { - continue; - } - if ((p[0] == '\\') && (p[1] == '\n')) { - if (p+2 == lastChar) { - return p+2; - } - continue; - } - break; - } - - /* - * Handle words beginning with a double-quote or a brace. - */ - - if (*p == '"') { - p = QuoteEnd(p+1, lastChar, '"'); - if (p == lastChar) { - return p; - } - p++; - } else if (*p == '{') { - int braces = 1; - while (braces != 0) { - p++; - while (*p == '\\') { - (void) Tcl_Backslash(p, &count); - p += count; - } - if (*p == '}') { - braces--; - } else if (*p == '{') { - braces++; - } else if (p == lastChar) { - return p; - } - } - p++; - } - - /* - * Handle words that don't start with a brace or double-quote. - * This code is also invoked if the word starts with a brace or - * double-quote and there is garbage after the closing brace or - * quote. This is an error as far as Tcl_Eval is concerned, but - * for here the garbage is treated as part of the word. - */ - - while (1) { - if (*p == '[') { - p = ScriptEnd(p+1, lastChar, 1); - if (p == lastChar) { - return p; - } - p++; - } else if (*p == '\\') { - if (p[1] == '\n') { - /* - * Backslash-newline: it maps to a space character - * that is a word separator, so the word ends just before - * the backslash. - */ - - return p-1; - } - (void) Tcl_Backslash(p, &count); - p += count; - } else if (*p == '$') { - p = VarNameEnd(p, lastChar); - if (p == lastChar) { - return p; - } - p++; - } else if (*p == ';') { - /* - * Include the semi-colon in the word that is returned. - */ - - if (semiPtr != NULL) { - *semiPtr = 1; - } - return p; - } else if (isspace(UCHAR(*p))) { - return p-1; - } else if ((*p == ']') && nested) { - return p-1; - } else if (p == lastChar) { - if (nested) { - /* - * Nested commands can't end because of the end of the - * string. - */ - return p; - } - return p-1; - } else { - p++; - } - } -} - -/* - *---------------------------------------------------------------------- - * - * QuoteEnd -- - * - * Given a pointer to a string that obeys the parsing conventions - * for quoted things in Tcl, find the end of that quoted thing. - * The actual thing may be a quoted argument or a parenthesized - * index name. - * - * Results: - * The return value is a pointer to the last character that is - * part of the quoted string (i.e the character that's equal to - * term). If the quoted string doesn't terminate properly then - * the return value is a pointer to the null character at the - * end of the string. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static char * -QuoteEnd(string, lastChar, term) - char *string; /* Pointer to character just after opening - * "quote". */ - char *lastChar; /* Terminating character in string. */ - int term; /* This character will terminate the - * quoted string (e.g. '"' or ')'). */ -{ - register char *p = string; - int count; - - while (*p != term) { - if (*p == '\\') { - (void) Tcl_Backslash(p, &count); - p += count; - } else if (*p == '[') { - for (p++; *p != ']'; p++) { - p = TclWordEnd(p, lastChar, 1, (int *) NULL); - if (*p == 0) { - return p; - } - } - p++; - } else if (*p == '$') { - p = VarNameEnd(p, lastChar); - if (*p == 0) { - return p; - } - p++; - } else if (p == lastChar) { - return p; - } else { - p++; - } - } - return p-1; -} - -/* - *---------------------------------------------------------------------- - * - * VarNameEnd -- - * - * Given a pointer to a variable reference using $-notation, find - * the end of the variable name spec. - * - * Results: - * The return value is a pointer to the last character that - * is part of the variable name. If the variable name doesn't - * terminate properly then the return value is a pointer to the - * null character at the end of the string. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static char * -VarNameEnd(string, lastChar) - char *string; /* Pointer to dollar-sign character. */ - char *lastChar; /* Terminating character in string. */ -{ - register char *p = string+1; - - if (*p == '{') { - for (p++; (*p != '}') && (p != lastChar); p++) { - /* Empty loop body. */ - } - return p; - } - while (isalnum(UCHAR(*p)) || (*p == '_')) { - p++; - } - if ((*p == '(') && (p != string+1)) { - return QuoteEnd(p+1, lastChar, ')'); - } - return p-1; -} - - -/* - *---------------------------------------------------------------------- - * - * ScriptEnd -- - * - * Given a pointer to the beginning of a Tcl script, find the end of - * the script. - * - * Results: - * The return value is a pointer to the last character that's part - * of the script pointed to by "p". If the command doesn't end - * properly within the string then the return value is the address - * of the null character at the end of the string. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static char * -ScriptEnd(p, lastChar, nested) - char *p; /* Script to check. */ - char *lastChar; /* Terminating character in string. */ - int nested; /* Zero means this is a top-level command. - * One means this is a nested command (the - * last character of the script must be - * an unquoted ]). */ -{ - int commentOK = 1; - int length; - - while (1) { - while (isspace(UCHAR(*p))) { - if (*p == '\n') { - commentOK = 1; - } - p++; - } - if ((*p == '#') && commentOK) { - do { - if (*p == '\\') { - /* - * If the script ends with backslash-newline, then - * this command isn't complete. - */ - - if ((p[1] == '\n') && (p+2 == lastChar)) { - return p+2; - } - Tcl_Backslash(p, &length); - p += length; - } else { - p++; - } - } while ((p != lastChar) && (*p != '\n')); - continue; - } - p = TclWordEnd(p, lastChar, nested, &commentOK); - if (p == lastChar) { - return p; - } - p++; - if (nested) { - if (*p == ']') { - return p; - } - } else { - if (p == lastChar) { - return p-1; - } - } - } +Tcl_LogCommandInfo(interp, script, command, length) + Tcl_Interp *interp; /* Interpreter in which to log information. */ + char *script; /* First character in script containing + * command (must be <= command). */ + 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). */ +{ + char buffer[200]; + register char *p; + char *ellipsis = ""; + Interp *iPtr = (Interp *) interp; + + if (iPtr->flags & ERR_ALREADY_LOGGED) { + /* + * Someone else has already logged error information for this + * command; we shouldn't add anything more. + */ + + return; + } + + /* + * Compute the line number where the error occurred. + */ + + iPtr->errorLine = 1; + for (p = script; p != command; p++) { + if (*p == '\n') { + iPtr->errorLine++; + } + } + + /* + * Create an error message to add to errorInfo, including up to a + * maximum number of characters of the command. + */ + + if (length < 0) { + length = strlen(command); + } + if (length > 150) { + length = 150; + ellipsis = "..."; + } + if (!(iPtr->flags & ERR_IN_PROGRESS)) { + sprintf(buffer, "\n while executing\n\"%.*s%s\"", + length, command, ellipsis); + } else { + sprintf(buffer, "\n invoked from within\n\"%.*s%s\"", + length, command, ellipsis); + } + Tcl_AddObjErrorInfo(interp, buffer, -1); + iPtr->flags &= ~ERR_ALREADY_LOGGED; +} + +/* + *---------------------------------------------------------------------- + * + * 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 procedure 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. + * + *---------------------------------------------------------------------- + */ + +Tcl_Obj * +Tcl_EvalTokens(interp, tokenPtr, count) + 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 *resultPtr, *indexPtr, *valuePtr, *newPtr; + char buffer[TCL_UTF_MAX]; +#ifdef TCL_MEM_DEBUG +# define MAX_VAR_CHARS 5 +#else +# define MAX_VAR_CHARS 30 +#endif + char nameBuffer[MAX_VAR_CHARS+1]; + char *varName, *index; + char *p = NULL; /* Initialized to avoid compiler warning. */ + int length, code; + + /* + * The only tricky thing about this procedure is that it attempts to + * avoid object creation and string copying whenever possible. For + * example, if the value is just a nested command, then use the + * command's result object directly. + */ + + resultPtr = NULL; + for ( ; count > 0; count--, tokenPtr++) { + valuePtr = NULL; + + /* + * The switch statement below computes the next value to be + * concat to the result, as either a range of text or an + * object. + */ + + switch (tokenPtr->type) { + case TCL_TOKEN_TEXT: + p = tokenPtr->start; + length = tokenPtr->size; + break; + + case TCL_TOKEN_BS: + length = Tcl_UtfBackslash(tokenPtr->start, (int *) NULL, + buffer); + p = buffer; + break; + + case TCL_TOKEN_COMMAND: + code = Tcl_EvalEx(interp, tokenPtr->start+1, tokenPtr->size-2, + 0); + if (code != TCL_OK) { + goto error; + } + valuePtr = Tcl_GetObjResult(interp); + break; + + case TCL_TOKEN_VARIABLE: + if (tokenPtr->numComponents == 1) { + indexPtr = NULL; + } else { + indexPtr = Tcl_EvalTokens(interp, tokenPtr+2, + tokenPtr->numComponents - 1); + if (indexPtr == NULL) { + goto error; + } + } + + /* + * We have to make a copy of the variable name in order + * to have a null-terminated string. We can't make a + * temporary modification to the script to null-terminate + * the name, because a trace callback might potentially + * reuse the script and be affected by the null character. + */ + + if (tokenPtr[1].size <= MAX_VAR_CHARS) { + varName = nameBuffer; + } else { + varName = ckalloc((unsigned) (tokenPtr[1].size + 1)); + } + strncpy(varName, tokenPtr[1].start, (size_t) tokenPtr[1].size); + varName[tokenPtr[1].size] = 0; + if (indexPtr != NULL) { + index = TclGetString(indexPtr); + } else { + index = NULL; + } + valuePtr = Tcl_GetVar2Ex(interp, varName, index, + TCL_LEAVE_ERR_MSG); + if (varName != nameBuffer) { + ckfree(varName); + } + if (indexPtr != NULL) { + Tcl_DecrRefCount(indexPtr); + } + if (valuePtr == NULL) { + goto error; + } + count -= tokenPtr->numComponents; + tokenPtr += tokenPtr->numComponents; + break; + + default: + panic("unexpected token type in Tcl_EvalTokens"); + } + + /* + * If valuePtr isn't NULL, the next piece of text comes from that + * object; otherwise, take length bytes starting at p. + */ + + if (resultPtr == NULL) { + if (valuePtr != NULL) { + resultPtr = valuePtr; + } else { + resultPtr = Tcl_NewStringObj(p, length); + } + Tcl_IncrRefCount(resultPtr); + } else { + if (Tcl_IsShared(resultPtr)) { + newPtr = Tcl_DuplicateObj(resultPtr); + Tcl_DecrRefCount(resultPtr); + resultPtr = newPtr; + Tcl_IncrRefCount(resultPtr); + } + if (valuePtr != NULL) { + p = Tcl_GetStringFromObj(valuePtr, &length); + } + Tcl_AppendToObj(resultPtr, p, length); + } + } + return resultPtr; + + error: + if (resultPtr != NULL) { + Tcl_DecrRefCount(resultPtr); + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_EvalEx -- + * + * This procedure 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. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_EvalEx(interp, script, numBytes, flags) + Tcl_Interp *interp; /* Interpreter in which to evaluate the + * script. Also used for error reporting. */ + 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. */ +{ + Interp *iPtr = (Interp *) interp; + char *p, *next; + Tcl_Parse parse; +#define NUM_STATIC_OBJS 20 + Tcl_Obj *staticObjArray[NUM_STATIC_OBJS], **objv; + Tcl_Token *tokenPtr; + int i, code, commandLength, bytesLeft, nested; + CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr + * in case TCL_EVAL_GLOBAL was set. */ + + /* + * The variables below keep track of how much state has been + * allocated while evaluating the script, so that it can be freed + * properly if an error occurs. + */ + + int gotParse = 0, objectsUsed = 0; + + if (numBytes < 0) { + numBytes = strlen(script); + } + Tcl_ResetResult(interp); + + savedVarFramePtr = iPtr->varFramePtr; + if (flags & TCL_EVAL_GLOBAL) { + iPtr->varFramePtr = NULL; + } + + /* + * Each iteration through the following loop parses the next + * command from the script and then executes it. + */ + + objv = staticObjArray; + p = script; + bytesLeft = numBytes; + if (iPtr->evalFlags & TCL_BRACKET_TERM) { + nested = 1; + } else { + nested = 0; + } + iPtr->evalFlags = 0; + do { + if (Tcl_ParseCommand(interp, p, bytesLeft, nested, &parse) + != TCL_OK) { + code = TCL_ERROR; + goto error; + } + gotParse = 1; + if (parse.numWords > 0) { + /* + * Generate an array of objects for the words of the command. + */ + + if (parse.numWords <= NUM_STATIC_OBJS) { + objv = staticObjArray; + } else { + objv = (Tcl_Obj **) ckalloc((unsigned) + (parse.numWords * sizeof (Tcl_Obj *))); + } + for (objectsUsed = 0, tokenPtr = parse.tokenPtr; + objectsUsed < parse.numWords; + objectsUsed++, tokenPtr += (tokenPtr->numComponents + 1)) { + objv[objectsUsed] = Tcl_EvalTokens(interp, tokenPtr+1, + tokenPtr->numComponents); + if (objv[objectsUsed] == NULL) { + code = TCL_ERROR; + goto error; + } + } + + /* + * Execute the command and free the objects for its words. + */ + + code = EvalObjv(interp, objectsUsed, objv, p, bytesLeft, 0); + if (code != TCL_OK) { + goto error; + } + for (i = 0; i < objectsUsed; i++) { + Tcl_DecrRefCount(objv[i]); + } + objectsUsed = 0; + if (objv != staticObjArray) { + ckfree((char *) objv); + objv = staticObjArray; + } + } + + /* + * Advance to the next command in the script. + */ + + next = parse.commandStart + parse.commandSize; + bytesLeft -= next - p; + p = next; + Tcl_FreeParse(&parse); + gotParse = 0; + if ((nested != 0) && (p > script) && (p[-1] == ']')) { + /* + * We get here in the special case where the TCL_BRACKET_TERM + * flag was set in the interpreter and we reached a close + * bracket in the script. Return immediately. + */ + + iPtr->termOffset = (p - 1) - script; + iPtr->varFramePtr = savedVarFramePtr; + return TCL_OK; + } + } while (bytesLeft > 0); + iPtr->termOffset = p - script; + iPtr->varFramePtr = savedVarFramePtr; + return TCL_OK; + + error: + /* + * Generate various pieces of error information, such as the line + * number where the error occurred and information to add to the + * errorInfo variable. Then free resources that had been allocated + * to the command. + */ + + if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { + commandLength = parse.commandSize; + if ((parse.commandStart + commandLength) != (script + numBytes)) { + /* + * The command where the error occurred didn't end at the end + * of the script (i.e. it ended at a terminator character such + * as ";". Reduce the length by one so that the error message + * doesn't include the terminator character. + */ + + commandLength -= 1; + } + Tcl_LogCommandInfo(interp, script, parse.commandStart, commandLength); + } + + for (i = 0; i < objectsUsed; i++) { + Tcl_DecrRefCount(objv[i]); + } + if (gotParse) { + Tcl_FreeParse(&parse); + } + if (objv != staticObjArray) { + ckfree((char *) objv); + } + iPtr->varFramePtr = savedVarFramePtr; + return code; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_Eval -- + * + * Execute a Tcl command in a string. This procedure 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 procedure 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. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_Eval(interp, string) + Tcl_Interp *interp; /* Token for command interpreter (returned + * by previous call to Tcl_CreateInterp). */ + char *string; /* Pointer to TCL command to execute. */ +{ + int code; + + code = Tcl_EvalEx(interp, string, -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). + */ + + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), + TCL_VOLATILE); + 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(interp, objPtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; +{ + return Tcl_EvalObjEx(interp, objPtr, 0); +} + +#undef Tcl_GlobalEvalObj +int +Tcl_GlobalEvalObj(interp, objPtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; +{ + return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_ParseVarName -- + * + * Given a string starting with a $ sign, parse off a variable + * name and return information about the parse. + * + * 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 procedure returns TCL_OK then the caller must + * eventually invoke Tcl_FreeParse to release any additional space + * that was allocated. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_ParseVarName(interp, string, numBytes, parsePtr, append) + Tcl_Interp *interp; /* Interpreter to use for error reporting; + * if NULL, then no error message is + * provided. */ + char *string; /* String containing variable name. First + * character must be "$". */ + 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; + char *end, *src; + unsigned char c; + int varIndex, offset; + Tcl_UniChar ch; + + if (numBytes >= 0) { + end = string + numBytes; + } else { + end = string + strlen(string); + } + + if (!append) { + parsePtr->numWords = 0; + parsePtr->tokenPtr = parsePtr->staticTokens; + parsePtr->numTokens = 0; + parsePtr->tokensAvailable = NUM_STATIC_TOKENS; + parsePtr->string = string; + parsePtr->end = end; + parsePtr->interp = interp; + parsePtr->incomplete = 0; + } + + /* + * 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 = string; + if ((parsePtr->numTokens + 2) > parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens]; + tokenPtr->type = TCL_TOKEN_VARIABLE; + tokenPtr->start = src; + varIndex = parsePtr->numTokens; + parsePtr->numTokens++; + tokenPtr++; + src++; + if (src >= end) { + 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++; + tokenPtr->type = TCL_TOKEN_TEXT; + tokenPtr->start = src; + tokenPtr->numComponents = 0; + while (1) { + if (src == end) { + if (interp != NULL) { + Tcl_SetResult(interp, + "missing close-brace for variable name", + TCL_STATIC); + } + parsePtr->term = tokenPtr->start-1; + parsePtr->incomplete = 1; + goto error; + } + if (*src == '}') { + break; + } + src++; + } + 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 (src != end) { + offset = Tcl_UtfToUniChar(src, &ch); + c = UCHAR(ch); + if (isalnum(c) || (c == '_')) { /* INTL: ISO only, UCHAR. */ + src += offset; + continue; + } + if ((c == ':') && (((src+1) != end) && (src[1] == ':'))) { + src += 2; + while ((src != end) && (*src == ':')) { + src += 1; + } + continue; + } + break; + } + tokenPtr->size = src - tokenPtr->start; + if (tokenPtr->size == 0) { + goto justADollarSign; + } + parsePtr->numTokens++; + if ((src != end) && (*src == '(')) { + /* + * 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 (ParseTokens(src+1, TYPE_CLOSE_PAREN, parsePtr) + != TCL_OK) { + goto error; + } + if ((parsePtr->term == end) || (*parsePtr->term != ')')) { + if (parsePtr->interp != NULL) { + Tcl_SetResult(parsePtr->interp, "missing )", + TCL_STATIC); + } + 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: + if (parsePtr->tokenPtr != parsePtr->staticTokens) { + ckfree((char *) parsePtr->tokenPtr); + parsePtr->tokenPtr = parsePtr->staticTokens; + } + return TCL_ERROR; } /* *---------------------------------------------------------------------- * @@ -736,11 +1753,11 @@ * 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->result. + * an error message will be left in interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -754,155 +1771,378 @@ char **termPtr; /* If non-NULL, points to word to fill * in with character just after last * one in the variable specifier. */ { - char *name1, *name1End, c, *result; - register char *name2; -#define NUM_CHARS 200 - char copyStorage[NUM_CHARS]; - ParseValue pv; - - /* - * There are three cases: - * 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, or a "::" namespace separator. - * If the following character is an open parenthesis, then the - * information between parentheses is the array element name, which - * can include any of the substitutions permissible between quotes. - * 3. The $ sign is followed by something that isn't a letter, digit, - * underscore, or a "::" namespace separator: in this case, - * there is no variable name, and "$" is returned. - */ - - name2 = NULL; - string++; - if (*string == '{') { - string++; - name1 = string; - while (*string != '}') { - if (*string == 0) { - Tcl_SetResult(interp, "missing close-brace for variable name", - TCL_STATIC); - if (termPtr != 0) { - *termPtr = string; - } - return NULL; - } - string++; - } - name1End = string; - string++; - } else { - name1 = string; - while (isalnum(UCHAR(*string)) || (*string == '_') - || (*string == ':')) { - if (*string == ':') { - if (*(string+1) == ':') { - string += 2; /* skip over the initial :: */ - while (*string == ':') { - string++; /* skip over a subsequent : */ - } - } else { - break; /* : by itself */ - } - } else { - string++; - } - } - if (string == name1) { - if (termPtr != 0) { - *termPtr = string; - } - return "$"; - } - name1End = string; - if (*string == '(') { - char *end; - - /* - * Perform substitutions on the array element name, just as - * is done for quotes. - */ - - pv.buffer = pv.next = copyStorage; - pv.end = copyStorage + NUM_CHARS - 1; - pv.expandProc = TclExpandParseValue; - pv.clientData = (ClientData) NULL; - if (TclParseQuotes(interp, string+1, ')', 0, &end, &pv) - != TCL_OK) { - char msg[200]; - int length; - - length = string-name1; - if (length > 100) { - length = 100; - } - sprintf(msg, "\n (parsing index for array \"%.*s\")", - length, name1); - Tcl_AddErrorInfo(interp, msg); - result = NULL; - name2 = pv.buffer; - if (termPtr != 0) { - *termPtr = end; - } - goto done; - } - Tcl_ResetResult(interp); - string = end; - name2 = pv.buffer; - } - } - if (termPtr != 0) { - *termPtr = string; - } - - c = *name1End; - *name1End = 0; - result = Tcl_GetVar2(interp, name1, name2, TCL_LEAVE_ERR_MSG); - *name1End = c; - - done: - if ((name2 != NULL) && (pv.buffer != copyStorage)) { - ckfree(pv.buffer); - } - return result; + Tcl_Parse parse; + register Tcl_Obj *objPtr; + + if (Tcl_ParseVarName(interp, string, -1, &parse, 0) != TCL_OK) { + return NULL; + } + + if (termPtr != NULL) { + *termPtr = string + parse.tokenPtr->size; + } + if (parse.numTokens == 1) { + /* + * There isn't a variable name after all: the $ is just a $. + */ + + return "$"; + } + + objPtr = Tcl_EvalTokens(interp, parse.tokenPtr, parse.numTokens); + if (objPtr == NULL) { + return NULL; + } + + /* + * At this point we should have an object containing the value of + * a variable. Just return the string from that object. + */ + +#ifdef TCL_COMPILE_DEBUG + if (objPtr->refCount < 2) { + panic("Tcl_ParseVar got temporary object from Tcl_EvalTokens"); + } +#endif /*TCL_COMPILE_DEBUG*/ + TclDecrRefCount(objPtr); + 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 procedure parses the string and + * returns information about the parse. + * + * 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 procedure returns TCL_OK then the caller must + * eventually invoke Tcl_FreeParse to release any additional space + * that was allocated. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_ParseBraces(interp, string, numBytes, parsePtr, append, termPtr) + Tcl_Interp *interp; /* Interpreter to use for error reporting; + * if NULL, then no error message is + * provided. */ + char *string; /* String containing the string in braces. + * The first character must be '{'. */ + 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. */ + 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. */ + +{ + char utfBytes[TCL_UTF_MAX]; /* For result of backslash substitution. */ + Tcl_Token *tokenPtr; + register char *src, *end; + int startIndex, level, length; + + if ((numBytes >= 0) || (string == NULL)) { + end = string + numBytes; + } else { + end = string + strlen(string); + } + + if (!append) { + parsePtr->numWords = 0; + parsePtr->tokenPtr = parsePtr->staticTokens; + parsePtr->numTokens = 0; + parsePtr->tokensAvailable = NUM_STATIC_TOKENS; + parsePtr->string = string; + parsePtr->end = end; + parsePtr->interp = interp; + } + + src = string+1; + startIndex = parsePtr->numTokens; + + if (parsePtr->numTokens == parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + tokenPtr = &parsePtr->tokenPtr[startIndex]; + tokenPtr->type = TCL_TOKEN_TEXT; + tokenPtr->start = src; + tokenPtr->numComponents = 0; + level = 1; + while (1) { + while (CHAR_TYPE(*src) == TYPE_NORMAL) { + src++; + } + if (*src == '}') { + level--; + if (level == 0) { + break; + } + src++; + } else if (*src == '{') { + level++; + src++; + } else if (*src == '\\') { + Tcl_UtfBackslash(src, &length, utfBytes); + if (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 ((src + 2) == end) { + parsePtr->incomplete = 1; + } + tokenPtr->size = (src - tokenPtr->start); + if (tokenPtr->size != 0) { + parsePtr->numTokens++; + } + if ((parsePtr->numTokens+1) >= parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens]; + tokenPtr->type = TCL_TOKEN_BS; + tokenPtr->start = src; + tokenPtr->size = length; + tokenPtr->numComponents = 0; + parsePtr->numTokens++; + + src += length; + tokenPtr++; + tokenPtr->type = TCL_TOKEN_TEXT; + tokenPtr->start = src; + tokenPtr->numComponents = 0; + } else { + src += length; + } + } else if (src == end) { + if (interp != NULL) { + Tcl_SetResult(interp, "missing close-brace", TCL_STATIC); + } + parsePtr->term = string; + parsePtr->incomplete = 1; + goto error; + } else { + src++; + } + } + + /* + * 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; + + error: + if (parsePtr->tokenPtr != parsePtr->staticTokens) { + ckfree((char *) parsePtr->tokenPtr); + parsePtr->tokenPtr = parsePtr->staticTokens; + } + 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 procedure parses the + * string and returns information about the parse. + * + * 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 procedure returns TCL_OK then the caller must + * eventually invoke Tcl_FreeParse to release any additional space + * that was allocated. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_ParseQuotedString(interp, string, numBytes, parsePtr, append, termPtr) + Tcl_Interp *interp; /* Interpreter to use for error reporting; + * if NULL, then no error message is + * provided. */ + char *string; /* String containing the quoted string. + * The first character must be '"'. */ + 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. */ + 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. */ +{ + char *end; + + if ((numBytes >= 0) || (string == NULL)) { + end = string + numBytes; + } else { + end = string + strlen(string); + } + + if (!append) { + parsePtr->numWords = 0; + parsePtr->tokenPtr = parsePtr->staticTokens; + parsePtr->numTokens = 0; + parsePtr->tokensAvailable = NUM_STATIC_TOKENS; + parsePtr->string = string; + parsePtr->end = end; + parsePtr->interp = interp; + } + + if (ParseTokens(string+1, TYPE_QUOTE, parsePtr) != TCL_OK) { + goto error; + } + if (*parsePtr->term != '"') { + if (interp != NULL) { + Tcl_SetResult(parsePtr->interp, "missing \"", TCL_STATIC); + } + parsePtr->term = string; + parsePtr->incomplete = 1; + goto error; + } + if (termPtr != NULL) { + *termPtr = (parsePtr->term + 1); + } + return TCL_OK; + + error: + if (parsePtr->tokenPtr != parsePtr->staticTokens) { + ckfree((char *) parsePtr->tokenPtr); + parsePtr->tokenPtr = parsePtr->staticTokens; + } + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * CommandComplete -- + * + * This procedure is shared by TclCommandComplete and + * Tcl_ObjCommandcoComplete; 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 int +CommandComplete(script, length) + char *script; /* Script to check. */ + int length; /* Number of bytes in script. */ +{ + Tcl_Parse parse; + char *p, *end; + + p = script; + end = p + length; + while (Tcl_ParseCommand((Tcl_Interp *) NULL, p, end - p, 0, &parse) + == TCL_OK) { + p = parse.commandStart + parse.commandSize; + if (*p == 0) { + break; + } + } + if (parse.incomplete) { + return 0; + } + return 1; } /* *---------------------------------------------------------------------- * * Tcl_CommandComplete -- * - * Given a partial or complete Tcl command, this procedure - * determines whether the command is complete in the sense + * Given a partial or complete Tcl script, this procedure + * determines whether the script is complete in the sense * of having matched braces and quotes and brackets. * * Results: - * 1 is returned if the command is complete, 0 otherwise. + * 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(cmd) - char *cmd; /* Command to check. */ -{ - char *p; - - if (*cmd == 0) { - return 1; - } - p = ScriptEnd(cmd, cmd+strlen(cmd), 0); - return (*p != 0); +Tcl_CommandComplete(script) + char *script; /* Script to check. */ +{ + return CommandComplete(script, (int) strlen(script)); } /* *---------------------------------------------------------------------- * @@ -920,19 +2160,65 @@ * *---------------------------------------------------------------------- */ int -TclObjCommandComplete(cmdPtr) - Tcl_Obj *cmdPtr; /* Points to object holding command +TclObjCommandComplete(objPtr) + Tcl_Obj *objPtr; /* Points to object holding script * to check. */ { - char *cmd, *p; + char *script; int length; - cmd = Tcl_GetStringFromObj(cmdPtr, &length); - if (length == 0) { - return 1; + script = Tcl_GetStringFromObj(objPtr, &length); + return CommandComplete(script, length); +} + +/* + *---------------------------------------------------------------------- + * + * TclIsLocalScalar -- + * + * Check to see if a given string is a legal scalar variable + * name with no namespace qualifiers or substitutions. + * + * Results: + * Returns 1 if the variable is a local scalar. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TclIsLocalScalar(src, len) + CONST char *src; + int len; +{ + CONST char *p; + CONST char *lastChar = src + (len - 1); + + for (p = src; p <= lastChar; p++) { + if ((CHAR_TYPE(*p) != TYPE_NORMAL) && + (CHAR_TYPE(*p) != TYPE_COMMAND_END)) { + /* + * TCL_COMMAND_END is returned for the last character + * of the string. By this point we know it isn't + * an array or namespace reference. + */ + + return 0; + } + if (*p == '(') { + if (*lastChar == ')') { /* we have an array element */ + return 0; + } + } else if (*p == ':') { + if ((p != lastChar) && *(p+1) == ':') { /* qualified name */ + return 0; + } + } } - p = ScriptEnd(cmd, cmd+length, /*nested*/ 0); - return (*p != 0); + + return 1; } ADDED generic/tclParseExpr.c Index: generic/tclParseExpr.c ================================================================== --- /dev/null +++ generic/tclParseExpr.c @@ -0,0 +1,1826 @@ +/* + * tclParseExpr.c -- + * + * This file contains procedures that parse Tcl expressions. 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. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclParseExpr.c,v 1.1.2.3 1998/11/11 04:54:18 stanton Exp $ + */ + +#include "tclInt.h" +#include "tclCompile.h" + +/* + * The stuff below is a bit of a hack so that this file can be used in + * environments that include no UNIX, i.e. no errno: just arrange to use + * the errno from tclExecute.c here. + */ + +#ifndef TCL_GENERIC_ONLY +#include "tclPort.h" +#else +#define NO_ERRNO_H +#endif + +#ifdef NO_ERRNO_H +extern int errno; /* Use errno from tclExecute.c. */ +#define ERANGE 34 +#endif + +/* + * Boolean variable that controls whether expression parse tracing + * is enabled. + */ + +#ifdef TCL_COMPILE_DEBUG +static int traceParseExpr = 0; +#endif /* TCL_COMPILE_DEBUG */ + +/* + * The ParseInfo structure holds state while parsing an expression. + * A pointer to an ParseInfo record is passed among the routines in + * this module. + */ + +typedef struct ParseInfo { + Tcl_Parse *parsePtr; /* Points to structure to fill in with + * information about the expression. */ + int lexeme; /* Type of last lexeme scanned in expr. + * See below for definitions. Corresponds to + * size characters beginning at start. */ + char *start; /* First character in lexeme. */ + int size; /* Number of bytes in lexeme. */ + char *next; /* Position of the next character to be + * scanned in the expression string. */ + char *prevEnd; /* Points to the character just after the + * last one in the previous lexeme. Used to + * compute size of subexpression tokens. */ + char *originalExpr; /* Points to the start of the expression + * originally passed to Tcl_ParseExpr. */ + char *lastChar; /* Points just after last byte of expr. */ +} ParseInfo; + +/* + * Definitions of the different lexemes that appear in expressions. The + * order of these must match the corresponding entries in the + * operatorStrings array below. + */ + +#define LITERAL 0 +#define FUNC_NAME 1 +#define OPEN_BRACKET 2 +#define OPEN_BRACE 3 +#define OPEN_PAREN 4 +#define CLOSE_PAREN 5 +#define DOLLAR 6 +#define QUOTE 7 +#define COMMA 8 +#define END 9 +#define UNKNOWN 10 + +/* + * Binary operators: + */ + +#define MULT 11 +#define DIVIDE 12 +#define MOD 13 +#define PLUS 14 +#define MINUS 15 +#define LEFT_SHIFT 16 +#define RIGHT_SHIFT 17 +#define LESS 18 +#define GREATER 19 +#define LEQ 20 +#define GEQ 21 +#define EQUAL 22 +#define NEQ 23 +#define BIT_AND 24 +#define BIT_XOR 25 +#define BIT_OR 26 +#define AND 27 +#define OR 28 +#define QUESTY 29 +#define COLON 30 + +/* + * Unary operators. Unary minus and plus are represented by the (binary) + * lexemes MINUS and PLUS. + */ + +#define NOT 31 +#define BIT_NOT 32 + +/* + * Mapping from lexemes to strings; used for debugging messages. These + * entries must match the order and number of the lexeme definitions above. + */ + +#ifdef TCL_COMPILE_DEBUG +static char *lexemeStrings[] = { + "LITERAL", "FUNCNAME", + "[", "{", "(", ")", "$", "\"", ",", "END", "UNKNOWN", + "*", "/", "%", "+", "-", + "<<", ">>", "<", ">", "<=", ">=", "==", "!=", + "&", "^", "|", "&&", "||", "?", ":", + "!", "~" +}; +#endif /* TCL_COMPILE_DEBUG */ + +/* + * Declarations for local procedures to this file: + */ + +static int GetLexeme _ANSI_ARGS_((ParseInfo *infoPtr)); +static void LogSyntaxError _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseAddExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseBitAndExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseBitOrExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseBitXorExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseCondExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseEqualityExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseLandExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseLorExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseMultiplyExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParsePrimaryExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseRelationalExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseShiftExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static int ParseUnaryExpr _ANSI_ARGS_((ParseInfo *infoPtr)); +static void PrependSubExprTokens _ANSI_ARGS_((char *op, + int opBytes, char *src, int srcBytes, + int firstIndex, ParseInfo *infoPtr)); + +/* + * Macro used to debug the execution of the recursive descent parser used + * to parse expressions. + */ + +#ifdef TCL_COMPILE_DEBUG +#define HERE(production, level) \ + if (traceParseExpr) { \ + fprintf(stderr, "%*s%s: lexeme=%s, next=\"%.20s\"\n", \ + (level), " ", (production), \ + lexemeStrings[infoPtr->lexeme], infoPtr->next); \ + } +#else +#define HERE(production, level) +#endif /* TCL_COMPILE_DEBUG */ + +/* + *---------------------------------------------------------------------- + * + * Tcl_ParseExpr -- + * + * Given a string, this procedure parses the first Tcl expression + * in the string and returns information about the structure of + * the expression. This procedure is the top-level interface to the + * the expression parsing module. + * + * 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 expression that + * was parsed. + * + * 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 procedure returns TCL_OK then the caller must + * eventually invoke Tcl_FreeParse to release any additional space + * that was allocated. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_ParseExpr(interp, string, numBytes, parsePtr) + Tcl_Interp *interp; /* Used for error reporting. */ + char *string; /* The 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. */ +{ + ParseInfo info; + int code; + char savedChar; + + if (numBytes < 0) { + numBytes = (string? strlen(string) : 0); + } +#ifdef TCL_COMPILE_DEBUG + if (traceParseExpr) { + fprintf(stderr, "Tcl_ParseExpr: string=\"%.*s\"\n", + numBytes, string); + } +#endif /* TCL_COMPILE_DEBUG */ + + parsePtr->commentStart = NULL; + parsePtr->commentSize = 0; + parsePtr->commandStart = NULL; + parsePtr->commandSize = 0; + parsePtr->numWords = 0; + parsePtr->tokenPtr = parsePtr->staticTokens; + parsePtr->numTokens = 0; + parsePtr->tokensAvailable = NUM_STATIC_TOKENS; + parsePtr->string = string; + parsePtr->end = (string + numBytes); + parsePtr->interp = interp; + parsePtr->term = string; + parsePtr->incomplete = 0; + + /* + * Temporarily overwrite the character just after the end of the + * string with a 0 byte. This acts as a sentinel and reduces the + * number of places where we have to check for the end of the + * input string. The original value of the byte is restored at + * the end of the parse. + */ + + savedChar = string[numBytes]; + string[numBytes] = 0; + + /* + * Initialize the ParseInfo structure that holds state while parsing + * the expression. + */ + + info.parsePtr = parsePtr; + info.lexeme = UNKNOWN; + info.start = NULL; + info.size = 0; + info.next = string; + info.prevEnd = string; + info.originalExpr = string; + info.lastChar = (string + numBytes); /* just after last char of expr */ + + /* + * Get the first lexeme then parse the expression. + */ + + code = GetLexeme(&info); + if (code != TCL_OK) { + goto error; + } + code = ParseCondExpr(&info); + if (code != TCL_OK) { + goto error; + } + if (info.lexeme != END) { + LogSyntaxError(&info); + goto error; + } + string[numBytes] = (char) savedChar; + return TCL_OK; + + error: + string[numBytes] = (char) savedChar; + if (parsePtr->tokenPtr != parsePtr->staticTokens) { + ckfree((char *) parsePtr->tokenPtr); + } + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * ParseCondExpr -- + * + * This procedure parses a Tcl conditional expression: + * condExpr ::= lorExpr ['?' condExpr ':' condExpr] + * + * Note that this is the topmost recursive-descent parsing routine used + * by TclParseExpr to parse expressions. This avoids an extra procedure + * call since such a procedure would only return the result of calling + * ParseCondExpr. Other recursive-descent procedures that need to parse + * complete expressions also call ParseCondExpr. + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseCondExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + Tcl_Token *tokenPtr, *firstTokenPtr, *condTokenPtr; + int firstIndex, numToMove, code; + char *srcStart; + + HERE("condExpr", 1); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + code = ParseLorExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + if (infoPtr->lexeme == QUESTY) { + /* + * Emit two tokens: one TCL_TOKEN_SUB_EXPR token for the entire + * conditional expression, and a TCL_TOKEN_OPERATOR token for + * the "?" operator. Note that these two tokens must be inserted + * before the LOR operand tokens generated above. + */ + + if ((parsePtr->numTokens + 1) >= parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + firstTokenPtr = &parsePtr->tokenPtr[firstIndex]; + tokenPtr = (firstTokenPtr + 2); + numToMove = (parsePtr->numTokens - firstIndex); + memmove((VOID *) tokenPtr, (VOID *) firstTokenPtr, + (size_t) (numToMove * sizeof(Tcl_Token))); + parsePtr->numTokens += 2; + + tokenPtr = firstTokenPtr; + tokenPtr->type = TCL_TOKEN_SUB_EXPR; + tokenPtr->start = srcStart; + + tokenPtr++; + tokenPtr->type = TCL_TOKEN_OPERATOR; + tokenPtr->start = infoPtr->start; + tokenPtr->size = 1; + tokenPtr->numComponents = 0; + + /* + * Skip over the '?'. + */ + + code = GetLexeme(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Parse the "then" expression. + */ + + code = ParseCondExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + if (infoPtr->lexeme != COLON) { + LogSyntaxError(infoPtr); + return TCL_ERROR; + } + code = GetLexeme(infoPtr); /* skip over the ':' */ + if (code != TCL_OK) { + return code; + } + + /* + * Parse the "else" expression. + */ + + code = ParseCondExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Now set the size-related fields in the '?' subexpression token. + */ + + condTokenPtr = &parsePtr->tokenPtr[firstIndex]; + condTokenPtr->size = (infoPtr->prevEnd - srcStart); + condTokenPtr->numComponents = parsePtr->numTokens - (firstIndex+1); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseLorExpr -- + * + * This procedure parses a Tcl logical or expression: + * lorExpr ::= landExpr {'||' landExpr} + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseLorExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + int firstIndex, code; + char *srcStart, *operator; + + HERE("lorExpr", 2); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + code = ParseLandExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + while (infoPtr->lexeme == OR) { + operator = infoPtr->start; + code = GetLexeme(infoPtr); /* skip over the '||' */ + if (code != TCL_OK) { + return code; + } + code = ParseLandExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Generate tokens for the LOR subexpression and the '||' operator. + */ + + PrependSubExprTokens(operator, 2, srcStart, + (infoPtr->prevEnd - srcStart), firstIndex, infoPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseLandExpr -- + * + * This procedure parses a Tcl logical and expression: + * landExpr ::= bitOrExpr {'&&' bitOrExpr} + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseLandExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + int firstIndex, code; + char *srcStart, *operator; + + HERE("landExpr", 3); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + code = ParseBitOrExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + while (infoPtr->lexeme == AND) { + operator = infoPtr->start; + code = GetLexeme(infoPtr); /* skip over the '&&' */ + if (code != TCL_OK) { + return code; + } + code = ParseBitOrExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Generate tokens for the LAND subexpression and the '&&' operator. + */ + + PrependSubExprTokens(operator, 2, srcStart, + (infoPtr->prevEnd - srcStart), firstIndex, infoPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseBitOrExpr -- + * + * This procedure parses a Tcl bitwise or expression: + * bitOrExpr ::= bitXorExpr {'|' bitXorExpr} + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseBitOrExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + int firstIndex, code; + char *srcStart, *operator; + + HERE("bitOrExpr", 4); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + code = ParseBitXorExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + while (infoPtr->lexeme == BIT_OR) { + operator = infoPtr->start; + code = GetLexeme(infoPtr); /* skip over the '|' */ + if (code != TCL_OK) { + return code; + } + + code = ParseBitXorExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Generate tokens for the BITOR subexpression and the '|' operator. + */ + + PrependSubExprTokens(operator, 1, srcStart, + (infoPtr->prevEnd - srcStart), firstIndex, infoPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseBitXorExpr -- + * + * This procedure parses a Tcl bitwise exclusive or expression: + * bitXorExpr ::= bitAndExpr {'^' bitAndExpr} + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseBitXorExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + int firstIndex, code; + char *srcStart, *operator; + + HERE("bitXorExpr", 5); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + code = ParseBitAndExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + while (infoPtr->lexeme == BIT_XOR) { + operator = infoPtr->start; + code = GetLexeme(infoPtr); /* skip over the '^' */ + if (code != TCL_OK) { + return code; + } + + code = ParseBitAndExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Generate tokens for the XOR subexpression and the '^' operator. + */ + + PrependSubExprTokens(operator, 1, srcStart, + (infoPtr->prevEnd - srcStart), firstIndex, infoPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseBitAndExpr -- + * + * This procedure parses a Tcl bitwise and expression: + * bitAndExpr ::= equalityExpr {'&' equalityExpr} + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseBitAndExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + int firstIndex, code; + char *srcStart, *operator; + + HERE("bitAndExpr", 6); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + code = ParseEqualityExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + while (infoPtr->lexeme == BIT_AND) { + operator = infoPtr->start; + code = GetLexeme(infoPtr); /* skip over the '&' */ + if (code != TCL_OK) { + return code; + } + code = ParseEqualityExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Generate tokens for the BITAND subexpression and '&' operator. + */ + + PrependSubExprTokens(operator, 1, srcStart, + (infoPtr->prevEnd - srcStart), firstIndex, infoPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseEqualityExpr -- + * + * This procedure parses a Tcl equality (inequality) expression: + * equalityExpr ::= relationalExpr {('==' | '!=') relationalExpr} + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseEqualityExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + int firstIndex, lexeme, code; + char *srcStart, *operator; + + HERE("equalityExpr", 7); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + code = ParseRelationalExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + lexeme = infoPtr->lexeme; + while ((lexeme == EQUAL) || (lexeme == NEQ)) { + operator = infoPtr->start; + code = GetLexeme(infoPtr); /* skip over == or != */ + if (code != TCL_OK) { + return code; + } + code = ParseRelationalExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Generate tokens for the subexpression and '==' or '!=' operator. + */ + + PrependSubExprTokens(operator, 2, srcStart, + (infoPtr->prevEnd - srcStart), firstIndex, infoPtr); + lexeme = infoPtr->lexeme; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseRelationalExpr -- + * + * This procedure parses a Tcl relational expression: + * relationalExpr ::= shiftExpr {('<' | '>' | '<=' | '>=') shiftExpr} + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseRelationalExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + int firstIndex, lexeme, operatorSize, code; + char *srcStart, *operator; + + HERE("relationalExpr", 8); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + code = ParseShiftExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + lexeme = infoPtr->lexeme; + while ((lexeme == LESS) || (lexeme == GREATER) || (lexeme == LEQ) + || (lexeme == GEQ)) { + operator = infoPtr->start; + if ((lexeme == LEQ) || (lexeme == GEQ)) { + operatorSize = 2; + } else { + operatorSize = 1; + } + code = GetLexeme(infoPtr); /* skip over the operator */ + if (code != TCL_OK) { + return code; + } + code = ParseShiftExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Generate tokens for the subexpression and the operator. + */ + + PrependSubExprTokens(operator, operatorSize, srcStart, + (infoPtr->prevEnd - srcStart), firstIndex, infoPtr); + lexeme = infoPtr->lexeme; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseShiftExpr -- + * + * This procedure parses a Tcl shift expression: + * shiftExpr ::= addExpr {('<<' | '>>') addExpr} + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseShiftExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + int firstIndex, lexeme, code; + char *srcStart, *operator; + + HERE("shiftExpr", 9); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + code = ParseAddExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + lexeme = infoPtr->lexeme; + while ((lexeme == LEFT_SHIFT) || (lexeme == RIGHT_SHIFT)) { + operator = infoPtr->start; + code = GetLexeme(infoPtr); /* skip over << or >> */ + if (code != TCL_OK) { + return code; + } + code = ParseAddExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Generate tokens for the subexpression and '<<' or '>>' operator. + */ + + PrependSubExprTokens(operator, 2, srcStart, + (infoPtr->prevEnd - srcStart), firstIndex, infoPtr); + lexeme = infoPtr->lexeme; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseAddExpr -- + * + * This procedure parses a Tcl addition expression: + * addExpr ::= multiplyExpr {('+' | '-') multiplyExpr} + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseAddExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + int firstIndex, lexeme, code; + char *srcStart, *operator; + + HERE("addExpr", 10); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + code = ParseMultiplyExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + lexeme = infoPtr->lexeme; + while ((lexeme == PLUS) || (lexeme == MINUS)) { + operator = infoPtr->start; + code = GetLexeme(infoPtr); /* skip over + or - */ + if (code != TCL_OK) { + return code; + } + code = ParseMultiplyExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Generate tokens for the subexpression and '+' or '-' operator. + */ + + PrependSubExprTokens(operator, 1, srcStart, + (infoPtr->prevEnd - srcStart), firstIndex, infoPtr); + lexeme = infoPtr->lexeme; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseMultiplyExpr -- + * + * This procedure parses a Tcl multiply expression: + * multiplyExpr ::= unaryExpr {('*' | '/' | '%') unaryExpr} + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseMultiplyExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + int firstIndex, lexeme, code; + char *srcStart, *operator; + + HERE("multiplyExpr", 11); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + code = ParseUnaryExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + lexeme = infoPtr->lexeme; + while ((lexeme == MULT) || (lexeme == DIVIDE) || (lexeme == MOD)) { + operator = infoPtr->start; + code = GetLexeme(infoPtr); /* skip over * or / or % */ + if (code != TCL_OK) { + return code; + } + code = ParseUnaryExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Generate tokens for the subexpression and * or / or % operator. + */ + + PrependSubExprTokens(operator, 1, srcStart, + (infoPtr->prevEnd - srcStart), firstIndex, infoPtr); + lexeme = infoPtr->lexeme; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParseUnaryExpr -- + * + * This procedure parses a Tcl unary expression: + * unaryExpr ::= ('+' | '-' | '~' | '!') unaryExpr | primaryExpr + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParseUnaryExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + int firstIndex, lexeme, code; + char *srcStart, *operator; + + HERE("unaryExpr", 12); + srcStart = infoPtr->start; + firstIndex = parsePtr->numTokens; + + lexeme = infoPtr->lexeme; + if ((lexeme == PLUS) || (lexeme == MINUS) || (lexeme == BIT_NOT) + || (lexeme == NOT)) { + operator = infoPtr->start; + code = GetLexeme(infoPtr); /* skip over the unary operator */ + if (code != TCL_OK) { + return code; + } + code = ParseUnaryExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + /* + * Generate tokens for the subexpression and the operator. + */ + + PrependSubExprTokens(operator, 1, srcStart, + (infoPtr->prevEnd - srcStart), firstIndex, infoPtr); + } else { /* must be a primaryExpr */ + code = ParsePrimaryExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ParsePrimaryExpr -- + * + * This procedure parses a Tcl primary expression: + * primaryExpr ::= literal | varReference | quotedString | + * '[' command ']' | mathFuncCall | '(' condExpr ')' + * + * Results: + * The return value is TCL_OK on a successful parse and TCL_ERROR + * on failure. If TCL_ERROR is returned, then the interpreter's result + * contains an error message. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static int +ParsePrimaryExpr(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + Tcl_Interp *interp = parsePtr->interp; + Tcl_Token *tokenPtr, *exprTokenPtr; + Tcl_Parse nested; + char *dollarPtr, *stringStart, *termPtr, *src; + int lexeme, exprIndex, firstIndex, numToMove, code; + + /* + * We simply recurse on parenthesized subexpressions. + */ + + HERE("primaryExpr", 13); + lexeme = infoPtr->lexeme; + if (lexeme == OPEN_PAREN) { + code = GetLexeme(infoPtr); /* skip over the '(' */ + if (code != TCL_OK) { + return code; + } + code = ParseCondExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + if (infoPtr->lexeme != CLOSE_PAREN) { + goto syntaxError; + } + code = GetLexeme(infoPtr); /* skip over the ')' */ + if (code != TCL_OK) { + return code; + } + return TCL_OK; + } + + /* + * Start a TCL_TOKEN_SUB_EXPR token for the primary. + */ + + if (parsePtr->numTokens == parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + exprIndex = parsePtr->numTokens; + exprTokenPtr = &parsePtr->tokenPtr[exprIndex]; + exprTokenPtr->type = TCL_TOKEN_SUB_EXPR; + exprTokenPtr->start = infoPtr->start; + parsePtr->numTokens++; + + /* + * Process the primary then finish setting the fields of the + * TCL_TOKEN_SUB_EXPR token. Note that we can't use the pointer now + * stored in "exprTokenPtr" in the code below since the token array + * might be reallocated. + */ + + firstIndex = parsePtr->numTokens; + switch (lexeme) { + case LITERAL: + /* + * Int or double number. + */ + + if (parsePtr->numTokens == parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens]; + tokenPtr->type = TCL_TOKEN_TEXT; + tokenPtr->start = infoPtr->start; + tokenPtr->size = infoPtr->size; + tokenPtr->numComponents = 0; + parsePtr->numTokens++; + + exprTokenPtr = &parsePtr->tokenPtr[exprIndex]; + exprTokenPtr->size = infoPtr->size; + exprTokenPtr->numComponents = 1; + break; + + case DOLLAR: + /* + * $var variable reference. + */ + + dollarPtr = (infoPtr->next - 1); + code = Tcl_ParseVarName(interp, dollarPtr, + (infoPtr->lastChar - dollarPtr), parsePtr, 1); + if (code != TCL_OK) { + return code; + } + infoPtr->next = dollarPtr + parsePtr->tokenPtr[firstIndex].size; + + exprTokenPtr = &parsePtr->tokenPtr[exprIndex]; + exprTokenPtr->size = parsePtr->tokenPtr[firstIndex].size; + exprTokenPtr->numComponents = + (parsePtr->tokenPtr[firstIndex].numComponents + 1); + break; + + case QUOTE: + /* + * '"' string '"' + */ + + stringStart = infoPtr->next; + code = Tcl_ParseQuotedString(interp, infoPtr->start, + (infoPtr->lastChar - stringStart), parsePtr, 1, &termPtr); + if (code != TCL_OK) { + return code; + } + infoPtr->next = termPtr; + + exprTokenPtr = &parsePtr->tokenPtr[exprIndex]; + exprTokenPtr->size = (termPtr - exprTokenPtr->start); + exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex; + + /* + * If parsing the quoted string resulted in more than one token, + * insert a TCL_TOKEN_WORD token before them. This indicates that + * the quoted string represents a concatenation of multiple tokens. + */ + + if (exprTokenPtr->numComponents > 1) { + if (parsePtr->numTokens >= parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + tokenPtr = &parsePtr->tokenPtr[firstIndex]; + numToMove = (parsePtr->numTokens - firstIndex); + memmove((VOID *) (tokenPtr + 1), (VOID *) tokenPtr, + (size_t) (numToMove * sizeof(Tcl_Token))); + parsePtr->numTokens++; + + exprTokenPtr = &parsePtr->tokenPtr[exprIndex]; + exprTokenPtr->numComponents++; + + tokenPtr->type = TCL_TOKEN_WORD; + tokenPtr->start = exprTokenPtr->start; + tokenPtr->size = exprTokenPtr->size; + tokenPtr->numComponents = (exprTokenPtr->numComponents - 1); + } + break; + + case OPEN_BRACKET: + /* + * '[' command {command} ']' + */ + + if (parsePtr->numTokens == parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens]; + tokenPtr->type = TCL_TOKEN_COMMAND; + tokenPtr->start = infoPtr->start; + tokenPtr->numComponents = 0; + parsePtr->numTokens++; + + /* + * Call Tcl_ParseCommand repeatedly to parse the nested command(s) + * to find their end, then throw away that parse information. + */ + + src = infoPtr->next; + while (1) { + if (Tcl_ParseCommand(interp, src, (parsePtr->end - src), 1, + &nested) != TCL_OK) { + parsePtr->term = nested.term; + parsePtr->incomplete = nested.incomplete; + return TCL_ERROR; + } + src = (nested.commandStart + nested.commandSize); + if (nested.tokenPtr != nested.staticTokens) { + ckfree((char *) nested.tokenPtr); + } + if ((src[-1] == ']') && !nested.incomplete) { + break; + } + if (src == parsePtr->end) { + if (parsePtr->interp != NULL) { + Tcl_SetResult(interp, "missing close-bracket", + TCL_STATIC); + } + parsePtr->term = tokenPtr->start; + parsePtr->incomplete = 1; + return TCL_ERROR; + } + } + tokenPtr->size = (src - tokenPtr->start); + infoPtr->next = src; + + exprTokenPtr = &parsePtr->tokenPtr[exprIndex]; + exprTokenPtr->size = (src - tokenPtr->start); + exprTokenPtr->numComponents = 1; + break; + + case OPEN_BRACE: + /* + * '{' string '}' + */ + + code = Tcl_ParseBraces(interp, infoPtr->start, + (infoPtr->lastChar - infoPtr->start), parsePtr, 1, + &termPtr); + if (code != TCL_OK) { + return code; + } + infoPtr->next = termPtr; + + exprTokenPtr = &parsePtr->tokenPtr[exprIndex]; + exprTokenPtr->size = (termPtr - infoPtr->start); + exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex; + + /* + * If parsing the braced string resulted in more than one token, + * insert a TCL_TOKEN_WORD token before them. This indicates that + * the braced string represents a concatenation of multiple tokens. + */ + + if (exprTokenPtr->numComponents > 1) { + if (parsePtr->numTokens >= parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + tokenPtr = &parsePtr->tokenPtr[firstIndex]; + numToMove = (parsePtr->numTokens - firstIndex); + memmove((VOID *) (tokenPtr + 1), (VOID *) tokenPtr, + (size_t) (numToMove * sizeof(Tcl_Token))); + parsePtr->numTokens++; + + exprTokenPtr = &parsePtr->tokenPtr[exprIndex]; + exprTokenPtr->numComponents++; + + tokenPtr->type = TCL_TOKEN_WORD; + tokenPtr->start = exprTokenPtr->start; + tokenPtr->size = exprTokenPtr->size; + tokenPtr->numComponents = exprTokenPtr->numComponents-1; + } + break; + + case FUNC_NAME: + /* + * math_func '(' expr {',' expr} ')' + */ + + if (parsePtr->numTokens == parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens]; + tokenPtr->type = TCL_TOKEN_OPERATOR; + tokenPtr->start = infoPtr->start; + tokenPtr->size = infoPtr->size; + tokenPtr->numComponents = 0; + parsePtr->numTokens++; + + code = GetLexeme(infoPtr); /* skip over function name */ + if (code != TCL_OK) { + return code; + } + if (infoPtr->lexeme != OPEN_PAREN) { + goto syntaxError; + } + code = GetLexeme(infoPtr); /* skip over '(' */ + if (code != TCL_OK) { + return code; + } + + while (infoPtr->lexeme != CLOSE_PAREN) { + code = ParseCondExpr(infoPtr); + if (code != TCL_OK) { + return code; + } + + if (infoPtr->lexeme == COMMA) { + code = GetLexeme(infoPtr); /* skip over , */ + if (code != TCL_OK) { + return code; + } + } else if (infoPtr->lexeme != CLOSE_PAREN) { + goto syntaxError; + } + } + + exprTokenPtr = &parsePtr->tokenPtr[exprIndex]; + exprTokenPtr->size = (infoPtr->next - exprTokenPtr->start); + exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex; + break; + + default: + goto syntaxError; + } + + /* + * Advance to the next lexeme before returning. + */ + + code = GetLexeme(infoPtr); + if (code != TCL_OK) { + return code; + } + parsePtr->term = infoPtr->next; + return TCL_OK; + + syntaxError: + LogSyntaxError(infoPtr); + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * GetLexeme -- + * + * Lexical scanner for Tcl expressions: scans a single operator or + * other syntactic element from an expression string. + * + * Results: + * TCL_OK is returned unless an error occurred. In that case a standard + * Tcl error code is returned and, if infoPtr->parsePtr->interp is + * non-NULL, the interpreter's result is set to hold an error + * message. TCL_ERROR is returned if an integer overflow, or a + * floating-point overflow or underflow occurred while reading in a + * number. If the lexical analysis is successful, infoPtr->lexeme + * refers to the next symbol in the expression string, and + * infoPtr->next is advanced past the lexeme. Also, if the lexeme is a + * LITERAL or FUNC_NAME, then infoPtr->start is set to the first + * character of the lexeme; otherwise it is set NULL. + * + * Side effects: + * If there is insufficient space in parsePtr to hold all the + * information about the subexpression, then additional space is + * malloc-ed.. + * + *---------------------------------------------------------------------- + */ + +static int +GetLexeme(infoPtr) + ParseInfo *infoPtr; /* Holds state needed to parse the expr, + * including the resulting lexeme. */ +{ + register char *src; /* Points to current source char. */ + char *termPtr; /* Points to char terminating a literal. */ + double doubleValue; /* Value of a scanned double literal. */ + char c; + int startsWithDigit, offset; + Tcl_Parse *parsePtr = infoPtr->parsePtr; + Tcl_Interp *interp = parsePtr->interp; + Tcl_UniChar ch; + + /* + * Record where the previous lexeme ended. Since we always read one + * lexeme ahead during parsing, this helps us know the source length of + * subexpression tokens. + */ + + infoPtr->prevEnd = infoPtr->next; + + /* + * Scan over leading white space at the start of a lexeme. Note that a + * backslash-newline is treated as a space. + */ + + src = infoPtr->next; + c = *src; + while (isspace(UCHAR(c)) || (c == '\\')) { /* INTL: ISO space */ + if (c == '\\') { + if (src[1] == '\n') { + src += 2; + } else { + break; /* no longer white space */ + } + } else { + src++; + } + c = *src; + } + parsePtr->term = src; + if (src >= infoPtr->lastChar) { + infoPtr->lexeme = END; + infoPtr->next = src; + return TCL_OK; + } + + /* + * Try to parse the lexeme first as an integer or floating-point + * number. Don't check for a number if the first character c is + * "+" or "-". If we did, we might treat a binary operator as unary + * by mistake, which would eventually cause a syntax error. + */ + + if ((c != '+') && (c != '-')) { + startsWithDigit = isdigit(UCHAR(c)); /* INTL: digit */ + if (startsWithDigit && TclLooksLikeInt(src, -1)) { + errno = 0; + (void) strtoul(src, &termPtr, 0); + if (errno == ERANGE) { + if (interp != NULL) { + char *s = "integer value too large to represent"; + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1); + Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, + (char *) NULL); + } + return TCL_ERROR; + } + if (termPtr != src) { + /* + * src was the start of a valid integer. + */ + + infoPtr->lexeme = LITERAL; + infoPtr->start = src; + infoPtr->size = (termPtr - src); + infoPtr->next = termPtr; + parsePtr->term = termPtr; + return TCL_OK; + } + } else if (startsWithDigit || (c == '.') + || (c == 'n') || (c == 'N')) { + errno = 0; + doubleValue = strtod(src, &termPtr); + if (termPtr != src) { + if (errno != 0) { + if (interp != NULL) { + TclExprFloatError(interp, doubleValue); + } + return TCL_ERROR; + } + + /* + * src was the start of a valid double. + */ + + infoPtr->lexeme = LITERAL; + infoPtr->start = src; + infoPtr->size = (termPtr - src); + infoPtr->next = termPtr; + parsePtr->term = termPtr; + return TCL_OK; + } + } + } + + /* + * Not an integer or double literal. Initialize the lexeme's fields + * assuming the common case of a single character lexeme. + */ + + infoPtr->start = src; + infoPtr->size = 1; + infoPtr->next = src+1; + parsePtr->term = infoPtr->next; + + switch (*src) { + case '[': + infoPtr->lexeme = OPEN_BRACKET; + return TCL_OK; + + case '{': + infoPtr->lexeme = OPEN_BRACE; + return TCL_OK; + + case '(': + infoPtr->lexeme = OPEN_PAREN; + return TCL_OK; + + case ')': + infoPtr->lexeme = CLOSE_PAREN; + return TCL_OK; + + case '$': + infoPtr->lexeme = DOLLAR; + return TCL_OK; + + case '"': + infoPtr->lexeme = QUOTE; + return TCL_OK; + + case ',': + infoPtr->lexeme = COMMA; + return TCL_OK; + + case '*': + infoPtr->lexeme = MULT; + return TCL_OK; + + case '/': + infoPtr->lexeme = DIVIDE; + return TCL_OK; + + case '%': + infoPtr->lexeme = MOD; + return TCL_OK; + + case '+': + infoPtr->lexeme = PLUS; + return TCL_OK; + + case '-': + infoPtr->lexeme = MINUS; + return TCL_OK; + + case '?': + infoPtr->lexeme = QUESTY; + return TCL_OK; + + case ':': + infoPtr->lexeme = COLON; + return TCL_OK; + + case '<': + switch (src[1]) { + case '<': + infoPtr->lexeme = LEFT_SHIFT; + infoPtr->size = 2; + infoPtr->next = src+2; + break; + case '=': + infoPtr->lexeme = LEQ; + infoPtr->size = 2; + infoPtr->next = src+2; + break; + default: + infoPtr->lexeme = LESS; + break; + } + parsePtr->term = infoPtr->next; + return TCL_OK; + + case '>': + switch (src[1]) { + case '>': + infoPtr->lexeme = RIGHT_SHIFT; + infoPtr->size = 2; + infoPtr->next = src+2; + break; + case '=': + infoPtr->lexeme = GEQ; + infoPtr->size = 2; + infoPtr->next = src+2; + break; + default: + infoPtr->lexeme = GREATER; + break; + } + parsePtr->term = infoPtr->next; + return TCL_OK; + + case '=': + if (src[1] == '=') { + infoPtr->lexeme = EQUAL; + infoPtr->size = 2; + infoPtr->next = src+2; + } else { + infoPtr->lexeme = UNKNOWN; + } + parsePtr->term = infoPtr->next; + return TCL_OK; + + case '!': + if (src[1] == '=') { + infoPtr->lexeme = NEQ; + infoPtr->size = 2; + infoPtr->next = src+2; + } else { + infoPtr->lexeme = NOT; + } + parsePtr->term = infoPtr->next; + return TCL_OK; + + case '&': + if (src[1] == '&') { + infoPtr->lexeme = AND; + infoPtr->size = 2; + infoPtr->next = src+2; + } else { + infoPtr->lexeme = BIT_AND; + } + parsePtr->term = infoPtr->next; + return TCL_OK; + + case '^': + infoPtr->lexeme = BIT_XOR; + return TCL_OK; + + case '|': + if (src[1] == '|') { + infoPtr->lexeme = OR; + infoPtr->size = 2; + infoPtr->next = src+2; + } else { + infoPtr->lexeme = BIT_OR; + } + parsePtr->term = infoPtr->next; + return TCL_OK; + + case '~': + infoPtr->lexeme = BIT_NOT; + return TCL_OK; + + default: + offset = Tcl_UtfToUniChar(src, &ch); + c = UCHAR(ch); + if (isalpha(UCHAR(c))) { /* INTL: ISO only. */ + infoPtr->lexeme = FUNC_NAME; + while (isalnum(UCHAR(c)) || (c == '_')) { /* INTL: ISO only. */ + src += offset; + offset = Tcl_UtfToUniChar(src, &ch); + c = UCHAR(ch); + } + infoPtr->size = (src - infoPtr->start); + infoPtr->next = src; + parsePtr->term = infoPtr->next; + return TCL_OK; + } + infoPtr->lexeme = UNKNOWN; + return TCL_OK; + } +} + +/* + *---------------------------------------------------------------------- + * + * PrependSubExprTokens -- + * + * This procedure is called after the operands of an subexpression have + * been parsed. It generates two tokens: a TCL_TOKEN_SUB_EXPR token for + * the subexpression, and a TCL_TOKEN_OPERATOR token for its operator. + * These two tokens are inserted before the operand tokens. + * + * Results: + * None. + * + * Side effects: + * If there is insufficient space in parsePtr to hold the new tokens, + * additional space is malloc-ed. + * + *---------------------------------------------------------------------- + */ + +static void +PrependSubExprTokens(op, opBytes, src, srcBytes, firstIndex, infoPtr) + char *op; /* Points to first byte of the operator + * in the source script. */ + int opBytes; /* Number of bytes in the operator. */ + char *src; /* Points to first byte of the subexpression + * in the source script. */ + int srcBytes; /* Number of bytes in subexpression's + * source. */ + int firstIndex; /* Index of first token already emitted for + * operator's first (or only) operand. */ + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + Tcl_Parse *parsePtr = infoPtr->parsePtr; + Tcl_Token *tokenPtr, *firstTokenPtr; + int numToMove; + + if ((parsePtr->numTokens + 1) >= parsePtr->tokensAvailable) { + TclExpandTokenArray(parsePtr); + } + firstTokenPtr = &parsePtr->tokenPtr[firstIndex]; + tokenPtr = (firstTokenPtr + 2); + numToMove = (parsePtr->numTokens - firstIndex); + memmove((VOID *) tokenPtr, (VOID *) firstTokenPtr, + (size_t) (numToMove * sizeof(Tcl_Token))); + parsePtr->numTokens += 2; + + tokenPtr = firstTokenPtr; + tokenPtr->type = TCL_TOKEN_SUB_EXPR; + tokenPtr->start = src; + tokenPtr->size = srcBytes; + tokenPtr->numComponents = parsePtr->numTokens - (firstIndex + 1); + + tokenPtr++; + tokenPtr->type = TCL_TOKEN_OPERATOR; + tokenPtr->start = op; + tokenPtr->size = opBytes; + tokenPtr->numComponents = 0; +} + +/* + *---------------------------------------------------------------------- + * + * LogSyntaxError -- + * + * This procedure is invoked after an error occurs when parsing an + * expression. It sets the interpreter result to an error message + * describing the error. + * + * Results: + * None. + * + * Side effects: + * Sets the interpreter result to an error message describing the + * expression that was being parsed when the error occurred. + * + *---------------------------------------------------------------------- + */ + +static void +LogSyntaxError(infoPtr) + ParseInfo *infoPtr; /* Holds the parse state for the + * expression being parsed. */ +{ + int numBytes = (infoPtr->lastChar - infoPtr->originalExpr); + char buffer[100]; + + sprintf(buffer, "syntax error in expression \"%.*s\"", + ((numBytes > 60)? 60 : numBytes), infoPtr->originalExpr); + Tcl_AppendStringsToObj(Tcl_GetObjResult(infoPtr->parsePtr->interp), + buffer, (char *) NULL); +} Index: generic/tclPipe.c ================================================================== --- generic/tclPipe.c +++ generic/tclPipe.c @@ -8,11 +8,11 @@ * Copyright (c) 1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclPipe.c 1.8 97/06/20 13:26:45 + * RCS: @(#) $Id: tclPipe.c,v 1.1.2.5 1998/12/12 01:37:02 lfb Exp $ */ #include "tclInt.h" #include "tclPort.h" @@ -30,10 +30,11 @@ 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 procedures defined in this file: */ @@ -51,11 +52,11 @@ * 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 interp->result. Several arguments are side-effected; see + * in the interp's result. Several arguments are side-effected; see * the argument list below for details. * * Side effects: * None. * @@ -181,16 +182,19 @@ Tcl_Pid *pidPtr; /* Array of pids to detach. */ { register Detached *detPtr; int i; + Tcl_MutexLock(&pipeMutex); for (i = 0; i < numPids; i++) { detPtr = (Detached *) ckalloc(sizeof(Detached)); detPtr->pid = pidPtr[i]; detPtr->nextPtr = detList; detList = detPtr; } + Tcl_MutexUnlock(&pipeMutex); + } /* *---------------------------------------------------------------------- * @@ -217,10 +221,11 @@ 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; @@ -233,10 +238,11 @@ prevPtr->nextPtr = detPtr->nextPtr; } ckfree((char *) detPtr); detPtr = nextPtr; } + Tcl_MutexUnlock(&pipeMutex); } /* *---------------------------------------------------------------------- * @@ -247,14 +253,14 @@ * 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 interp->result. + * and a message is left in the interp's result. * * Side effects: - * If the last character of interp->result is a newline, then it + * 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. * *---------------------------------------------------------------------- */ @@ -303,17 +309,17 @@ * 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[20], msg2[20]; + char msg1[TCL_INTEGER_SPACE], msg2[TCL_INTEGER_SPACE]; result = TCL_ERROR; - sprintf(msg1, "%ld", TclpGetPid(pid)); + TclFormatInt(msg1, (long) TclpGetPid(pid)); if (WIFEXITED(waitStatus)) { if (interp != (Tcl_Interp *) NULL) { - sprintf(msg2, "%d", WEXITSTATUS(waitStatus)); + TclFormatInt(msg2, WEXITSTATUS(waitStatus)); Tcl_SetErrorCode(interp, "CHILDSTATUS", msg1, msg2, (char *) NULL); } abnormalExit = 1; } else if (WIFSIGNALED(waitStatus)) { @@ -359,48 +365,43 @@ /* * Make sure we start at the beginning of the file. */ - Tcl_Seek(errorChan, 0L, SEEK_SET); - - if (interp != (Tcl_Interp *) NULL) { - while (1) { -#define BUFFER_SIZE 1000 - char buffer[BUFFER_SIZE+1]; - int count; - - count = Tcl_Read(errorChan, buffer, BUFFER_SIZE); - if (count == 0) { - break; - } - result = TCL_ERROR; - if (count < 0) { - Tcl_AppendResult(interp, - "error reading stderr output file: ", - Tcl_PosixError(interp), (char *) NULL); - break; /* out of the "while (1)" loop. */ - } - buffer[count] = 0; - Tcl_AppendResult(interp, buffer, (char *) NULL); - anyErrorInfo = 1; - } - } - - Tcl_Close((Tcl_Interp *) NULL, errorChan); + if (interp != NULL) { + int count; + Tcl_Obj *objPtr; + + Tcl_Seek(errorChan, 0L, 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_AppendResult(interp, "error reading stderr output file: ", + Tcl_PosixError(interp), NULL); + } 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 && !anyErrorInfo && (interp != (Tcl_Interp *) NULL)) { + if ((abnormalExit != 0) && (anyErrorInfo == 0) && (interp != NULL)) { Tcl_AppendResult(interp, "child process exited abnormally", (char *) NULL); } - return result; } /* *---------------------------------------------------------------------- @@ -687,11 +688,11 @@ /* * 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, NULL); + inputFile = TclpCreateTempFile(inputLiteral); if (inputFile == NULL) { Tcl_AppendResult(interp, "couldn't create input file for command: ", Tcl_PosixError(interp), (char *) NULL); goto error; @@ -763,11 +764,11 @@ * 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, NULL); + errorFile = TclpCreateTempFile(NULL); if (errorFile == NULL) { Tcl_AppendResult(interp, "couldn't create error file for command: ", Tcl_PosixError(interp), (char *) NULL); goto error; @@ -797,19 +798,19 @@ pidPtr = (Tcl_Pid *) ckalloc((unsigned) (cmdCount * sizeof(Tcl_Pid))); curInFile = inputFile; for (i = 0; i < argc; i = lastArg + 1) { - int joinThisError; + int result, joinThisError; Tcl_Pid pid; + char *oldName; /* * Convert the program name into native form. */ - argv[i] = Tcl_TranslateFileName(interp, argv[i], &execBuffer); - if (argv[i] == NULL) { + if (Tcl_TranslateFileName(interp, argv[i], &execBuffer) == NULL) { goto error; } /* * Find the end of the current segment of the pipeline. @@ -849,12 +850,21 @@ curErrFile = curOutFile; } else { curErrFile = errorFile; } - if (TclpCreateProcess(interp, lastArg - i, argv + i, - curInFile, curOutFile, curErrFile, &pid) != TCL_OK) { + /* + * 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; Index: generic/tclPkg.c ================================================================== --- generic/tclPkg.c +++ generic/tclPkg.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) tclPkg.c 1.9 97/05/14 13:23:51 + * RCS: @(#) $Id: tclPkg.c,v 1.1.2.4 1999/03/25 23:28:54 stanton Exp $ */ #include "tclInt.h" /* @@ -41,10 +41,11 @@ * 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. */ + ClientData clientData; /* Client data. */ } Package; /* * Prototypes for procedures defined in this file: */ @@ -57,21 +58,21 @@ char *name)); /* *---------------------------------------------------------------------- * - * Tcl_PkgProvide -- + * Tcl_PkgProvide / Tcl_PkgProvideEx -- * * This procedure 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 interp->result. + * 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. @@ -84,19 +85,35 @@ Tcl_Interp *interp; /* Interpreter in which package is now * available. */ char *name; /* Name of package. */ char *version; /* Version string for package. */ { + return Tcl_PkgProvideEx(interp, name, version, (ClientData) NULL); +} + +int +Tcl_PkgProvideEx(interp, name, version, clientData) + Tcl_Interp *interp; /* Interpreter in which package is now + * available. */ + char *name; /* Name of package. */ + char *version; /* Version string for package. */ + ClientData clientData; /* clientdata for this package (normally + * used for C callback function table) */ +{ Package *pkgPtr; pkgPtr = FindPackage(interp, name); if (pkgPtr->version == NULL) { pkgPtr->version = ckalloc((unsigned) (strlen(version) + 1)); strcpy(pkgPtr->version, version); + pkgPtr->clientData = clientData; return TCL_OK; } if (ComparePkgVersions(pkgPtr->version, version, (int *) NULL) == 0) { + if (clientData != NULL) { + pkgPtr->clientData = clientData; + } return TCL_OK; } Tcl_AppendResult(interp, "conflicting versions provided for package \"", name, "\": ", pkgPtr->version, ", then ", version, (char *) NULL); return TCL_ERROR; @@ -103,11 +120,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_PkgRequire -- + * Tcl_PkgRequire / Tcl_PkgRequireEx -- * * This procedure 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 procedure invokes a Tcl script * to provide it. If the package is already provided, this @@ -120,11 +137,11 @@ * 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 interp->result. + * 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. * @@ -141,15 +158,50 @@ * 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, (ClientData *) NULL); +} + +char * +Tcl_PkgRequireEx(interp, name, version, exact, clientDataPtr) + Tcl_Interp *interp; /* Interpreter in which package is now + * available. */ + char *name; /* Name of desired package. */ + 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. */ + ClientData *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. */ +{ Package *pkgPtr; PkgAvail *availPtr, *bestPtr; char *script; int code, satisfies, result, pass; Tcl_DString command; + + /* + * If an attempt is being made to load this into a standalong 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) { + Tcl_AppendResult(interp, "Cannot load package \"", name, + "\" in standalone executable: This package is not ", + "compiled with stub support", NULL); + 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 @@ -251,19 +303,25 @@ } return NULL; } /* - * At this point we now that the package is present. Make sure that the + * At this point we know that the package is present. Make sure that the * provided version meets the current requirement. */ if (version == NULL) { + if (clientDataPtr) { + *clientDataPtr = pkgPtr->clientData; + } return pkgPtr->version; } result = ComparePkgVersions(pkgPtr->version, version, &satisfies); if ((satisfies && !exact) || (result == 0)) { + if (clientDataPtr) { + *clientDataPtr = pkgPtr->clientData; + } return pkgPtr->version; } Tcl_AppendResult(interp, "version conflict for package \"", name, "\": have ", pkgPtr->version, ", need ", version, (char *) NULL); @@ -271,11 +329,127 @@ } /* *---------------------------------------------------------------------- * - * Tcl_PackageCmd -- + * 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. + * + *---------------------------------------------------------------------- + */ + +char * +Tcl_PkgPresent(interp, name, version, exact) + Tcl_Interp *interp; /* Interpreter in which package is now + * available. */ + char *name; /* Name of desired package. */ + 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, (ClientData *) NULL); +} + +char * +Tcl_PkgPresentEx(interp, name, version, exact, clientDataPtr) + Tcl_Interp *interp; /* Interpreter in which package is now + * available. */ + char *name; /* Name of desired package. */ + 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. */ + ClientData *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; + int satisfies, result; + + /* + * 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) { + Tcl_AppendResult(interp, "Cannot load package \"", name, + "\" in standalone executable: This package is not ", + "compiled with stub support", NULL); + return NULL; + } + + hPtr = Tcl_FindHashEntry(&iPtr->packageTable, name); + if (hPtr) { + pkgPtr = (Package *) 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. + */ + + if (version == NULL) { + if (clientDataPtr) { + *clientDataPtr = pkgPtr->clientData; + } + + return pkgPtr->version; + } + result = ComparePkgVersions(pkgPtr->version, version, &satisfies); + if ((satisfies && !exact) || (result == 0)) { + if (clientDataPtr) { + *clientDataPtr = pkgPtr->clientData; + } + + return pkgPtr->version; + } + Tcl_AppendResult(interp, "version conflict for package \"", + name, "\": have ", pkgPtr->version, + ", need ", version, (char *) NULL); + return NULL; + } + } + + if (version != NULL) { + Tcl_AppendResult(interp, "package ", name, " ", version, + " is not present", (char *) NULL); + } else { + Tcl_AppendResult(interp, "package ", name, " is not present", + (char *) NULL); + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_PackageObjCmd -- * * This procedure is invoked to process the "package" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -287,230 +461,297 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_PackageCmd(dummy, interp, argc, argv) +Tcl_PackageObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { + static char *pkgOptions[] = { + "forget", "ifneeded", "names", "present", "provide", "require", + "unknown", "vcompare", "versions", "vsatisfies", (char *) NULL + }; + enum pkgOptions { + PKG_FORGET, PKG_IFNEEDED, PKG_NAMES, PKG_PRESENT, + PKG_PROVIDE, PKG_REQUIRE, PKG_UNKNOWN, PKG_VCOMPARE, + PKG_VERSIONS, PKG_VSATISFIES + }; Interp *iPtr = (Interp *) interp; - size_t length; - int c, exact, i, satisfies; + int optionIndex, exact, i, satisfies; PkgAvail *availPtr, *prevPtr; Package *pkgPtr; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_HashTable *tablePtr; - char *version; - char buf[30]; - - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " option ?arg arg ...?\"", (char *) NULL); - return TCL_ERROR; - } - c = argv[1][0]; - length = strlen(argv[1]); - if ((c == 'f') && (strncmp(argv[1], "forget", length) == 0)) { - for (i = 2; i < argc; i++) { - hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv[i]); - if (hPtr == NULL) { - return TCL_OK; - } - pkgPtr = (Package *) Tcl_GetHashValue(hPtr); - Tcl_DeleteHashEntry(hPtr); - if (pkgPtr->version != NULL) { - ckfree(pkgPtr->version); - } - while (pkgPtr->availPtr != NULL) { - availPtr = pkgPtr->availPtr; - pkgPtr->availPtr = availPtr->nextPtr; - ckfree(availPtr->version); - Tcl_EventuallyFree((ClientData)availPtr->script, TCL_DYNAMIC); - ckfree((char *) availPtr); - } - ckfree((char *) pkgPtr); - } - } else if ((c == 'i') && (strncmp(argv[1], "ifneeded", length) == 0)) { - if ((argc != 4) && (argc != 5)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ifneeded package version ?script?\"", (char *) NULL); - return TCL_ERROR; - } - if (CheckVersion(interp, argv[3]) != TCL_OK) { - return TCL_ERROR; - } - if (argc == 4) { - hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv[2]); - if (hPtr == NULL) { - return TCL_OK; - } - pkgPtr = (Package *) Tcl_GetHashValue(hPtr); - } else { - pkgPtr = FindPackage(interp, argv[2]); - } - for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL; - prevPtr = availPtr, availPtr = availPtr->nextPtr) { - if (ComparePkgVersions(availPtr->version, argv[3], (int *) NULL) - == 0) { - if (argc == 4) { - Tcl_SetResult(interp, availPtr->script, TCL_VOLATILE); - return TCL_OK; - } - Tcl_EventuallyFree((ClientData)availPtr->script, TCL_DYNAMIC); - break; - } - } - if (argc == 4) { - return TCL_OK; - } - if (availPtr == NULL) { - availPtr = (PkgAvail *) ckalloc(sizeof(PkgAvail)); - availPtr->version = ckalloc((unsigned) (strlen(argv[3]) + 1)); - strcpy(availPtr->version, argv[3]); - if (prevPtr == NULL) { - availPtr->nextPtr = pkgPtr->availPtr; - pkgPtr->availPtr = availPtr; - } else { - availPtr->nextPtr = prevPtr->nextPtr; - prevPtr->nextPtr = availPtr; - } - } - availPtr->script = ckalloc((unsigned) (strlen(argv[4]) + 1)); - strcpy(availPtr->script, argv[4]); - } else if ((c == 'n') && (strncmp(argv[1], "names", length) == 0)) { - if (argc != 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " names\"", (char *) NULL); - return TCL_ERROR; - } - tablePtr = &iPtr->packageTable; - for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL; - hPtr = Tcl_NextHashEntry(&search)) { - pkgPtr = (Package *) Tcl_GetHashValue(hPtr); - if ((pkgPtr->version != NULL) || (pkgPtr->availPtr != NULL)) { - Tcl_AppendElement(interp, Tcl_GetHashKey(tablePtr, hPtr)); - } - } - } else if ((c == 'p') && (strncmp(argv[1], "provide", length) == 0)) { - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " provide package ?version?\"", (char *) NULL); - return TCL_ERROR; - } - if (argc == 3) { - hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv[2]); - if (hPtr != NULL) { - pkgPtr = (Package *) Tcl_GetHashValue(hPtr); - if (pkgPtr->version != NULL) { - Tcl_SetResult(interp, pkgPtr->version, TCL_VOLATILE); - } - } - return TCL_OK; - } - if (CheckVersion(interp, argv[3]) != TCL_OK) { - return TCL_ERROR; - } - return Tcl_PkgProvide(interp, argv[2], argv[3]); - } else if ((c == 'r') && (strncmp(argv[1], "require", length) == 0)) { - if (argc < 3) { - requireSyntax: - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " require ?-exact? package ?version?\"", (char *) NULL); - return TCL_ERROR; - } - if ((argv[2][0] == '-') && (strcmp(argv[2], "-exact") == 0)) { - exact = 1; - } else { - exact = 0; - } - version = NULL; - if (argc == (4+exact)) { - version = argv[3+exact]; - if (CheckVersion(interp, version) != TCL_OK) { - return TCL_ERROR; - } - } else if ((argc != 3) || exact) { - goto requireSyntax; - } - version = Tcl_PkgRequire(interp, argv[2+exact], version, exact); - if (version == NULL) { - return TCL_ERROR; - } - Tcl_SetResult(interp, version, TCL_VOLATILE); - } else if ((c == 'u') && (strncmp(argv[1], "unknown", length) == 0)) { - if (argc == 2) { - if (iPtr->packageUnknown != NULL) { - Tcl_SetResult(interp, iPtr->packageUnknown, TCL_VOLATILE); - } - } else if (argc == 3) { - if (iPtr->packageUnknown != NULL) { - ckfree(iPtr->packageUnknown); - } - if (argv[2][0] == 0) { - iPtr->packageUnknown = NULL; - } else { - iPtr->packageUnknown = (char *) ckalloc((unsigned) - (strlen(argv[2]) + 1)); - strcpy(iPtr->packageUnknown, argv[2]); - } - } else { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " unknown ?command?\"", (char *) NULL); - return TCL_ERROR; - } - } else if ((c == 'v') && (strncmp(argv[1], "vcompare", length) == 0) - && (length >= 2)) { - if (argc != 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " vcompare version1 version2\"", (char *) NULL); - return TCL_ERROR; - } - if ((CheckVersion(interp, argv[2]) != TCL_OK) - || (CheckVersion(interp, argv[3]) != TCL_OK)) { - return TCL_ERROR; - } - TclFormatInt(buf, ComparePkgVersions(argv[2], argv[3], (int *) NULL)); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else if ((c == 'v') && (strncmp(argv[1], "versions", length) == 0) - && (length >= 2)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " versions package\"", (char *) NULL); - return TCL_ERROR; - } - hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv[2]); - if (hPtr != NULL) { - pkgPtr = (Package *) Tcl_GetHashValue(hPtr); - for (availPtr = pkgPtr->availPtr; availPtr != NULL; - availPtr = availPtr->nextPtr) { - Tcl_AppendElement(interp, availPtr->version); - } - } - } else if ((c == 'v') && (strncmp(argv[1], "vsatisfies", length) == 0) - && (length >= 2)) { - if (argc != 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " vsatisfies version1 version2\"", (char *) NULL); - return TCL_ERROR; - } - if ((CheckVersion(interp, argv[2]) != TCL_OK) - || (CheckVersion(interp, argv[3]) != TCL_OK)) { - return TCL_ERROR; - } - ComparePkgVersions(argv[2], argv[3], &satisfies); - TclFormatInt(buf, satisfies); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": should be forget, ifneeded, names, ", - "provide, require, unknown, vcompare, ", - "versions, or vsatisfies", (char *) NULL); - return TCL_ERROR; + char *version, *argv2, *argv3, *argv4; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg 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: { + char *keyString; + for (i = 2; i < objc; i++) { + keyString = Tcl_GetString(objv[i]); + hPtr = Tcl_FindHashEntry(&iPtr->packageTable, keyString); + if (hPtr == NULL) { + return TCL_OK; + } + pkgPtr = (Package *) Tcl_GetHashValue(hPtr); + Tcl_DeleteHashEntry(hPtr); + if (pkgPtr->version != NULL) { + ckfree(pkgPtr->version); + } + while (pkgPtr->availPtr != NULL) { + availPtr = pkgPtr->availPtr; + pkgPtr->availPtr = availPtr->nextPtr; + ckfree(availPtr->version); + Tcl_EventuallyFree((ClientData)availPtr->script, TCL_DYNAMIC); + ckfree((char *) availPtr); + } + ckfree((char *) pkgPtr); + } + break; + } + case PKG_IFNEEDED: { + int length; + if ((objc != 4) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "package version ?script?"); + return TCL_ERROR; + } + argv3 = Tcl_GetString(objv[3]); + if (CheckVersion(interp, argv3) != TCL_OK) { + return TCL_ERROR; + } + argv2 = Tcl_GetString(objv[2]); + if (objc == 4) { + hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2); + if (hPtr == NULL) { + return TCL_OK; + } + pkgPtr = (Package *) 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 (ComparePkgVersions(availPtr->version, argv3, (int *) NULL) + == 0) { + if (objc == 4) { + Tcl_SetResult(interp, availPtr->script, TCL_VOLATILE); + return TCL_OK; + } + Tcl_EventuallyFree((ClientData)availPtr->script, TCL_DYNAMIC); + break; + } + } + if (objc == 4) { + return TCL_OK; + } + if (availPtr == NULL) { + availPtr = (PkgAvail *) ckalloc(sizeof(PkgAvail)); + availPtr->version = ckalloc((unsigned) (length + 1)); + strcpy(availPtr->version, argv3); + if (prevPtr == NULL) { + availPtr->nextPtr = pkgPtr->availPtr; + pkgPtr->availPtr = availPtr; + } else { + availPtr->nextPtr = prevPtr->nextPtr; + prevPtr->nextPtr = availPtr; + } + } + argv4 = Tcl_GetStringFromObj(objv[4], &length); + availPtr->script = ckalloc((unsigned) (length + 1)); + strcpy(availPtr->script, argv4); + break; + } + case PKG_NAMES: { + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; + } + tablePtr = &iPtr->packageTable; + for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL; + hPtr = Tcl_NextHashEntry(&search)) { + pkgPtr = (Package *) Tcl_GetHashValue(hPtr); + if ((pkgPtr->version != NULL) || (pkgPtr->availPtr != NULL)) { + Tcl_AppendElement(interp, Tcl_GetHashKey(tablePtr, hPtr)); + } + } + break; + } + case PKG_PRESENT: { + if (objc < 3) { + presentSyntax: + Tcl_WrongNumArgs(interp, 2, objv, "?-exact? package ?version?"); + return TCL_ERROR; + } + argv2 = Tcl_GetString(objv[2]); + if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) { + exact = 1; + } else { + exact = 0; + } + version = NULL; + if (objc == (4 + exact)) { + version = Tcl_GetString(objv[3 + exact]); + if (CheckVersion(interp, version) != TCL_OK) { + return TCL_ERROR; + } + } else if ((objc != 3) || exact) { + goto presentSyntax; + } + if (exact) { + argv3 = Tcl_GetString(objv[3]); + version = Tcl_PkgPresent(interp, argv3, version, exact); + } else { + version = Tcl_PkgPresent(interp, argv2, version, exact); + } + if (version == NULL) { + return TCL_ERROR; + } + Tcl_SetResult(interp, version, TCL_VOLATILE); + break; + } + case PKG_PROVIDE: { + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "package ?version?"); + return TCL_ERROR; + } + argv2 = Tcl_GetString(objv[2]); + if (objc == 3) { + hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2); + if (hPtr != NULL) { + pkgPtr = (Package *) Tcl_GetHashValue(hPtr); + if (pkgPtr->version != NULL) { + Tcl_SetResult(interp, pkgPtr->version, TCL_VOLATILE); + } + } + return TCL_OK; + } + argv3 = Tcl_GetString(objv[3]); + if (CheckVersion(interp, argv3) != TCL_OK) { + return TCL_ERROR; + } + return Tcl_PkgProvide(interp, argv2, argv3); + } + case PKG_REQUIRE: { + if (objc < 3) { + requireSyntax: + Tcl_WrongNumArgs(interp, 2, objv, "?-exact? package ?version?"); + return TCL_ERROR; + } + argv2 = Tcl_GetString(objv[2]); + if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) { + exact = 1; + } else { + exact = 0; + } + version = NULL; + if (objc == (4 + exact)) { + version = Tcl_GetString(objv[3 + exact]); + if (CheckVersion(interp, version) != TCL_OK) { + return TCL_ERROR; + } + } else if ((objc != 3) || exact) { + goto requireSyntax; + } + if (exact) { + argv3 = Tcl_GetString(objv[3]); + version = Tcl_PkgRequire(interp, argv3, version, exact); + } else { + version = Tcl_PkgRequire(interp, argv2, version, exact); + } + if (version == NULL) { + return TCL_ERROR; + } + Tcl_SetResult(interp, version, TCL_VOLATILE); + break; + } + case PKG_UNKNOWN: { + int length; + if (objc == 2) { + if (iPtr->packageUnknown != NULL) { + Tcl_SetResult(interp, iPtr->packageUnknown, TCL_VOLATILE); + } + } 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 { + iPtr->packageUnknown = (char *) ckalloc((unsigned) + (length + 1)); + strcpy(iPtr->packageUnknown, argv2); + } + } else { + Tcl_WrongNumArgs(interp, 2, objv, "?command?"); + return TCL_ERROR; + } + break; + } + case PKG_VCOMPARE: { + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "version1 version2"); + return TCL_ERROR; + } + argv3 = Tcl_GetString(objv[3]); + argv2 = Tcl_GetString(objv[2]); + if ((CheckVersion(interp, argv2) != TCL_OK) + || (CheckVersion(interp, argv3) != TCL_OK)) { + return TCL_ERROR; + } + Tcl_SetIntObj(Tcl_GetObjResult(interp), + ComparePkgVersions(argv2, argv3, (int *) NULL)); + break; + } + case PKG_VERSIONS: { + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "package"); + return TCL_ERROR; + } + argv2 = Tcl_GetString(objv[2]); + hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2); + if (hPtr != NULL) { + pkgPtr = (Package *) Tcl_GetHashValue(hPtr); + for (availPtr = pkgPtr->availPtr; availPtr != NULL; + availPtr = availPtr->nextPtr) { + Tcl_AppendElement(interp, availPtr->version); + } + } + break; + } + case PKG_VSATISFIES: { + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "version1 version2"); + return TCL_ERROR; + } + argv3 = Tcl_GetString(objv[3]); + argv2 = Tcl_GetString(objv[2]); + if ((CheckVersion(interp, argv2) != TCL_OK) + || (CheckVersion(interp, argv3) != TCL_OK)) { + return TCL_ERROR; + } + ComparePkgVersions(argv2, argv3, &satisfies); + Tcl_SetIntObj(Tcl_GetObjResult(interp), satisfies); + break; + } + default: { + panic("Tcl_PackageObjCmd: bad option index to pkgOptions"); + } } return TCL_OK; } /* @@ -545,10 +786,11 @@ hPtr = Tcl_CreateHashEntry(&iPtr->packageTable, name, &new); if (new) { pkgPtr = (Package *) ckalloc(sizeof(Package)); pkgPtr->version = NULL; pkgPtr->availPtr = NULL; + pkgPtr->clientData = NULL; Tcl_SetHashValue(hPtr, pkgPtr); } else { pkgPtr = (Package *) Tcl_GetHashValue(hPtr); } return pkgPtr; @@ -611,11 +853,11 @@ * valid syntax. * * 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 interp->result. + * message is left in the interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -628,15 +870,15 @@ * groups of decimal digits separated * by dots. */ { char *p = string; - if (!isdigit(UCHAR(*p))) { + if (!isdigit(UCHAR(*p))) { /* INTL: digit */ goto error; } for (p++; *p != 0; p++) { - if (!isdigit(UCHAR(*p)) && (*p != '.')) { + if (!isdigit(UCHAR(*p)) && (*p != '.')) { /* INTL: digit */ goto error; } } if (p[-1] != '.') { return TCL_OK; ADDED generic/tclPlatDecls.h Index: generic/tclPlatDecls.h ================================================================== --- /dev/null +++ generic/tclPlatDecls.h @@ -0,0 +1,146 @@ +/* + * tclPlatDecls.h -- + * + * Declarations of platform specific Tcl APIs. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * All rights reserved. + * + * RCS: @(#) $Id: tclPlatDecls.h,v 1.3.2.5 1999/04/01 21:58:18 stanton Exp $ + */ + +#ifndef _TCLPLATDECLS +#define _TCLPLATDECLS + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +#ifdef __WIN32__ +/* 0 */ +EXTERN TCHAR * Tcl_WinUtfToTChar _ANSI_ARGS_((CONST char * str, + int len, Tcl_DString * dsPtr)); +/* 1 */ +EXTERN char * Tcl_WinTCharToUtf _ANSI_ARGS_((CONST TCHAR * str, + int len, Tcl_DString * dsPtr)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 0 */ +EXTERN void Tcl_MacSetEventProc _ANSI_ARGS_(( + Tcl_MacConvertEventPtr procPtr)); +/* 1 */ +EXTERN char * Tcl_MacConvertTextResource _ANSI_ARGS_(( + Handle resource)); +/* 2 */ +EXTERN int Tcl_MacEvalResource _ANSI_ARGS_((Tcl_Interp * interp, + char * resourceName, int resourceNumber, + char * fileName)); +/* 3 */ +EXTERN Handle Tcl_MacFindResource _ANSI_ARGS_((Tcl_Interp * interp, + long resourceType, char * resourceName, + int resourceNumber, char * resFileRef, + int * releaseIt)); +/* 4 */ +EXTERN int Tcl_GetOSTypeFromObj _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr, + OSType * osTypePtr)); +/* 5 */ +EXTERN void Tcl_SetOSTypeObj _ANSI_ARGS_((Tcl_Obj * objPtr, + OSType osType)); +/* 6 */ +EXTERN Tcl_Obj * Tcl_NewOSTypeObj _ANSI_ARGS_((OSType osType)); +/* 7 */ +EXTERN int strncasecmp _ANSI_ARGS_((CONST char * s1, + CONST char * s2, size_t n)); +/* 8 */ +EXTERN int strcasecmp _ANSI_ARGS_((CONST char * s1, + CONST char * s2)); +#endif /* MAC_TCL */ + +typedef struct TclPlatStubs { + int magic; + struct TclPlatStubHooks *hooks; + +#ifdef __WIN32__ + TCHAR * (*tcl_WinUtfToTChar) _ANSI_ARGS_((CONST char * str, int len, Tcl_DString * dsPtr)); /* 0 */ + char * (*tcl_WinTCharToUtf) _ANSI_ARGS_((CONST TCHAR * str, int len, Tcl_DString * dsPtr)); /* 1 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tcl_MacSetEventProc) _ANSI_ARGS_((Tcl_MacConvertEventPtr procPtr)); /* 0 */ + char * (*tcl_MacConvertTextResource) _ANSI_ARGS_((Handle resource)); /* 1 */ + int (*tcl_MacEvalResource) _ANSI_ARGS_((Tcl_Interp * interp, char * resourceName, int resourceNumber, char * fileName)); /* 2 */ + Handle (*tcl_MacFindResource) _ANSI_ARGS_((Tcl_Interp * interp, long resourceType, char * resourceName, int resourceNumber, char * resFileRef, int * releaseIt)); /* 3 */ + int (*tcl_GetOSTypeFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, OSType * osTypePtr)); /* 4 */ + void (*tcl_SetOSTypeObj) _ANSI_ARGS_((Tcl_Obj * objPtr, OSType osType)); /* 5 */ + Tcl_Obj * (*tcl_NewOSTypeObj) _ANSI_ARGS_((OSType osType)); /* 6 */ + int (*strncasecmp) _ANSI_ARGS_((CONST char * s1, CONST char * s2, size_t n)); /* 7 */ + int (*strcasecmp) _ANSI_ARGS_((CONST char * s1, CONST char * s2)); /* 8 */ +#endif /* MAC_TCL */ +} TclPlatStubs; + +extern TclPlatStubs *tclPlatStubsPtr; + +#if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifdef __WIN32__ +#ifndef Tcl_WinUtfToTChar +#define Tcl_WinUtfToTChar \ + (tclPlatStubsPtr->tcl_WinUtfToTChar) /* 0 */ +#endif +#ifndef Tcl_WinTCharToUtf +#define Tcl_WinTCharToUtf \ + (tclPlatStubsPtr->tcl_WinTCharToUtf) /* 1 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef Tcl_MacSetEventProc +#define Tcl_MacSetEventProc \ + (tclPlatStubsPtr->tcl_MacSetEventProc) /* 0 */ +#endif +#ifndef Tcl_MacConvertTextResource +#define Tcl_MacConvertTextResource \ + (tclPlatStubsPtr->tcl_MacConvertTextResource) /* 1 */ +#endif +#ifndef Tcl_MacEvalResource +#define Tcl_MacEvalResource \ + (tclPlatStubsPtr->tcl_MacEvalResource) /* 2 */ +#endif +#ifndef Tcl_MacFindResource +#define Tcl_MacFindResource \ + (tclPlatStubsPtr->tcl_MacFindResource) /* 3 */ +#endif +#ifndef Tcl_GetOSTypeFromObj +#define Tcl_GetOSTypeFromObj \ + (tclPlatStubsPtr->tcl_GetOSTypeFromObj) /* 4 */ +#endif +#ifndef Tcl_SetOSTypeObj +#define Tcl_SetOSTypeObj \ + (tclPlatStubsPtr->tcl_SetOSTypeObj) /* 5 */ +#endif +#ifndef Tcl_NewOSTypeObj +#define Tcl_NewOSTypeObj \ + (tclPlatStubsPtr->tcl_NewOSTypeObj) /* 6 */ +#endif +#ifndef strncasecmp +#define strncasecmp \ + (tclPlatStubsPtr->strncasecmp) /* 7 */ +#endif +#ifndef strcasecmp +#define strcasecmp \ + (tclPlatStubsPtr->strcasecmp) /* 8 */ +#endif +#endif /* MAC_TCL */ + +#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#endif /* _TCLPLATDECLS */ + + Index: generic/tclPort.h ================================================================== --- generic/tclPort.h +++ generic/tclPort.h @@ -8,17 +8,17 @@ * 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. * - * SCCS: @(#) tclPort.h 1.15 96/02/07 17:24:21 + * RCS: @(#) $Id: tclPort.h,v 1.1.2.2 1998/09/24 23:59:01 stanton Exp $ */ #ifndef _TCLPORT #define _TCLPORT -#if defined(__WIN32__) || defined(_WIN32) +#if defined(__WIN32__) # include "../win/tclWinPort.h" #else # if defined(MAC_TCL) # include "tclMacPort.h" # else Index: generic/tclPosixStr.c ================================================================== --- generic/tclPosixStr.c +++ generic/tclPosixStr.c @@ -9,11 +9,11 @@ * 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. * - * SCCS: @(#) tclPosixStr.c 1.33 97/10/08 12:40:12 + * RCS: @(#) $Id: tclPosixStr.c,v 1.1.2.2 1998/09/24 23:59:01 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" @@ -334,11 +334,11 @@ case ENOTUNIQ: return "ENOTUNIQ"; #endif #ifdef ENXIO case ENXIO: return "ENXIO"; #endif -#ifdef EOPNOTSUPP +#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP)) case EOPNOTSUPP: return "EOPNOTSUPP"; #endif #ifdef EPERM case EPERM: return "EPERM"; #endif @@ -781,11 +781,11 @@ case ENOTUNIQ: return "name not unique on network"; #endif #ifdef ENXIO case ENXIO: return "no such device or address"; #endif -#ifdef EOPNOTSUPP +#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP)) case EOPNOTSUPP: return "operation not supported on socket"; #endif #ifdef EPERM case EPERM: return "not owner"; #endif Index: generic/tclPreserve.c ================================================================== --- generic/tclPreserve.c +++ generic/tclPreserve.c @@ -5,16 +5,16 @@ * to make sure that widget records and other data structures * aren't reallocated when there are nested procedures that * depend on their existence. * * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1995 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclPreserve.c 1.18 96/08/05 13:15:08 + * RCS: @(#) $Id: tclPreserve.c,v 1.1.2.5 1998/12/12 01:37:02 lfb Exp $ */ #include "tclInt.h" /* @@ -38,10 +38,35 @@ static int spaceAvl = 0; /* Total number of structures available * at *firstRefPtr. */ static int inUse = 0; /* Count of structures currently in use * in refArray. */ #define INITIAL_SIZE 2 +TCL_DECLARE_MUTEX(preserveMutex)/* To protect the above statics */ + +/* + * 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 abpve 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; + /* * Static routines in this file: */ @@ -67,16 +92,18 @@ /* ARGSUSED */ static void PreserveExitProc(clientData) ClientData clientData; /* NULL -Unused. */ { + Tcl_MutexLock(&preserveMutex); if (spaceAvl != 0) { ckfree((char *) refArray); refArray = (Reference *) NULL; inUse = 0; spaceAvl = 0; } + Tcl_MutexUnlock(&preserveMutex); } /* *---------------------------------------------------------------------- * @@ -106,13 +133,15 @@ /* * 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; i < inUse; i++, refPtr++) { if (refPtr->clientData == clientData) { refPtr->refCount++; + Tcl_MutexUnlock(&preserveMutex); return; } } /* @@ -148,10 +177,11 @@ refPtr->clientData = clientData; refPtr->refCount = 1; refPtr->mustFree = 0; refPtr->freeProc = TCL_STATIC; inUse += 1; + Tcl_MutexUnlock(&preserveMutex); } /* *---------------------------------------------------------------------- * @@ -179,10 +209,11 @@ Reference *refPtr; int mustFree; Tcl_FreeProc *freeProc; int i; + Tcl_MutexLock(&preserveMutex); for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) { if (refPtr->clientData != clientData) { continue; } refPtr->refCount--; @@ -204,16 +235,20 @@ if (mustFree) { if ((freeProc == TCL_DYNAMIC) || (freeProc == (Tcl_FreeProc *) free)) { ckfree((char *) clientData); } else { + Tcl_MutexUnlock(&preserveMutex); (*freeProc)((char *) clientData); + return; } } } + Tcl_MutexUnlock(&preserveMutex); return; } + Tcl_MutexUnlock(&preserveMutex); /* * Reference not found. This is a bug in the caller. */ @@ -250,21 +285,24 @@ /* * 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) { panic("Tcl_EventuallyFree called twice for 0x%x\n", clientData); } refPtr->mustFree = 1; refPtr->freeProc = freeProc; + Tcl_MutexUnlock(&preserveMutex); return; } + Tcl_MutexUnlock(&preserveMutex); /* * No reference for this block. Free it now. */ @@ -273,5 +311,180 @@ ckfree((char *) clientData); } else { (*freeProc)((char *)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(ptr) + VOID *ptr; /* Pointer to an arbitrary block of memory + * to be tracked for deletion. Must not be + * NULL. */ +{ + HandleStruct *handlePtr; + + handlePtr = (HandleStruct *) 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(handle) + 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) { + panic("using previously disposed TclHandle %x", handlePtr); + } + if (handlePtr->ptr2 != handlePtr->ptr) { + panic("someone has changed the block referenced by the handle %x\nfrom %x to %x", + handlePtr, handlePtr->ptr2, handlePtr->ptr); + } +#endif + handlePtr->ptr = NULL; + if (handlePtr->refCount == 0) { + ckfree((char *) 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(handle) + 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) { + panic("using previously disposed TclHandle %x", handlePtr); + } + if ((handlePtr->ptr != NULL) + && (handlePtr->ptr != handlePtr->ptr2)) { + panic("someone has changed the block referenced by the handle %x\nfrom %x to %x", + handlePtr, handlePtr->ptr2, handlePtr->ptr); + } +#endif + handlePtr->refCount++; + + return handle; +} + +/* + *--------------------------------------------------------------------------- + * + * TclHandleRelease -- + * + * This procedure 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(handle) + 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) { + panic("using previously disposed TclHandle %x", handlePtr); + } + if ((handlePtr->ptr != NULL) + && (handlePtr->ptr != handlePtr->ptr2)) { + panic("someone has changed the block referenced by the handle %x\nfrom %x to %x", + handlePtr, handlePtr->ptr2, handlePtr->ptr); + } +#endif + handlePtr->refCount--; + if ((handlePtr->refCount == 0) && (handlePtr->ptr == NULL)) { + ckfree((char *) handlePtr); + } +} + Index: generic/tclProc.c ================================================================== --- generic/tclProc.c +++ generic/tclProc.c @@ -3,29 +3,44 @@ * * 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-1996 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclProc.c 1.116 97/10/29 18:33:24 + * RCS: @(#) $Id: tclProc.c,v 1.1.2.8 1999/03/25 00:34:16 redman Exp $ */ #include "tclInt.h" #include "tclCompile.h" /* - * Forward references to procedures defined later in this file: + * Prototypes for static functions in this file + */ + +static void ProcBodyDup _ANSI_ARGS_((Tcl_Obj *srcPtr, Tcl_Obj *dupPtr)); +static void ProcBodyFree _ANSI_ARGS_((Tcl_Obj *objPtr)); +static int ProcBodySetFromAny _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *objPtr)); +static void ProcBodyUpdateString _ANSI_ARGS_((Tcl_Obj *objPtr)); +static int ProcessProcResultCode _ANSI_ARGS_((Tcl_Interp *interp, + char *procName, int nameLen, int returnCode)); + +/* + * The ProcBodyObjType type */ -static void CleanupProc _ANSI_ARGS_((Proc *procPtr)); -static int InterpProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); -static void ProcDeleteProc _ANSI_ARGS_((ClientData clientData)); +Tcl_ObjType tclProcBodyType = { + "procbody", /* name for this type */ + ProcBodyFree, /* FreeInternalRep procedure */ + ProcBodyDup, /* DupInternalRep procedure */ + ProcBodyUpdateString, /* UpdateString procedure */ + ProcBodySetFromAny /* SetFromAny procedure */ +}; /* *---------------------------------------------------------------------- * * Tcl_ProcObjCmd -- @@ -49,19 +64,15 @@ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { register Interp *iPtr = (Interp *) interp; - register Proc *procPtr; - char *fullName, *procName, *args, *bytes, *p; - char **argArray = NULL; + Proc *procPtr; + char *fullName, *procName; Namespace *nsPtr, *altNsPtr, *cxtNsPtr; - Tcl_Obj *defPtr, *bodyPtr; Tcl_Command cmd; Tcl_DString ds; - int numArgs, length, result, i; - register CompiledLocal *localPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "name args body"); return TCL_ERROR; } @@ -70,17 +81,14 @@ * Determine the namespace where the procedure should reside. Unless * the command name includes namespace qualifiers, this will be the * current namespace. */ - fullName = Tcl_GetStringFromObj(objv[1], (int *) NULL); - result = TclGetNamespaceForQualName(interp, fullName, - (Namespace *) NULL, TCL_LEAVE_ERR_MSG, - &nsPtr, &altNsPtr, &cxtNsPtr, &procName); - if (result != TCL_OK) { - return result; - } + fullName = TclGetString(objv[1]); + TclGetNamespaceForQualName(interp, fullName, (Namespace *) NULL, + 0, &nsPtr, &altNsPtr, &cxtNsPtr, &procName); + if (nsPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't create procedure \"", fullName, "\": unknown namespace", (char *) NULL); return TCL_ERROR; @@ -99,152 +107,15 @@ (char *) NULL); return TCL_ERROR; } /* - * 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 compiler-allocated "slots" - * for local variables. Each formal parameter is given a local variable - * slot (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. - */ - - bodyPtr = objv[3]; - if (Tcl_IsShared(bodyPtr)) { - bytes = Tcl_GetStringFromObj(bodyPtr, &length); - bodyPtr = Tcl_NewStringObj(bytes, length); - } - - /* - * Create and initialize a Proc structure for the procedure. Note that - * we initialize its cmdPtr field below after we've created the command - * 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 = (Proc *) 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. - * THIS FAILS IF THE ARG LIST OBJECT'S STRING REP CONTAINS NULLS. - */ - - args = Tcl_GetStringFromObj(objv[2], &length); - result = Tcl_SplitList(interp, args, &numArgs, &argArray); - if (result != TCL_OK) { - goto procError; - } - - procPtr->numArgs = numArgs; - procPtr->numCompiledLocals = numArgs; - for (i = 0; i < numArgs; i++) { - int fieldCount, nameLength, valueLength; - 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((char *) fieldValues); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "too many fields in argument specifier \"", - argArray[i], "\"", (char *) NULL); - goto procError; - } - if ((fieldCount == 0) || (*fieldValues[0] == 0)) { - ckfree((char *) fieldValues); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "procedure \"", fullName, - "\" has argument with no name", (char *) 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 == '(') { - char *q = p; - do { - q++; - } while (*q != '\0'); - q--; - if (*q == ')') { /* we have an array element */ - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "procedure \"", fullName, - "\" has formal parameter \"", fieldValues[0], - "\" that is an array element", - (char *) NULL); - ckfree((char *) fieldValues); - goto procError; - } - } - p++; - } - - /* - * Allocate an entry in the runtime procedure frame's array of local - * variables for the argument. - */ - - localPtr = (CompiledLocal *) ckalloc((unsigned) - (sizeof(CompiledLocal) - sizeof(localPtr->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->isArg = 1; - localPtr->isTemp = 0; - localPtr->flags = VAR_SCALAR; - if (fieldCount == 2) { - localPtr->defValuePtr = - Tcl_NewStringObj(fieldValues[1], valueLength); - Tcl_IncrRefCount(localPtr->defValuePtr); - } else { - localPtr->defValuePtr = NULL; - } - strcpy(localPtr->name, fieldValues[0]); - - ckfree((char *) fieldValues); + * Create the data structure to represent the procedure. + */ + if (TclCreateProc(interp, nsPtr, procName, objv[2], objv[3], + &procPtr) != TCL_OK) { + 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 @@ -257,41 +128,327 @@ Tcl_DStringAppend(&ds, nsPtr->fullName, -1); Tcl_DStringAppend(&ds, "::", 2); } Tcl_DStringAppend(&ds, procName, -1); - Tcl_CreateCommand(interp, Tcl_DStringValue(&ds), InterpProc, - (ClientData) procPtr, ProcDeleteProc); + Tcl_CreateCommand(interp, Tcl_DStringValue(&ds), TclProcInterpProc, + (ClientData) procPtr, TclProcDeleteProc); cmd = Tcl_CreateObjCommand(interp, Tcl_DStringValue(&ds), - TclObjInterpProc, (ClientData) procPtr, ProcDeleteProc); + TclObjInterpProc, (ClientData) procPtr, TclProcDeleteProc); /* * 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; + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TclCreateProc -- + * + * Creates the data associated with a Tcl procedure definition. + * This procedure 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. This definition should + * be freed by calling TclCleanupProc() when it is no longer + * needed. Returns TCL_ERROR if anything goes wrong. + * + * Side effects: + * If anything goes wrong, this procedure returns an error + * message in the interpreter. + * + *---------------------------------------------------------------------- + */ +int +TclCreateProc(interp, nsPtr, procName, argsPtr, bodyPtr, procPtrPtr) + Tcl_Interp *interp; /* interpreter containing proc */ + Namespace *nsPtr; /* namespace containing this proc */ + 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; + char **argArray = NULL; + + register Proc *procPtr; + int i, length, result, numArgs; + 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. Note that + * we initialize its cmdPtr field below after we've created the command + * for the procedure. We increment the ref count of the Proc struct + * since the command (soon to be created) will be holding a reference + * to it. + */ + + procPtr = (Proc *) bodyPtr->internalRep.otherValuePtr; + 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 compiler-allocated "slots" + * for local variables. Each formal parameter is given a local variable + * slot (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)) { + bytes = Tcl_GetStringFromObj(bodyPtr, &length); + bodyPtr = Tcl_NewStringObj(bytes, length); + } + + /* + * Create and initialize a Proc structure for the procedure. Note that + * we initialize its cmdPtr field below after we've created the command + * 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 = (Proc *) 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 the parsed argument is consistent with the one stored in the + * Proc. + * THIS FAILS IF THE ARG LIST OBJECT'S STRING REP CONTAINS NULLS. + */ + + args = Tcl_GetStringFromObj(argsPtr, &length); + result = Tcl_SplitList(interp, args, &numArgs, &argArray); + if (result != TCL_OK) { + goto procError; + } + + if (precompiled) { + if (numArgs > procPtr->numArgs) { + char buf[128]; + sprintf(buf, "\": arg list contains %d entries, precompiled header expects %d", + numArgs, procPtr->numArgs); + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "procedure \"", procName, + buf, (char *) NULL); + goto procError; + } + localPtr = procPtr->firstLocalPtr; + } else { + procPtr->numArgs = numArgs; + procPtr->numCompiledLocals = numArgs; + } + for (i = 0; i < numArgs; i++) { + int fieldCount, nameLength, valueLength; + 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((char *) fieldValues); + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "too many fields in argument specifier \"", + argArray[i], "\"", (char *) NULL); + goto procError; + } + if ((fieldCount == 0) || (*fieldValues[0] == 0)) { + ckfree((char *) fieldValues); + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "procedure \"", procName, + "\" has argument with no name", (char *) 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 == '(') { + char *q = p; + do { + q++; + } while (*q != '\0'); + q--; + if (*q == ')') { /* we have an array element */ + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "procedure \"", procName, + "\" has formal parameter \"", fieldValues[0], + "\" that is an array element", + (char *) NULL); + ckfree((char *) fieldValues); + goto procError; + } + } + p++; + } + + if (precompiled) { + /* + * compare the parsed argument with the stored one + */ + + if ((localPtr->nameLength != nameLength) + || (strcmp(localPtr->name, fieldValues[0])) + || (localPtr->frameIndex != i) + || (localPtr->flags != (VAR_SCALAR | VAR_ARGUMENT)) + || ((localPtr->defValuePtr == NULL) + && (fieldCount == 2)) + || ((localPtr->defValuePtr != NULL) + && (fieldCount != 2))) { + char buf[128]; + sprintf(buf, "\": formal parameter %d is inconsistent with precompiled body", + i); + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "procedure \"", procName, + buf, (char *) NULL); + ckfree((char *) fieldValues); + goto procError; + } + + /* + * compare the default value if any + */ + + if (localPtr->defValuePtr != NULL) { + int tmpLength; + char *tmpPtr = Tcl_GetStringFromObj(localPtr->defValuePtr, + &tmpLength); + if ((valueLength != tmpLength) + || (strncmp(fieldValues[1], tmpPtr, + (size_t) tmpLength))) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "procedure \"", procName, + "\": formal parameter \"", + fieldValues[0], + "\" has default value inconsistent with precompiled body", + (char *) NULL); + ckfree((char *) fieldValues); + goto procError; + } + } + + localPtr = localPtr->nextPtr; + } else { + /* + * Allocate an entry in the runtime procedure frame's array of + * local variables for the argument. + */ + + localPtr = (CompiledLocal *) ckalloc((unsigned) + (sizeof(CompiledLocal) - sizeof(localPtr->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_SCALAR | VAR_ARGUMENT; + localPtr->resolveInfo = NULL; + if (fieldCount == 2) { + localPtr->defValuePtr = + Tcl_NewStringObj(fieldValues[1], valueLength); + Tcl_IncrRefCount(localPtr->defValuePtr); + } else { + localPtr->defValuePtr = NULL; + } + strcpy(localPtr->name, fieldValues[0]); + } + + ckfree((char *) fieldValues); + } + + /* + * 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. + */ + + *procPtrPtr = procPtr; ckfree((char *) argArray); return TCL_OK; - procError: - Tcl_DecrRefCount(bodyPtr); - while (procPtr->firstLocalPtr != NULL) { - localPtr = procPtr->firstLocalPtr; - procPtr->firstLocalPtr = localPtr->nextPtr; - - defPtr = localPtr->defValuePtr; - if (defPtr != NULL) { - Tcl_DecrRefCount(defPtr); - } - - ckfree((char *) localPtr); - } - ckfree((char *) procPtr); +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((char *) localPtr); + } + ckfree((char *) procPtr); + } if (argArray != NULL) { ckfree((char *) argArray); } return TCL_ERROR; } @@ -304,12 +461,12 @@ * 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 interp->result). + * 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 @@ -346,11 +503,11 @@ levelError: Tcl_AppendResult(interp, "bad level \"", string, "\"", (char *) NULL); return -1; } - } else if (isdigit(UCHAR(*string))) { + } else if (isdigit(UCHAR(*string))) { /* INTL: digit */ if (Tcl_GetInt(interp, string, &level) != TCL_OK) { return -1; } level = curLevel - level; } else { @@ -405,11 +562,11 @@ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { register Interp *iPtr = (Interp *) interp; char *optLevel; - int length, result; + int result; CallFrame *savedVarFramePtr, *framePtr; if (objc < 2) { uplevelSyntax: Tcl_WrongNumArgs(interp, 1, objv, "?level? command ?arg ...?"); @@ -416,14 +573,13 @@ return TCL_ERROR; } /* * Find the level to use for executing the command. - * THIS FAILS IF THE OBJECT RESULT'S STRING REP CONTAINS A NULL. */ - optLevel = Tcl_GetStringFromObj(objv[1], &length); + optLevel = TclGetString(objv[1]); result = TclGetFrame(interp, optLevel, &framePtr); if (result == -1) { return TCL_ERROR; } objc -= (result+1); @@ -442,18 +598,19 @@ /* * Execute the residual arguments as a command. */ if (objc == 1) { - result = Tcl_EvalObj(interp, objv[0]); + result = Tcl_EvalObjEx(interp, objv[0], 0); } else { - Tcl_Obj *cmdObjPtr = Tcl_ConcatObj(objc, objv); - result = Tcl_EvalObj(interp, cmdObjPtr); - Tcl_DecrRefCount(cmdObjPtr); /* done with object */ + Tcl_Obj *objPtr; + + objPtr = Tcl_ConcatObj(objc, objv); + result = Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_DIRECT); } if (result == TCL_ERROR) { - char msg[60]; + char msg[32 + TCL_INTEGER_SPACE]; sprintf(msg, "\n (\"uplevel\" body line %d)", interp->errorLine); Tcl_AddObjErrorInfo(interp, msg, -1); } /* @@ -468,16 +625,21 @@ *---------------------------------------------------------------------- * * TclFindProc -- * * Given the name of a procedure, return a pointer to the - * record describing the procedure. + * 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. + * 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. * *---------------------------------------------------------------------- @@ -487,19 +649,25 @@ TclFindProc(iPtr, procName) Interp *iPtr; /* Interpreter in which to look. */ char *procName; /* Name of desired procedure. */ { Tcl_Command cmd; + Tcl_Command origCmd; Command *cmdPtr; - + cmd = Tcl_FindCommand((Tcl_Interp *) iPtr, procName, (Tcl_Namespace *) NULL, /*flags*/ 0); if (cmd == (Tcl_Command) NULL) { return NULL; } cmdPtr = (Command *) cmd; - if (cmdPtr->proc != InterpProc) { + + origCmd = TclGetOriginalCommand(cmd); + if (origCmd != NULL) { + cmdPtr = (Command *) origCmd; + } + if (cmdPtr->proc != TclProcInterpProc) { return NULL; } return (Proc *) cmdPtr->clientData; } @@ -509,11 +677,11 @@ * TclIsProc -- * * Tells whether a command is a Tcl procedure or not. * * Results: - * If the given command is actuall a Tcl procedure, the + * 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. @@ -523,20 +691,26 @@ Proc * TclIsProc(cmdPtr) Command *cmdPtr; /* Command to test. */ { - if (cmdPtr->proc == InterpProc) { + Tcl_Command origCmd; + + origCmd = TclGetOriginalCommand((Tcl_Command) cmdPtr); + if (origCmd != NULL) { + cmdPtr = (Command *) origCmd; + } + if (cmdPtr->proc == TclProcInterpProc) { return (Proc *) cmdPtr->clientData; } return (Proc *) 0; } /* *---------------------------------------------------------------------- * - * InterpProc -- + * TclProcInterpProc -- * * When a Tcl procedure gets invoked with an argc/argv array of * strings, this routine gets invoked to interpret the procedure. * * Results: @@ -546,12 +720,12 @@ * Depends on the commands in the procedure. * *---------------------------------------------------------------------- */ -static int -InterpProc(clientData, interp, argc, argv) +int +TclProcInterpProc(clientData, interp, argc, argv) ClientData clientData; /* Record describing procedure to be * interpreted. */ Tcl_Interp *interp; /* Interpreter in which procedure was * invoked. */ int argc; /* Count of number of arguments to this @@ -596,15 +770,13 @@ result = TclObjInterpProc(clientData, interp, argc, objv); /* * Move the interpreter's object result to the string result, * then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS. */ - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL), + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), TCL_VOLATILE); /* * Decrement the ref counts on the objv elements since we are done * with them. @@ -643,28 +815,27 @@ *---------------------------------------------------------------------- */ int TclObjInterpProc(clientData, interp, objc, objv) - ClientData clientData; /* Record describing procedure to be - * interpreted. */ - 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. */ + 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. */ { Interp *iPtr = (Interp *) interp; - Proc *procPtr = (Proc *) clientData; - Tcl_Obj *bodyPtr = procPtr->bodyPtr; + register Proc *procPtr = (Proc *) clientData; + Namespace *nsPtr = procPtr->cmdPtr->nsPtr; CallFrame frame; register CallFrame *framePtr = &frame; register Var *varPtr; register CompiledLocal *localPtr; - Proc *saveProcPtr; - char *procName, *bytes; - int nameLen, localCt, numArgs, argCt, length, i, result; + char *procName; + int nameLen, localCt, numArgs, argCt, i, result; /* * This procedure generates an array "compiledLocals" that holds the * storage for local variables. It starts out with stack-allocated space * but uses dynamically-allocated storage if needed. @@ -674,75 +845,27 @@ Var localStorage[NUM_LOCALS]; Var *compiledLocals = localStorage; /* * Get the procedure's name. - * THIS FAILS IF THE PROC NAME'S STRING REP HAS A NULL. */ procName = Tcl_GetStringFromObj(objv[0], &nameLen); /* * 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. - */ - - if (bodyPtr->typePtr == &tclByteCodeType) { - ByteCode *codePtr = (ByteCode *) bodyPtr->internalRep.otherValuePtr; - - if ((codePtr->iPtr != iPtr) - || (codePtr->compileEpoch != iPtr->compileEpoch)) { - tclByteCodeType.freeIntRepProc(bodyPtr); - bodyPtr->typePtr = (Tcl_ObjType *) NULL; - } - } - if (bodyPtr->typePtr != &tclByteCodeType) { - char buf[100]; - int numChars; - char *ellipsis; - - if (tclTraceCompile >= 1) { - /* - * Display a line summarizing the top level command we - * are about to compile. - */ - - numChars = nameLen; - ellipsis = ""; - if (numChars > 50) { - numChars = 50; - ellipsis = "..."; - } - fprintf(stdout, "Compiling body of proc \"%.*s%s\"\n", - numChars, procName, ellipsis); - } - - saveProcPtr = iPtr->compiledProcPtr; - iPtr->compiledProcPtr = procPtr; - result = tclByteCodeType.setFromAnyProc(interp, bodyPtr); - iPtr->compiledProcPtr = saveProcPtr; - - if (result != TCL_OK) { - if (result == TCL_ERROR) { - numChars = nameLen; - ellipsis = ""; - if (numChars > 50) { - numChars = 50; - ellipsis = "..."; - } - sprintf(buf, "\n (compiling body of proc \"%.*s%s\", line %d)", - numChars, procName, ellipsis, interp->errorLine); - Tcl_AddObjErrorInfo(interp, buf, -1); - } - return result; - } + * variables. Note that compiling the body might increase + * procPtr->numCompiledLocals if new local variables are found + * while compiling. + */ + + result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr, + "body of proc", procName); + + if (result != TCL_OK) { + return result; } /* * Create the "compiledLocals" array. Make sure it is large enough to * hold all the procedure's compiled local variables, including its @@ -761,39 +884,28 @@ * that of its command, which can change if the command is renamed * from one namespace to another. */ result = Tcl_PushCallFrame(interp, (Tcl_CallFrame *) framePtr, - (Tcl_Namespace *) procPtr->cmdPtr->nsPtr, - /*isProcCallFrame*/ 1); + (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 1); + if (result != TCL_OK) { return result; } framePtr->objc = objc; framePtr->objv = objv; /* ref counts for args are incremented below */ + + /* + * Initialize and resolve compiled variable references. + */ + framePtr->procPtr = procPtr; framePtr->numCompiledLocals = localCt; framePtr->compiledLocals = compiledLocals; - /* - * Initialize the array of local variables stored in the call frame. - */ - - varPtr = framePtr->compiledLocals; - for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; - localPtr = localPtr->nextPtr) { - varPtr->value.objPtr = NULL; - varPtr->name = localPtr->name; /* will be just '\0' if temp var */ - varPtr->nsPtr = NULL; - varPtr->hPtr = NULL; - varPtr->refCount = 0; - varPtr->tracePtr = NULL; - varPtr->searchPtr = NULL; - varPtr->flags = (localPtr->flags | VAR_UNDEFINED); - varPtr++; - } + TclInitCompiledLocals(interp, framePtr, nsPtr); /* * 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 @@ -803,16 +915,16 @@ numArgs = procPtr->numArgs; varPtr = framePtr->compiledLocals; localPtr = procPtr->firstLocalPtr; argCt = objc; for (i = 1, argCt -= 1; i <= numArgs; i++, argCt--) { - if (!localPtr->isArg) { + if (!TclIsVarArgument(localPtr)) { panic("TclObjInterpProc: local variable %s is not argument but should be", localPtr->name); return TCL_ERROR; } - if (localPtr->isTemp) { + if (TclIsVarTemporary(localPtr)) { panic("TclObjInterpProc: local variable %d is temporary but should be an argument", i); return TCL_ERROR; } /* @@ -843,21 +955,20 @@ * another reference to object. */ } else { Tcl_ResetResult(interp); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no value given for parameter \"", localPtr->name, - "\" to \"", Tcl_GetStringFromObj(objv[0], (int *) NULL), - "\"", (char *) NULL); + "\" to \"", Tcl_GetString(objv[0]), "\"", (char *) NULL); result = TCL_ERROR; goto procDone; } varPtr++; localPtr = localPtr->nextPtr; } if (argCt > 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "called \"", Tcl_GetStringFromObj(objv[0], (int *) NULL), + "called \"", Tcl_GetString(objv[0]), "\" with too many arguments", (char *) NULL); result = TCL_ERROR; goto procDone; } @@ -864,61 +975,42 @@ /* * Invoke the commands in the procedure's body. */ if (tclTraceExec >= 1) { +#ifdef TCL_COMPILE_DEBUG fprintf(stdout, "Calling proc "); for (i = 0; i < objc; i++) { - bytes = Tcl_GetStringFromObj(objv[i], &length); - TclPrintSource(stdout, bytes, TclMin(length, 15)); + TclPrintObject(stdout, objv[i], 15); fprintf(stdout, " "); } fprintf(stdout, "\n"); +#else /* TCL_COMPILE_DEBUG */ + fprintf(stdout, "Calling proc %.*s\n", nameLen, procName); +#endif /*TCL_COMPILE_DEBUG*/ fflush(stdout); } iPtr->returnCode = TCL_OK; procPtr->refCount++; - result = Tcl_EvalObj(interp, procPtr->bodyPtr); + result = Tcl_EvalObjEx(interp, procPtr->bodyPtr, 0); procPtr->refCount--; if (procPtr->refCount <= 0) { - CleanupProc(procPtr); + TclProcCleanupProc(procPtr); } if (result != TCL_OK) { - if (result == TCL_RETURN) { - result = TclUpdateReturnInfo(iPtr); - } else if (result == TCL_ERROR) { - char msg[100]; - sprintf(msg, "\n (procedure \"%.50s\" line %d)", - procName, iPtr->errorLine); - Tcl_AddObjErrorInfo(interp, msg, -1); - } else if (result == TCL_BREAK) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "invoked \"break\" outside of a loop", -1); - result = TCL_ERROR; - } else if (result == TCL_CONTINUE) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "invoked \"continue\" outside of a loop", -1); - result = TCL_ERROR; - } - } + result = ProcessProcResultCode(interp, procName, nameLen, result); + } + + /* + * Pop and free the call frame for this procedure invocation, then + * free the compiledLocals array if malloc'ed storage was used. + */ procDone: - - /* - * Pop and free the call frame for this procedure invocation. - */ - Tcl_PopCallFrame(interp); - - /* - * Free the compiledLocals array if malloc'ed storage was used. - */ - if (compiledLocals != localStorage) { ckfree((char *) compiledLocals); } return result; #undef NUM_LOCALS @@ -925,11 +1017,218 @@ } /* *---------------------------------------------------------------------- * - * ProcDeleteProc -- + * 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 procedure does nothing. + * + * Results: + * None. + * + * Side effects: + * May change the internal representation of the body object + * to compiled code. + * + *---------------------------------------------------------------------- + */ + +int +TclProcCompileProc(interp, procPtr, bodyPtr, nsPtr, description, procName) + 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; + int result; + Tcl_CallFrame frame; + Proc *saveProcPtr; + ByteCode *codePtr = (ByteCode *) bodyPtr->internalRep.otherValuePtr; + + /* + * 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)) { + if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) { + if ((Interp *) *codePtr->interpHandle != iPtr) { + Tcl_AppendResult(interp, + "a precompiled script jumped interps", NULL); + return TCL_ERROR; + } + codePtr->compileEpoch = iPtr->compileEpoch; + codePtr->nsPtr = nsPtr; + } else { + (*tclByteCodeType.freeIntRepProc)(bodyPtr); + bodyPtr->typePtr = (Tcl_ObjType *) NULL; + } + } + } + if (bodyPtr->typePtr != &tclByteCodeType) { + char buf[100]; + int numChars; + char *ellipsis; + + if (tclTraceCompile >= 1) { + /* + * Display a line summarizing the top level command we + * are about to compile. + */ + + numChars = strlen(procName); + ellipsis = ""; + if (numChars > 50) { + numChars = 50; + ellipsis = "..."; + } + fprintf(stdout, "Compiling %s \"%.*s%s\"\n", + description, numChars, procName, ellipsis); + } + + /* + * 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. + */ + + saveProcPtr = iPtr->compiledProcPtr; + iPtr->compiledProcPtr = procPtr; + + result = Tcl_PushCallFrame(interp, &frame, + (Tcl_Namespace*)nsPtr, /* isProcCallFrame */ 0); + + if (result == TCL_OK) { + result = tclByteCodeType.setFromAnyProc(interp, bodyPtr); + Tcl_PopCallFrame(interp); + } + + iPtr->compiledProcPtr = saveProcPtr; + + if (result != TCL_OK) { + if (result == TCL_ERROR) { + numChars = strlen(procName); + ellipsis = ""; + if (numChars > 50) { + numChars = 50; + ellipsis = "..."; + } + sprintf(buf, "\n (compiling %s \"%.*s%s\", line %d)", + description, numChars, procName, ellipsis, + interp->errorLine); + Tcl_AddObjErrorInfo(interp, buf, -1); + } + return result; + } + } else if (codePtr->nsEpoch != nsPtr->resolverEpoch) { + register CompiledLocal *localPtr; + + /* + * The resolver epoch has changed, but we only need to invalidate + * the resolver cache. + */ + + for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; + localPtr = localPtr->nextPtr) { + localPtr->flags &= ~(VAR_RESOLVED); + if (localPtr->resolveInfo) { + if (localPtr->resolveInfo->deleteProc) { + localPtr->resolveInfo->deleteProc(localPtr->resolveInfo); + } else { + ckfree((char*)localPtr->resolveInfo); + } + localPtr->resolveInfo = NULL; + } + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ProcessProcResultCode -- + * + * Procedure called by TclObjInterpProc to process a return code other + * than TCL_OK returned by a Tcl procedure. + * + * Results: + * Depending on the argument return code, the result returned is + * another return code and the interpreter's result is set to a value + * to supplement that return code. + * + * Side effects: + * If the result returned is TCL_ERROR, traceback information about + * the procedure just executed is appended to the interpreter's + * "errorInfo" variable. + * + *---------------------------------------------------------------------- + */ + +static int +ProcessProcResultCode(interp, procName, nameLen, returnCode) + Tcl_Interp *interp; /* The interpreter in which the procedure + * was called and returned returnCode. */ + char *procName; /* Name of the procedure. Used for error + * messages and trace information. */ + int nameLen; /* Number of bytes in procedure's name. */ + int returnCode; /* The unexpected result code. */ +{ + Interp *iPtr = (Interp *) interp; + char msg[100 + TCL_INTEGER_SPACE]; + + if (returnCode == TCL_RETURN) { + returnCode = TclUpdateReturnInfo(iPtr); + } else if (returnCode == TCL_ERROR) { + sprintf(msg, "\n (procedure \"%.*s\" line %d)", + nameLen, procName, iPtr->errorLine); + Tcl_AddObjErrorInfo(interp, msg, -1); + } else if (returnCode == TCL_BREAK) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "invoked \"break\" outside of a loop", -1); + returnCode = TCL_ERROR; + } else if (returnCode == TCL_CONTINUE) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "invoked \"continue\" outside of a loop", -1); + returnCode = TCL_ERROR; + } + return returnCode; +} + +/* + *---------------------------------------------------------------------- + * + * TclProcDeleteProc -- * * This procedure is invoked just before a command procedure is * removed from an interpreter. Its job is to release all the * resources allocated to the procedure. * @@ -942,26 +1241,26 @@ * last call to the current procedure completes. * *---------------------------------------------------------------------- */ -static void -ProcDeleteProc(clientData) +void +TclProcDeleteProc(clientData) ClientData clientData; /* Procedure to be deleted. */ { Proc *procPtr = (Proc *) clientData; procPtr->refCount--; if (procPtr->refCount <= 0) { - CleanupProc(procPtr); + TclProcCleanupProc(procPtr); } } /* *---------------------------------------------------------------------- * - * CleanupProc -- + * TclProcCleanupProc -- * * This procedure does all the real work of freeing up a Proc * structure. It's called only when the structure's reference * count becomes zero. * @@ -972,23 +1271,33 @@ * Memory gets freed. * *---------------------------------------------------------------------- */ -static void -CleanupProc(procPtr) +void +TclProcCleanupProc(procPtr) register Proc *procPtr; /* Procedure to be deleted. */ { register CompiledLocal *localPtr; Tcl_Obj *bodyPtr = procPtr->bodyPtr; Tcl_Obj *defPtr; + Tcl_ResolvedVarInfo *resVarInfo; 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((char *) resVarInfo); + } + } if (localPtr->defValuePtr != NULL) { defPtr = localPtr->defValuePtr; Tcl_DecrRefCount(defPtr); } @@ -1038,5 +1347,211 @@ iPtr->flags |= ERR_IN_PROGRESS; } } return code; } + +/* + *---------------------------------------------------------------------- + * + * TclGetInterpProc -- + * + * Returns a pointer to the TclProcInterpProc procedure; this is different + * from the value obtained from the TclProcInterpProc reference on systems + * like Windows where import and export versions of a procedure exported + * by a DLL exist. + * + * Results: + * Returns the internal address of the TclProcInterpProc procedure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TclCmdProcType +TclGetInterpProc() +{ + return (TclCmdProcType) TclProcInterpProc; +} + +/* + *---------------------------------------------------------------------- + * + * TclGetObjInterpProc -- + * + * Returns a pointer to the TclObjInterpProc procedure; this is different + * from the value obtained from the TclObjInterpProc reference on systems + * like Windows where import and export versions of a procedure exported + * by a DLL exist. + * + * Results: + * Returns the internal address of the TclObjInterpProc procedure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TclObjCmdProcType +TclGetObjInterpProc() +{ + 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, 0 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(procPtr) + Proc *procPtr; /* the Proc struct to store as the internal + * representation. */ +{ + Tcl_Obj *objPtr; + + if (!procPtr) { + return (Tcl_Obj *) NULL; + } + + objPtr = Tcl_NewStringObj("", 0); + + if (objPtr) { + objPtr->typePtr = &tclProcBodyType; + objPtr->internalRep.otherValuePtr = (VOID *) 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(srcPtr, dupPtr) + Tcl_Obj *srcPtr; /* object to copy */ + Tcl_Obj *dupPtr; /* target object for the duplication */ +{ + Proc *procPtr = (Proc *) srcPtr->internalRep.otherValuePtr; + + dupPtr->typePtr = &tclProcBodyType; + dupPtr->internalRep.otherValuePtr = (VOID *) 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(objPtr) + Tcl_Obj *objPtr; /* the object to clean up */ +{ + Proc *procPtr = (Proc *) objPtr->internalRep.otherValuePtr; + procPtr->refCount--; + if (procPtr->refCount <= 0) { + TclProcCleanupProc(procPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * ProcBodySetFromAny -- + * + * Tcl_ObjType's SetFromAny function for the proc body object. + * Calls panic. + * + * Results: + * Theoretically returns a TCL result code. + * + * Side effects: + * Calls panic, since we can't set the value of the object from a string + * representation (or any other internal ones). + * + *---------------------------------------------------------------------- + */ + +static int +ProcBodySetFromAny(interp, objPtr) + Tcl_Interp *interp; /* current interpreter */ + Tcl_Obj *objPtr; /* object pointer */ +{ + panic("called ProcBodySetFromAny"); + + /* + * this to keep compilers happy. + */ + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ProcBodyUpdateString -- + * + * Tcl_ObjType's UpdateString function for the proc body object. + * Calls panic. + * + * Results: + * None. + * + * Side effects: + * Calls panic, since we this type has no string representation. + * + *---------------------------------------------------------------------- + */ + +static void +ProcBodyUpdateString(objPtr) + Tcl_Obj *objPtr; /* the object to update */ +{ + panic("called ProcBodyUpdateString"); +} ADDED generic/tclRegexp.c Index: generic/tclRegexp.c ================================================================== --- /dev/null +++ generic/tclRegexp.c @@ -0,0 +1,792 @@ +/* + * 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. + * + * RCS: @(#) $Id: tclRegexp.c,v 1.1.2.9 1999/04/14 00:33:26 surles Exp $ + */ + +#include "tclInt.h" +#include "tclPort.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. *** + */ + +/* + * Declarations for functions used only in this file. + */ + +static void DupRegexpInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, + Tcl_Obj *copyPtr)); +static void FreeRegexpInternalRep _ANSI_ARGS_((Tcl_Obj *regexpPtr)); +static int SetRegexpFromAny _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *objPtr)); +static TclRegexp * CompileRegexp _ANSI_ARGS_((Tcl_Interp *interp, + char *pattern, int length, int flags)); + +/* + * The regular expression Tcl object type. This serves as a cache + * of the compiled form of the regular expression. + */ + +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 procedure 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 procedure, 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(interp, string) + Tcl_Interp *interp; /* For use in error reporting. */ + char *string; /* String for which to produce + * compiled regular expression. */ +{ + Interp *iPtr = (Interp *) interp; + int i, length; + TclRegexp *result; + + length = strlen(string); + for (i = 0; i < NUM_REGEXPS; i++) { + if ((length == iPtr->patLengths[i]) + && (strcmp(string, iPtr->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 = iPtr->patterns[i]; + result = iPtr->regexps[i]; + for (j = i-1; j >= 0; j--) { + iPtr->patterns[j+1] = iPtr->patterns[j]; + iPtr->patLengths[j+1] = iPtr->patLengths[j]; + iPtr->regexps[j+1] = iPtr->regexps[j]; + } + iPtr->patterns[0] = cachedString; + iPtr->patLengths[0] = length; + iPtr->regexps[0] = result; + } + return (Tcl_RegExp) iPtr->regexps[0]; + } + } + + /* + * No match in the cache. Compile the string and add it to the + * cache. + */ + + result = CompileRegexp(interp, string, length, REG_ADVANCED); + if (!result) { + return NULL; + } + + /* + * We successfully compiled the expression, so add it to the cache. + */ + + if (iPtr->patterns[NUM_REGEXPS-1] != NULL) { + ckfree(iPtr->patterns[NUM_REGEXPS-1]); + TclReFree(&(iPtr->regexps[NUM_REGEXPS-1]->re)); + ckfree((char *) iPtr->regexps[NUM_REGEXPS-1]); + } + for (i = NUM_REGEXPS - 2; i >= 0; i--) { + iPtr->patterns[i+1] = iPtr->patterns[i]; + iPtr->patLengths[i+1] = iPtr->patLengths[i]; + iPtr->regexps[i+1] = iPtr->regexps[i]; + } + iPtr->patterns[0] = (char *) ckalloc((unsigned) (length+1)); + strcpy(iPtr->patterns[0], string); + iPtr->patLengths[0] = length; + iPtr->regexps[0] = result; + return (Tcl_RegExp) result; +} + +/* + *---------------------------------------------------------------------- + * + * 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(interp, re, string, start) + 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 *string; /* String against which to match re. */ + CONST char *start; /* If string is part of a larger string, + * this identifies beginning of larger + * string, so that "^" won't match. */ +{ + int result, numChars; + Tcl_DString stringBuffer; + Tcl_UniChar *uniString; + + TclRegexp *regexpPtr = (TclRegexp *) re; + + /* + * Remember the UTF-8 string so Tcl_RegExpRange() can convert the + * matches from character to byte offsets. + */ + + regexpPtr->string = string; + + Tcl_DStringInit(&stringBuffer); + uniString = Tcl_UtfToUniCharDString(string, -1, &stringBuffer); + numChars = Tcl_DStringLength(&stringBuffer) / sizeof(Tcl_UniChar); + + /* + * Perform the regexp match. + */ + + result = TclRegExpExecUniChar(interp, re, uniString, numChars, -1, + ((string > start) ? REG_NOTBOL : 0)); + + Tcl_DStringFree(&stringBuffer); + + 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(re, index, startPtr, endPtr) + 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. */ + char **startPtr; /* Store address of first character in + * (sub-) range here. */ + char **endPtr; /* Store address of character just after last + * in (sub-) range here. */ +{ + TclRegexp *regexpPtr = (TclRegexp *) re; + + if ((size_t) index > regexpPtr->re.re_nsub) { + *startPtr = *endPtr = NULL; + } else if (regexpPtr->matches[index].rm_so < 0) { + *startPtr = *endPtr = NULL; + } else { + *startPtr = Tcl_UtfAtIndex(regexpPtr->string, + regexpPtr->matches[index].rm_so); + *endPtr = Tcl_UtfAtIndex(regexpPtr->string, + regexpPtr->matches[index].rm_eo); + } +} + +/* + *--------------------------------------------------------------------------- + * + * TclRegExpExecUniChar -- + * + * 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. + * + *---------------------------------------------------------------------- + */ + +int +TclRegExpExecUniChar(interp, re, wString, numChars, nmatches, flags) + 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 nm = regexpPtr->re.re_nsub + 1; + + if (nmatches >= 0 && (size_t) nmatches < nm) + nm = (size_t) nmatches; + + status = TclReExec(®expPtr->re, wString, (size_t) numChars, + (rm_detail_t *)NULL, 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. + * + * 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 +TclRegExpRangeUniChar(re, index, startPtr, endPtr) + 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. */ + 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 ((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 "string" matches "pattern" + * and 0 otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_RegExpMatch(interp, string, pattern) + Tcl_Interp *interp; /* Used for error reporting. */ + char *string; /* String. */ + char *pattern; /* Regular expression to match against + * string. */ +{ + Tcl_RegExp re; + + re = Tcl_RegExpCompile(interp, pattern); + if (re == NULL) { + return -1; + } + return Tcl_RegExpExec(interp, re, string, string); +} + +/* + *---------------------------------------------------------------------- + * + * TclRegExpMatchObj -- + * + * See if a string matches a regular expression pattern 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: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TclRegExpMatchObj(interp, string, patObj) + Tcl_Interp *interp; /* Used for error reporting. */ + char *string; /* String. */ + Tcl_Obj *patObj; /* Regular expression to match against + * string. */ +{ + Tcl_RegExp re; + + re = Tcl_GetRegExpFromObj(interp, patObj, REG_ADVANCED); + if (re == NULL) { + return -1; + } + return Tcl_RegExpExec(interp, re, string, string); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_GetRegExpFromObj -- + * + * Compile a regular expression into a form suitable for fast + * matching. This procedure 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(interp, objPtr, flags) + Tcl_Interp *interp; /* For use in error reporting. */ + 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; + Tcl_ObjType *typePtr; + TclRegexp *regexpPtr; + char *pattern; + + typePtr = objPtr->typePtr; + regexpPtr = (TclRegexp *) objPtr->internalRep.otherValuePtr; + + if ((typePtr != &tclRegexpType) || (regexpPtr->flags != flags)) { + pattern = Tcl_GetStringFromObj(objPtr, &length); + regexpPtr = CompileRegexp(interp, pattern, length, flags); + if (regexpPtr == NULL) { + return NULL; + } + + /* + * Free the old representation and set our type. + */ + + if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { + (*typePtr->freeIntRepProc)(objPtr); + } + objPtr->internalRep.otherValuePtr = (VOID *) 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(interp, re) + Tcl_Interp *interp; /* For use in variable assignment. */ + Tcl_RegExp re; /* The compiled regular expression. */ +{ + TclRegexp *regexpPtr = (TclRegexp *)re; + char buf[TCL_INTEGER_SPACE]; + static struct infoname { + int bit; + char *text; + } 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"}, + {0, ""} + }; + struct infoname *inf; + int n; + + Tcl_ResetResult(interp); + + sprintf(buf, "%u", (unsigned)(regexpPtr->re.re_nsub)); + Tcl_AppendElement(interp, buf); + + /* + * Must count bits before generating list, because we must know + * whether {} are needed before we start appending names. + */ + n = 0; + for (inf = infonames; inf->bit != 0; inf++) { + if (regexpPtr->re.re_info&inf->bit) { + n++; + } + } + if (n != 1) { + Tcl_AppendResult(interp, " {", NULL); + } + for (inf = infonames; inf->bit != 0; inf++) { + if (regexpPtr->re.re_info&inf->bit) { + Tcl_AppendElement(interp, inf->text); + } + } + if (n != 1) { + Tcl_AppendResult(interp, "}", NULL); + } + + 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(interp, msg, status) + Tcl_Interp *interp; /* Interpreter for error reporting. */ + char *msg; /* Message to prepend to error. */ + int status; /* Status code to report. */ +{ + char buf[100]; /* ample in practice */ + char cbuf[100]; /* lots in practice */ + size_t n; + char *p; + + Tcl_ResetResult(interp); + n = TclReError(status, (regex_t *)NULL, buf, sizeof(buf)); + p = (n > sizeof(buf)) ? "..." : ""; + Tcl_AppendResult(interp, msg, buf, p, NULL); + + sprintf(cbuf, "%d", status); + (VOID) TclReError(REG_ITOA, (regex_t *)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(objPtr) + Tcl_Obj *objPtr; /* Regexp object with internal rep to free. */ +{ + TclRegexp *regexpRepPtr = (TclRegexp *) objPtr->internalRep.otherValuePtr; + + TclReFree(®expRepPtr->re); + if (regexpRepPtr->matches) { + ckfree((char *) regexpRepPtr->matches); + } + ckfree((char *) regexpRepPtr); +} + +/* + *---------------------------------------------------------------------- + * + * DupRegexpInternalRep -- + * + * It is way too hairy to copy a regular expression, so we punt + * and revert the object back to a vanilla string. + * + * Results: + * None. + * + * Side effects: + * Changes the type back to string. + * + *---------------------------------------------------------------------- + */ + +static void +DupRegexpInternalRep(srcPtr, copyPtr) + Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ + Tcl_Obj *copyPtr; /* Object with internal rep to set. */ +{ + copyPtr->internalRep.longValue = (long)copyPtr->length; + copyPtr->typePtr = &tclStringType; +} + +/* + *---------------------------------------------------------------------- + * + * 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(interp, objPtr) + 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 + * + * 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: + * Memory allocated. + * + *---------------------------------------------------------------------- + */ + +static TclRegexp * +CompileRegexp(interp, string, length, flags) + Tcl_Interp *interp; /* Used for error reporting if not NULL. */ + char *string; /* The regexp to compile (UTF-8). */ + int length; /* The length of the string in bytes. */ + int flags; /* Compilation flags. */ +{ + TclRegexp *regexpPtr; + Tcl_UniChar *uniString; + int numChars; + Tcl_DString stringBuf; + int status; + + regexpPtr = (TclRegexp *) ckalloc(sizeof(TclRegexp)); + + /* + * 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((char *)regexpPtr); + if (interp) { + TclRegError(interp, + "couldn't compile regular expression pattern: ", + status); + } + return NULL; + } + + /* + * Allocate enough space for all of the subexpressions, plus one + * extra for the entire pattern. + */ + + regexpPtr->matches = (regmatch_t *) ckalloc( + sizeof(regmatch_t) * (regexpPtr->re.re_nsub + 1)); + + return regexpPtr; +} Index: generic/tclRegexp.h ================================================================== --- generic/tclRegexp.h +++ generic/tclRegexp.h @@ -1,40 +1,92 @@ -/* - * Definitions etc. for regexp(3) routines. +/* + * tclRegexp.h -- + * + * This file contains definitions used internally by Henry + * Spencer's regular expression code. + * + * 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. + * + * 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. + * + * Copyright (c) 1998 by Sun Microsystems, Inc. + * Copyright (c) 1998-1999 by Scriptics Corporation. * - * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], - * not the System V one. + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclRegexp.h 1.6 96/04/02 18:43:57 + * RCS: @(#) $Id: tclRegexp.h,v 1.1.2.5 1999/04/05 22:20:31 rjohnson Exp $ */ -#ifndef _REGEXP -#define _REGEXP 1 +#ifndef _TCLREGEXP +#define _TCLREGEXP + +#include "regex.h" -#ifndef _TCL -#include "tcl.h" +#ifdef BUILD_tcl +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT #endif /* - * NSUBEXP must be at least 10, and no greater than 117 or the parser - * will not work properly. + * 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. + */ + +typedef struct TclRegexp { + int flags; /* Regexp compile flags. */ + regex_t re; /* Compiled re, includes number of + * subexpressions. */ + CONST char *string; /* Last string matched with this regexp + * (UTF-8), so Tcl_RegExpRange() can convert + * the matches from character indices to UTF-8 + * byte offsets. */ + 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. */ +} TclRegexp; + +/* + * Functions exported for use within the rest of Tcl. + */ + +EXTERN int TclRegAbout _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_RegExp re)); +EXTERN VOID TclRegXflags _ANSI_ARGS_((char *string, int length, + int *cflagsPtr, int *eflagsPtr)); +EXTERN int TclRegExpExecUniChar _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_RegExp re, CONST Tcl_UniChar *uniString, + int numChars, int nmatches, int flags)); +EXTERN int TclRegExpMatchObj _ANSI_ARGS_((Tcl_Interp *interp, + char *string, Tcl_Obj *patObj)); +EXTERN void TclRegExpRangeUniChar _ANSI_ARGS_((Tcl_RegExp re, + int index, int *startPtr, int *endPtr)); + +/* + * Functions exported from the regexp package for the test package to use. */ -#define NSUBEXP 20 - -typedef struct regexp { - char *startp[NSUBEXP]; - char *endp[NSUBEXP]; - char regstart; /* Internal use only. */ - char reganch; /* Internal use only. */ - char *regmust; /* Internal use only. */ - int regmlen; /* Internal use only. */ - char program[1]; /* Unwarranted chumminess with compiler. */ -} regexp; - -EXTERN regexp *TclRegComp _ANSI_ARGS_((char *exp)); -EXTERN int TclRegExec _ANSI_ARGS_((regexp *prog, char *string, char *start)); -EXTERN void TclRegSub _ANSI_ARGS_((regexp *prog, char *source, char *dest)); -EXTERN void TclRegError _ANSI_ARGS_((char *msg)); -EXTERN char *TclGetRegError _ANSI_ARGS_((void)); - -#endif /* REGEXP */ +EXTERN void TclRegError _ANSI_ARGS_((Tcl_Interp *interp, char *msg, + int status)); + +#endif /* _TCLREGEXP */ ADDED generic/tclResolve.c Index: generic/tclResolve.c ================================================================== --- /dev/null +++ generic/tclResolve.c @@ -0,0 +1,418 @@ +/* + * 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. + * + * RCS: @(#) $Id: tclResolve.c,v 1.1.2.2 1998/11/11 04:08:22 stanton Exp $ + */ + +#include "tclInt.h" + +/* + * Declarations for procedures local to this file: + */ + +static void BumpCmdRefEpochs _ANSI_ARGS_((Namespace *nsPtr)); + + +/* + *---------------------------------------------------------------------- + * + * Tcl_AddInterpResolvers -- + * + * Adds a set of command/variable resolution procedures to an + * interpreter. These procedures are consulted when commands + * are resolved in Tcl_FindCommand, and when variables are + * resolved in TclLookupVar and LookupCompiledLocal. Each + * namespace may also have its own set of resolution procedures + * which take precedence over those for the interpreter. + * + * When a name is resolved, it is handled as follows. First, + * the name is passed to the resolution procedures for the + * namespace. If not resolved, the name is passed to each of + * the resolution procedures added to the interpreter. Finally, + * if still not resolved, the name is handled using the default + * Tcl rules for name resolution. + * + * Results: + * Returns pointers to the current name resolution procedures + * in the cmdProcPtr, varProcPtr and compiledVarProcPtr + * arguments. + * + * Side effects: + * If a compiledVarProc is specified, this procedure bumps the + * compileEpoch for the interpreter, forcing all code to be + * recompiled. If a cmdProc is specified, this procedure bumps + * the cmdRefEpoch in all namespaces, forcing commands to be + * resolved again using the new rules. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_AddInterpResolvers(interp, name, cmdProc, varProc, compiledVarProc) + + Tcl_Interp *interp; /* Interpreter whose name resolution + * rules are being modified. */ + char *name; /* Name of this resolution scheme. */ + Tcl_ResolveCmdProc *cmdProc; /* New procedure for command + * resolution */ + Tcl_ResolveVarProc *varProc; /* Procedure for variable resolution + * at runtime */ + Tcl_ResolveCompiledVarProc *compiledVarProc; + /* Procedure for variable resolution + * at compile time. */ +{ + Interp *iPtr = (Interp*)interp; + ResolverScheme *resPtr; + + /* + * Since we're adding a new name resolution scheme, we must force + * all code to be recompiled to use the new scheme. If there + * are new compiled variable resolution rules, bump the compiler + * epoch to invalidate compiled code. If there are new command + * resolution rules, bump the cmdRefEpoch in all namespaces. + */ + if (compiledVarProc) { + iPtr->compileEpoch++; + } + if (cmdProc) { + BumpCmdRefEpochs(iPtr->globalNsPtr); + } + + /* + * Look for an existing scheme with the given name. If found, + * then replace its rules. + */ + for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) { + if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { + resPtr->cmdResProc = cmdProc; + resPtr->varResProc = varProc; + resPtr->compiledVarResProc = compiledVarProc; + return; + } + } + + /* + * Otherwise, this is a new scheme. Add it to the FRONT + * of the linked list, so that it overrides existing schemes. + */ + resPtr = (ResolverScheme *) ckalloc(sizeof(ResolverScheme)); + resPtr->name = (char*)ckalloc((unsigned)(strlen(name)+1)); + strcpy(resPtr->name, name); + resPtr->cmdResProc = cmdProc; + resPtr->varResProc = varProc; + resPtr->compiledVarResProc = compiledVarProc; + resPtr->nextPtr = iPtr->resolverPtr; + iPtr->resolverPtr = resPtr; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_GetInterpResolvers -- + * + * Looks for a set of command/variable resolution procedures with + * the given name in an interpreter. These procedures are + * registered by calling Tcl_AddInterpResolvers. + * + * Results: + * If the name is recognized, this procedure returns non-zero, + * along with pointers to the name resolution procedures in + * the Tcl_ResolverInfo structure. If the name is not recognized, + * this procedure returns zero. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_GetInterpResolvers(interp, name, resInfoPtr) + + Tcl_Interp *interp; /* Interpreter whose name resolution + * rules are being queried. */ + char *name; /* Look for a scheme with this name. */ + Tcl_ResolverInfo *resInfoPtr; /* Returns pointers to the procedures, + * if found */ +{ + Interp *iPtr = (Interp*)interp; + ResolverScheme *resPtr; + + /* + * Look for an existing scheme with the given name. If found, + * then return pointers to its procedures. + */ + for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) { + if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { + resInfoPtr->cmdResProc = resPtr->cmdResProc; + resInfoPtr->varResProc = resPtr->varResProc; + resInfoPtr->compiledVarResProc = resPtr->compiledVarResProc; + return 1; + } + } + + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_RemoveInterpResolvers -- + * + * Removes a set of command/variable resolution procedures + * previously added by Tcl_AddInterpResolvers. The next time + * a command/variable name is resolved, these procedures + * won't be consulted. + * + * Results: + * Returns non-zero if the name was recognized and the + * resolution scheme was deleted. Returns zero otherwise. + * + * Side effects: + * If a scheme with a compiledVarProc was deleted, this procedure + * bumps the compileEpoch for the interpreter, forcing all code + * to be recompiled. If a scheme with a cmdProc was deleted, + * this procedure bumps the cmdRefEpoch in all namespaces, + * forcing commands to be resolved again using the new rules. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_RemoveInterpResolvers(interp, name) + + Tcl_Interp *interp; /* Interpreter whose name resolution + * rules are being modified. */ + char *name; /* Name of the scheme to be removed. */ +{ + Interp *iPtr = (Interp*)interp; + ResolverScheme **prevPtrPtr, *resPtr; + + /* + * Look for an existing scheme with the given name. + */ + prevPtrPtr = &iPtr->resolverPtr; + for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) { + if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { + break; + } + prevPtrPtr = &resPtr->nextPtr; + } + + /* + * If we found the scheme, delete it. + */ + if (resPtr) { + /* + * If we're deleting a scheme with compiled variable resolution + * rules, bump the compiler epoch to invalidate compiled code. + * If we're deleting a scheme with command resolution rules, + * bump the cmdRefEpoch in all namespaces. + */ + if (resPtr->compiledVarResProc) { + iPtr->compileEpoch++; + } + if (resPtr->cmdResProc) { + BumpCmdRefEpochs(iPtr->globalNsPtr); + } + + *prevPtrPtr = resPtr->nextPtr; + ckfree(resPtr->name); + ckfree((char *) resPtr); + + return 1; + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * BumpCmdRefEpochs -- + * + * This procedure is used to bump the cmdRefEpoch counters in + * the specified namespace and all of its child namespaces. + * It is used whenever name resolution schemes are added/removed + * from an interpreter, to invalidate all command references. + * + * Results: + * None. + * + * Side effects: + * Bumps the cmdRefEpoch in the specified namespace and its + * children, recursively. + * + *---------------------------------------------------------------------- + */ + +static void +BumpCmdRefEpochs(nsPtr) + Namespace *nsPtr; /* Namespace being modified. */ +{ + Tcl_HashEntry *entry; + Tcl_HashSearch search; + Namespace *childNsPtr; + + nsPtr->cmdRefEpoch++; + + for (entry = Tcl_FirstHashEntry(&nsPtr->childTable, &search); + entry != NULL; + entry = Tcl_NextHashEntry(&search)) { + + childNsPtr = (Namespace *) Tcl_GetHashValue(entry); + BumpCmdRefEpochs(childNsPtr); + } +} + + +/* + *---------------------------------------------------------------------- + * + * Tcl_SetNamespaceResolvers -- + * + * Sets the command/variable resolution procedures for a namespace, + * thereby changing the way that command/variable names are + * interpreted. This allows extension writers to support different + * name resolution schemes, such as those for object-oriented + * packages. + * + * Command resolution is handled by a procedure of the following + * type: + * + * typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_(( + * Tcl_Interp* interp, char* name, Tcl_Namespace *context, + * int flags, Tcl_Command *rPtr)); + * + * Whenever a command is executed or Tcl_FindCommand is invoked + * within the namespace, this procedure is called to resolve the + * command name. If this procedure is able to resolve the name, + * it should return the status code TCL_OK, along with the + * corresponding Tcl_Command in the rPtr argument. Otherwise, + * the procedure can return TCL_CONTINUE, and the command will + * be treated under the usual name resolution rules. Or, it can + * return TCL_ERROR, and the command will be considered invalid. + * + * Variable resolution is handled by two procedures. The first + * is called whenever a variable needs to be resolved at compile + * time: + * + * typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_(( + * Tcl_Interp* interp, char* name, Tcl_Namespace *context, + * Tcl_ResolvedVarInfo *rPtr)); + * + * If this procedure is able to resolve the name, it should return + * the status code TCL_OK, along with variable resolution info in + * the rPtr argument; this info will be used to set up compiled + * locals in the call frame at runtime. The procedure may also + * return TCL_CONTINUE, and the variable will be treated under + * the usual name resolution rules. Or, it can return TCL_ERROR, + * and the variable will be considered invalid. + * + * Another procedure is used whenever a variable needs to be + * resolved at runtime but it is not recognized as a compiled local. + * (For example, the variable may be requested via + * Tcl_FindNamespaceVar.) This procedure has the following type: + * + * typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_(( + * Tcl_Interp* interp, char* name, Tcl_Namespace *context, + * int flags, Tcl_Var *rPtr)); + * + * This procedure is quite similar to the compile-time version. + * It returns the same status codes, but if variable resolution + * succeeds, this procedure returns a Tcl_Var directly via the + * rPtr argument. + * + * Results: + * Nothing. + * + * Side effects: + * Bumps the command epoch counter for the namespace, invalidating + * all command references in that namespace. Also bumps the + * resolver epoch counter for the namespace, forcing all code + * in the namespace to be recompiled. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_SetNamespaceResolvers(namespacePtr, cmdProc, varProc, compiledVarProc) + Tcl_Namespace *namespacePtr; /* Namespace whose resolution rules + * are being modified. */ + Tcl_ResolveCmdProc *cmdProc; /* Procedure for command resolution */ + Tcl_ResolveVarProc *varProc; /* Procedure for variable resolution + * at runtime */ + Tcl_ResolveCompiledVarProc *compiledVarProc; + /* Procedure for variable resolution + * at compile time. */ +{ + Namespace *nsPtr = (Namespace*)namespacePtr; + + /* + * Plug in the new command resolver, and bump the epoch counters + * so that all code will have to be recompiled and all commands + * will have to be resolved again using the new policy. + */ + nsPtr->cmdResProc = cmdProc; + nsPtr->varResProc = varProc; + nsPtr->compiledVarResProc = compiledVarProc; + + nsPtr->cmdRefEpoch++; + nsPtr->resolverEpoch++; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_GetNamespaceResolvers -- + * + * Returns the current command/variable resolution procedures + * for a namespace. By default, these procedures are NULL. + * New procedures can be installed by calling + * Tcl_SetNamespaceResolvers, to provide new name resolution + * rules. + * + * Results: + * Returns non-zero if any name resolution procedures have been + * assigned to this namespace; also returns pointers to the + * procedures in the Tcl_ResolverInfo structure. Returns zero + * otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_GetNamespaceResolvers(namespacePtr, resInfoPtr) + + Tcl_Namespace *namespacePtr; /* Namespace whose resolution rules + * are being modified. */ + Tcl_ResolverInfo *resInfoPtr; /* Returns: pointers for all + * name resolution procedures + * assigned to this namespace. */ +{ + Namespace *nsPtr = (Namespace*)namespacePtr; + + resInfoPtr->cmdResProc = nsPtr->cmdResProc; + resInfoPtr->varResProc = nsPtr->varResProc; + resInfoPtr->compiledVarResProc = nsPtr->compiledVarResProc; + + if (nsPtr->cmdResProc != NULL || + nsPtr->varResProc != NULL || + nsPtr->compiledVarResProc != NULL) { + return 1; + } + return 0; +} ADDED generic/tclResult.c Index: generic/tclResult.c ================================================================== --- /dev/null +++ generic/tclResult.c @@ -0,0 +1,1025 @@ +/* + * 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. + * + * RCS: @(#) $Id: tclResult.c,v 1.1.2.4 1999/03/10 06:49:21 stanton Exp $ + */ + +#include "tclInt.h" + +/* + * Function prototypes for local procedures in this file: + */ + +static void ResetObjResult _ANSI_ARGS_((Interp *iPtr)); +static void SetupAppendBuffer _ANSI_ARGS_((Interp *iPtr, + int newSpace)); + + +/* + *---------------------------------------------------------------------- + * + * 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. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_SaveResult(interp, statePtr) + 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. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_RestoreResult(interp, statePtr) + 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((char *)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 procedure must be called to discard it, + * or the memory will be lost. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_DiscardResult(statePtr) + Tcl_SavedResult *statePtr; /* State returned by Tcl_SaveResult. */ +{ + TclDecrRefCount(statePtr->objResultPtr); + + if (statePtr->result == statePtr->appendResult) { + ckfree(statePtr->appendResult); + } else if (statePtr->freeProc) { + if ((statePtr->freeProc == TCL_DYNAMIC) + || (statePtr->freeProc == (Tcl_FreeProc *) free)) { + ckfree(statePtr->result); + } else { + (*statePtr->freeProc)(statePtr->result); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_SetResult -- + * + * Arrange for "string" to be the Tcl return value. + * + * Results: + * None. + * + * Side effects: + * interp->result is left pointing either to "string" (if "copy" is 0) + * or to a copy of string. Also, the object result is reset. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_SetResult(interp, string, freeProc) + Tcl_Interp *interp; /* Interpreter with which to associate the + * return value. */ + register char *string; /* 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; + int length; + register Tcl_FreeProc *oldFreeProc = iPtr->freeProc; + char *oldResult = iPtr->result; + + if (string == NULL) { + iPtr->resultSpace[0] = 0; + iPtr->result = iPtr->resultSpace; + iPtr->freeProc = 0; + } else if (freeProc == TCL_VOLATILE) { + length = strlen(string); + if (length > TCL_RESULT_SIZE) { + iPtr->result = (char *) ckalloc((unsigned) length+1); + iPtr->freeProc = TCL_DYNAMIC; + } else { + iPtr->result = iPtr->resultSpace; + iPtr->freeProc = 0; + } + strcpy(iPtr->result, string); + } else { + iPtr->result = string; + 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) + || (oldFreeProc == (Tcl_FreeProc *) free)) { + 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. + * + *---------------------------------------------------------------------- + */ + +char * +Tcl_GetStringResult(interp) + 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. + */ + + if (*(interp->result) == 0) { + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), + TCL_VOLATILE); + } + return interp->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(interp, objPtr) + 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) + || (iPtr->freeProc == (Tcl_FreeProc *) free)) { + 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 procedure 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(interp) + 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) { + ResetObjResult(iPtr); + + objResultPtr = iPtr->objResultPtr; + length = strlen(iPtr->result); + TclInitStringRep(objResultPtr, iPtr->result, length); + + if (iPtr->freeProc != NULL) { + if ((iPtr->freeProc == TCL_DYNAMIC) + || (iPtr->freeProc == (Tcl_FreeProc *) free)) { + ckfree(iPtr->result); + } else { + (*iPtr->freeProc)(iPtr->result); + } + iPtr->freeProc = 0; + } + iPtr->result = iPtr->resultSpace; + iPtr->resultSpace[0] = 0; + } + return iPtr->objResultPtr; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppendResultVA -- + * + * Append a variable number of strings onto the interpreter's string + * 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 empty, the object result is moved to the + * string result, then the object result is reset. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_AppendResultVA (interp, argList) + Tcl_Interp *interp; /* Interpreter with which to associate the + * return value. */ + va_list argList; /* Variable argument list. */ +{ + Interp *iPtr = (Interp *) interp; + va_list tmpArgList; + char *string; + int newSpace; + + /* + * If the string result is empty, move the object result to the + * string result, then reset the object result. + */ + + if (*(iPtr->result) == 0) { + Tcl_SetResult((Tcl_Interp *) iPtr, + TclGetString(Tcl_GetObjResult((Tcl_Interp *) iPtr)), + TCL_VOLATILE); + } + + /* + * Scan through all the arguments to see how much space is needed. + */ + + tmpArgList = argList; + newSpace = 0; + while (1) { + string = va_arg(tmpArgList, char *); + if (string == NULL) { + break; + } + newSpace += strlen(string); + } + + /* + * If the append buffer isn't already setup and large enough to hold + * the new data, set it up. + */ + + if ((iPtr->result != iPtr->appendResult) + || (iPtr->appendResult[iPtr->appendUsed] != 0) + || ((newSpace + iPtr->appendUsed) >= iPtr->appendAvl)) { + SetupAppendBuffer(iPtr, newSpace); + } + + /* + * Now go through all the argument strings again, copying them into the + * buffer. + */ + + while (1) { + string = va_arg(argList, char *); + if (string == NULL) { + break; + } + strcpy(iPtr->appendResult + iPtr->appendUsed, string); + iPtr->appendUsed += strlen(string); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppendResult -- + * + * Append a variable number of strings onto the interpreter's string + * 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 empty, the object result is moved to the + * string result, then the object result is reset. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_AppendResult TCL_VARARGS_DEF(Tcl_Interp *,arg1) +{ + Tcl_Interp *interp; + va_list argList; + + interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList); + 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(interp, string) + Tcl_Interp *interp; /* Interpreter whose result is to be + * extended. */ + CONST char *string; /* 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. + */ + + if (*(iPtr->result) == 0) { + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), + TCL_VOLATILE); + } + + /* + * See how much space is needed, and grow the append buffer if + * needed to accommodate the list element. + */ + + size = Tcl_ScanElement(string, &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++; + } + iPtr->appendUsed += Tcl_ConvertElement(string, dst, flags); +} + +/* + *---------------------------------------------------------------------- + * + * SetupAppendBuffer -- + * + * This procedure 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(iPtr, newSpace) + 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 = (char *) ckalloc((unsigned) 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 procedure 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 procedure 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(interp) + register Tcl_Interp *interp; /* Interpreter for which to free result. */ +{ + register Interp *iPtr = (Interp *) interp; + + if (iPtr->freeProc != NULL) { + if ((iPtr->freeProc == TCL_DYNAMIC) + || (iPtr->freeProc == (Tcl_FreeProc *) free)) { + ckfree(iPtr->result); + } else { + (*iPtr->freeProc)(iPtr->result); + } + iPtr->freeProc = 0; + } + + ResetObjResult(iPtr); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_ResetResult -- + * + * This procedure 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(interp) + 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) + || (iPtr->freeProc == (Tcl_FreeProc *) free)) { + ckfree(iPtr->result); + } else { + (*iPtr->freeProc)(iPtr->result); + } + iPtr->freeProc = 0; + } + iPtr->result = iPtr->resultSpace; + iPtr->resultSpace[0] = 0; + iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS | ERROR_CODE_SET); +} + +/* + *---------------------------------------------------------------------- + * + * ResetObjResult -- + * + * Procedure 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(iPtr) + 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 != NULL) + && (objResultPtr->bytes != tclEmptyStringRep)) { + ckfree((char *) objResultPtr->bytes); + } + objResultPtr->bytes = tclEmptyStringRep; + objResultPtr->length = 0; + if ((objResultPtr->typePtr != NULL) + && (objResultPtr->typePtr->freeIntRepProc != NULL)) { + objResultPtr->typePtr->freeIntRepProc(objResultPtr); + } + objResultPtr->typePtr = (Tcl_ObjType *) NULL; + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_SetErrorCodeVA -- + * + * This procedure is called to record machine-readable information + * about an error that is about to be returned. + * + * Results: + * None. + * + * Side effects: + * The errorCode global variable is modified to hold all of the + * arguments to this procedure, in a list form with each argument + * becoming one element of the list. A flag is set internally + * to remember that errorCode has been set, so the variable doesn't + * get set automatically when the error is returned. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_SetErrorCodeVA (interp, argList) + Tcl_Interp *interp; /* Interpreter in which to access the errorCode + * variable. */ + va_list argList; /* Variable argument list. */ +{ + char *string; + int flags; + Interp *iPtr = (Interp *) interp; + + /* + * Scan through the arguments one at a time, appending them to + * $errorCode as list elements. + */ + + flags = TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT; + while (1) { + string = va_arg(argList, char *); + if (string == NULL) { + break; + } + (void) Tcl_SetVar2((Tcl_Interp *) iPtr, "errorCode", + (char *) NULL, string, flags); + flags |= TCL_APPEND_VALUE; + } + iPtr->flags |= ERROR_CODE_SET; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_SetErrorCode -- + * + * This procedure is called to record machine-readable information + * about an error that is about to be returned. + * + * Results: + * None. + * + * Side effects: + * The errorCode global variable is modified to hold all of the + * arguments to this procedure, in a list form with each argument + * becoming one element of the list. A flag is set internally + * to remember that errorCode has been set, so the variable doesn't + * get set automatically when the error is returned. + * + *---------------------------------------------------------------------- + */ + /* VARARGS2 */ +void +Tcl_SetErrorCode TCL_VARARGS_DEF(Tcl_Interp *,arg1) +{ + Tcl_Interp *interp; + va_list argList; + + /* + * Scan through the arguments one at a time, appending them to + * $errorCode as list elements. + */ + + interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList); + Tcl_SetErrorCodeVA(interp, argList); + va_end(argList); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_SetObjErrorCode -- + * + * This procedure 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 global variable is modified to be the new value. + * A flag is set internally to remember that errorCode has been + * set, so the variable doesn't get set automatically when the + * error is returned. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_SetObjErrorCode(interp, errorObjPtr) + Tcl_Interp *interp; + Tcl_Obj *errorObjPtr; +{ + Interp *iPtr; + + iPtr = (Interp *) interp; + Tcl_SetVar2Ex(interp, "errorCode", NULL, errorObjPtr, TCL_GLOBAL_ONLY); + iPtr->flags |= ERROR_CODE_SET; +} + +/* + *------------------------------------------------------------------------- + * + * TclTransferResult -- + * + * 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 error information "$errorInfo" may be + * appended to the target's error information and the source's error + * code "$errorCode" may be stored in the target's error code. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +void +TclTransferResult(sourceInterp, result, targetInterp) + 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 *iPtr; + Tcl_Obj *objPtr; + + if (sourceInterp == targetInterp) { + return; + } + + if (result == TCL_ERROR) { + /* + * An error occurred, so transfer error information from the source + * interpreter to the target interpreter. Setting the flags tells + * the target interp that it has inherited a partial traceback + * chain, not just a simple error message. + */ + + iPtr = (Interp *) sourceInterp; + if ((iPtr->flags & ERR_ALREADY_LOGGED) == 0) { + Tcl_AddErrorInfo(sourceInterp, ""); + } + iPtr->flags &= ~(ERR_ALREADY_LOGGED); + + Tcl_ResetResult(targetInterp); + + objPtr = Tcl_GetVar2Ex(sourceInterp, "errorInfo", NULL, + TCL_GLOBAL_ONLY); + Tcl_SetVar2Ex(targetInterp, "errorInfo", NULL, objPtr, + TCL_GLOBAL_ONLY); + + objPtr = Tcl_GetVar2Ex(sourceInterp, "errorCode", NULL, + TCL_GLOBAL_ONLY); + Tcl_SetVar2Ex(targetInterp, "errorCode", NULL, objPtr, + TCL_GLOBAL_ONLY); + + ((Interp *) targetInterp)->flags |= (ERR_IN_PROGRESS | ERROR_CODE_SET); + } + + ((Interp *) targetInterp)->returnCode = ((Interp *) sourceInterp)->returnCode; + Tcl_SetObjResult(targetInterp, Tcl_GetObjResult(sourceInterp)); + Tcl_ResetResult(sourceInterp); +} ADDED generic/tclScan.c Index: generic/tclScan.c ================================================================== --- /dev/null +++ generic/tclScan.c @@ -0,0 +1,1032 @@ +/* + * 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. + * + * RCS: @(#) $Id: tclScan.c,v 1.1.2.4 1999/04/02 23:44:57 stanton Exp $ + */ + +#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_SIGNOK 0x10 /* A +/- character is allowed. */ +#define SCAN_NODIGITS 0x20 /* No digits have been scanned. */ +#define SCAN_NOZERO 0x40 /* No zero digits have been scanned. */ +#define SCAN_XOK 0x80 /* An 'x' is allowed. */ +#define SCAN_PTOK 0x100 /* Decimal point is allowed. */ +#define SCAN_EXPOK 0x200 /* An exponent is allowed. */ + + +/* + * 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 char * BuildCharSet _ANSI_ARGS_((CharSet *cset, char *format)); +static int CharInSet _ANSI_ARGS_((CharSet *cset, int ch)); +static void ReleaseCharSet _ANSI_ARGS_((CharSet *cset)); +static int ValidateFormat _ANSI_ARGS_((Tcl_Interp *interp, char *format, + int numVars)); + +/* + *---------------------------------------------------------------------- + * + * 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 char * +BuildCharSet(cset, format) + CharSet *cset; + char *format; /* Points to first char of set. */ +{ + Tcl_UniChar ch, start; + int offset, nranges; + 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 = (Tcl_UniChar *) ckalloc(sizeof(Tcl_UniChar) + * (end - format - 1)); + if (nranges > 0) { + cset->ranges = (struct Range *) 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(cset, c) + 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(cset) + CharSet *cset; +{ + ckfree((char *)cset->chars); + if (cset->ranges) { + ckfree((char *)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(interp, format, numVars) + Tcl_Interp *interp; /* Current interpreter. */ + char *format; /* The format string. */ + int numVars; /* The number of variables passed to the + * scan command. */ +{ + int gotXpg, gotSequential, value, i, flags; + char *end; + Tcl_UniChar ch; + int *nassign = (int*)ckalloc(sizeof(int) * numVars); + int objIndex; + + /* + * 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 < numVars; i++) { + nassign[i] = 0; + } + + 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) || (objIndex >= numVars)) { + goto badIndex; + } + goto xpgCheckDone; + } + + notXpg: + gotSequential = 1; + if (gotXpg) { + mixedXPG: + Tcl_SetResult(interp, + "cannot mix \"%\" and \"%n$\" conversion specifiers", + TCL_STATIC); + goto error; + } + + xpgCheckDone: + /* + * Parse any width specifier. + */ + + if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ + value = strtoul(format-1, &format, 10); /* INTL: "C" locale. */ + flags |= SCAN_WIDTH; + format += Tcl_UtfToUniChar(format, &ch); + } + + /* + * Ignore size specifier. + */ + + if ((ch == 'l') || (ch == 'L') || (ch == 'h')) { + format += Tcl_UtfToUniChar(format, &ch); + } + + if (!(flags & SCAN_SUPPRESS) && objIndex >= numVars) { + goto badIndex; + } + + /* + * Handle the various field types. + */ + + switch (ch) { + case 'n': + case 'd': + case 'i': + case 'o': + case 'x': + case 'u': + case 'f': + case 'e': + case 'g': + case 's': + break; + case 'c': + if (flags & SCAN_WIDTH) { + Tcl_SetResult(interp, "field width may not be specified in %c conversion", TCL_STATIC); + goto error; + } + break; + case '[': + 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_SetResult(interp, "unmatched [ in format string", + TCL_STATIC); + goto error; + default: + { + char buf[TCL_UTF_MAX+1]; + + buf[Tcl_UniCharToUtf(ch, buf)] = '\0'; + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "bad scan conversion character \"", buf, "\"", NULL); + goto error; + } + } + if (!(flags & SCAN_SUPPRESS)) { + nassign[objIndex]++; + objIndex++; + } + } + + /* + * Verify that all of the variable were assigned exactly once. + */ + + for (i = 0; i < numVars; i++) { + if (nassign[i] > 1) { + Tcl_SetResult(interp, "variable is assigned by multiple \"%n$\" conversion specifiers", TCL_STATIC); + goto error; + } else if (nassign[i] == 0) { + Tcl_SetResult(interp, "variable is not assigend by any conversion specifiers", TCL_STATIC); + goto error; + } + } + + ckfree((char *)nassign); + return TCL_OK; + + badIndex: + if (gotXpg) { + Tcl_SetResult(interp, "\"%n$\" argument index out of range", + TCL_STATIC); + } else { + Tcl_SetResult(interp, + "different numbers of variable names and field specifiers", + TCL_STATIC); + } + + error: + ckfree((char *)nassign); + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_ScanObjCmd -- + * + * This procedure 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(dummy, interp, objc, objv) + ClientData dummy; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + char *format; + int numVars, nconversions; + int objIndex, offset, i, value, result, code; + char *string, *end, *baseString; + char op = 0; + int base = 0; + int underflow = 0; + size_t width; + long (*fn)() = NULL; + Tcl_UniChar ch, sch; + Tcl_Obj **objs, *objPtr; + 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 varName ...?"); + return TCL_ERROR; + } + + format = Tcl_GetStringFromObj(objv[2], NULL); + numVars = objc-3; + + /* + * Check for errors in the format string. + */ + + if (ValidateFormat(interp, format, numVars) == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * Allocate space for the result objects. + */ + + objs = (Tcl_Obj **) ckalloc(sizeof(Tcl_Obj*) * numVars); + for (i = 0; i < numVars; i++) { + objs[i] = NULL; + } + + string = Tcl_GetStringFromObj(objv[1], NULL); + 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') { + 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. */ + value = strtoul(format-1, &end, 10); /* INTL: "C" locale. */ + if (*end == '$') { + format = end+1; + format += Tcl_UtfToUniChar(format, &ch); + objIndex = value - 1; + } + } + + /* + * Parse any width specifier. + */ + + if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ + width = strtoul(format-1, &format, 10); /* INTL: "C" locale. */ + format += Tcl_UtfToUniChar(format, &ch); + } else { + width = 0; + } + + /* + * Ignore size specifier. + */ + + if ((ch == 'l') || (ch == 'L') || (ch == '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); + objs[objIndex++] = objPtr; + } + nconversions++; + continue; + + case 'd': + op = 'i'; + base = 10; + fn = (long (*)())strtol; + break; + case 'i': + op = 'i'; + base = 0; + fn = (long (*)())strtol; + break; + case 'o': + op = 'i'; + base = 8; + fn = (long (*)())strtol; + break; + case 'x': + op = 'i'; + base = 16; + fn = (long (*)())strtol; + break; + case 'u': + op = 'i'; + base = 10; + flags |= SCAN_UNSIGNED; + fn = (long (*)())strtoul; + break; + + case 'f': + case 'e': + 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 = (size_t) ~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); + objs[objIndex++] = objPtr; + } + string = end; + break; + + case '[': { + CharSet cset; + + if (width == 0) { + width = (size_t) ~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 (!(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); + objs[objIndex++] = objPtr; + } + break; + + case 'i': + /* + * Scan an unsigned or signed integer. + */ + + if ((width == 0) || (width > sizeof(buf) - 1)) { + width = sizeof(buf) - 1; + } + flags |= SCAN_SIGNOK | SCAN_NODIGITS | SCAN_NOZERO; + for (end = buf; width > 0; width--) { + switch (*string) { + /* + * The 0 digit has special meaning at the beginning of + * a number. If we are unsure of the base, it + * indicates that we are in base 8 or base 16 (if it is + * followed by an 'x'). + */ + case '0': + if (base == 0) { + base = 8; + flags |= SCAN_XOK; + } + if (flags & SCAN_NOZERO) { + flags &= ~(SCAN_SIGNOK | SCAN_NODIGITS + | SCAN_NOZERO); + } else { + flags &= ~(SCAN_SIGNOK | SCAN_XOK + | SCAN_NODIGITS); + } + goto addToInt; + + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + if (base == 0) { + base = 10; + } + flags &= ~(SCAN_SIGNOK | SCAN_XOK | SCAN_NODIGITS); + goto addToInt; + + case '8': case '9': + if (base == 0) { + base = 10; + } + if (base <= 8) { + break; + } + flags &= ~(SCAN_SIGNOK | SCAN_XOK | SCAN_NODIGITS); + goto addToInt; + + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + if (base <= 10) { + break; + } + flags &= ~(SCAN_SIGNOK | SCAN_XOK | SCAN_NODIGITS); + goto addToInt; + + case '+': case '-': + if (flags & SCAN_SIGNOK) { + flags &= ~SCAN_SIGNOK; + goto addToInt; + } + break; + + case 'x': case 'X': + if ((flags & SCAN_XOK) && (end == buf+1)) { + base = 16; + flags &= ~SCAN_XOK; + goto addToInt; + } + break; + } + + /* + * We got an illegal character so we are done accumulating. + */ + + break; + + addToInt: + /* + * Add the character to the temporary buffer. + */ + + *end++ = *string++; + if (*string == '\0') { + break; + } + } + + /* + * Check to see if we need to back up because we only got a + * sign or a trailing x after a 0. + */ + + if (flags & SCAN_NODIGITS) { + if (*string == '\0') { + underflow = 1; + } + goto done; + } else if (end[-1] == 'x' || end[-1] == 'X') { + end--; + string--; + } + + + /* + * Scan the value from the temporary buffer. If we are + * returning a large unsigned value, we have to convert it back + * to a string since Tcl only supports signed values. + */ + + if (!(flags & SCAN_SUPPRESS)) { + *end = '\0'; + value = (int) (*fn)(buf, NULL, base); + if ((flags & SCAN_UNSIGNED) && (value < 0)) { + sprintf(buf, "%u", value); /* INTL: ISO digit */ + objPtr = Tcl_NewStringObj(buf, -1); + } else { + objPtr = Tcl_NewIntObj(value); + } + Tcl_IncrRefCount(objPtr); + objs[objIndex++] = objPtr; + } + + break; + + case 'f': + /* + * Scan a floating point number + */ + + if ((width == 0) || (width > sizeof(buf) - 1)) { + width = sizeof(buf) - 1; + } + flags |= SCAN_SIGNOK | SCAN_NODIGITS | SCAN_PTOK | SCAN_EXPOK; + for (end = buf; width > 0; width--) { + switch (*string) { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + flags &= ~(SCAN_SIGNOK | SCAN_NODIGITS); + goto addToFloat; + case '+': case '-': + if (flags & SCAN_SIGNOK) { + flags &= ~SCAN_SIGNOK; + goto addToFloat; + } + break; + case '.': + if (flags & SCAN_PTOK) { + flags &= ~(SCAN_SIGNOK | SCAN_PTOK); + goto addToFloat; + } + break; + case 'e': case 'E': + /* + * An exponent is not allowed until there has + * been at least one digit. + */ + + if ((flags & (SCAN_NODIGITS | SCAN_EXPOK)) + == SCAN_EXPOK) { + flags = (flags & ~(SCAN_EXPOK|SCAN_PTOK)) + | SCAN_SIGNOK | SCAN_NODIGITS; + goto addToFloat; + } + break; + } + + /* + * We got an illegal character so we are done accumulating. + */ + + break; + + addToFloat: + /* + * Add the character to the temporary buffer. + */ + + *end++ = *string++; + if (*string == '\0') { + break; + } + } + + /* + * Check to see if we need to back up because we saw a + * trailing 'e' or sign. + */ + + if (flags & SCAN_NODIGITS) { + if (flags & SCAN_EXPOK) { + /* + * There were no digits at all so scanning has + * failed and we are done. + */ + if (*string == '\0') { + underflow = 1; + } + goto done; + } + + /* + * We got a bad exponent ('e' and maybe a sign). + */ + + end--; + string--; + if (*end != 'e' && *end != 'E') { + end--; + string--; + } + } + + /* + * Scan the value from the temporary buffer. + */ + + if (!(flags & SCAN_SUPPRESS)) { + double dvalue; + *end = '\0'; + dvalue = strtod(buf, NULL); + objPtr = Tcl_NewDoubleObj(dvalue); + Tcl_IncrRefCount(objPtr); + objs[objIndex++] = objPtr; + } + break; + } + nconversions++; + } + + done: + result = 0; + code = TCL_OK; + + for (i = 0; i < numVars; i++) { + if (objs[i] != NULL) { + result++; + if (Tcl_ObjSetVar2(interp, objv[i+3], NULL, objs[i], 0) == NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "couldn't set variable \"", + Tcl_GetString(objv[i+3]), "\"", (char *) NULL); + code = TCL_ERROR; + } + Tcl_DecrRefCount(objs[i]); + } + } + ckfree((char*) objs); + if (code == TCL_OK) { + if (underflow && (nconversions == 0)) { + result = -1; + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(result)); + } + return code; +} Index: generic/tclStringObj.c ================================================================== --- generic/tclStringObj.c +++ generic/tclStringObj.c @@ -12,11 +12,11 @@ * 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. * - * SCCS: @(#) tclStringObj.c 1.31 97/10/30 13:56:35 + * RCS: @(#) $Id: tclStringObj.c,v 1.1.2.3 1999/03/10 06:49:21 stanton Exp $ */ #include "tclInt.h" /* @@ -72,13 +72,13 @@ #ifdef TCL_MEM_DEBUG #undef Tcl_NewStringObj Tcl_Obj * Tcl_NewStringObj(bytes, length) - register char *bytes; /* Points to the first of the length bytes + CONST char *bytes; /* Points to the first of the length bytes * used to initialize the new object. */ - register int length; /* The number of bytes to copy from "bytes" + int length; /* The number of bytes to copy from "bytes" * when initializing the new object. If * negative, use bytes up to the first * NULL byte. */ { return Tcl_DbNewStringObj(bytes, length, "unknown", 0); @@ -86,13 +86,13 @@ #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_NewStringObj(bytes, length) - register char *bytes; /* Points to the first of the length bytes + CONST char *bytes; /* Points to the first of the length bytes * used to initialize the new object. */ - register int length; /* The number of bytes to copy from "bytes" + int length; /* The number of bytes to copy from "bytes" * when initializing the new object. If * negative, use bytes up to the first * NULL byte. */ { register Tcl_Obj *objPtr; @@ -138,13 +138,13 @@ #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_DbNewStringObj(bytes, length, file, line) - register char *bytes; /* Points to the first of the length bytes + CONST char *bytes; /* Points to the first of the length bytes * used to initialize the new object. */ - register int length; /* The number of bytes to copy from "bytes" + int length; /* The number of bytes to copy from "bytes" * when initializing the new object. If * negative, use bytes up to the first * NULL byte. */ char *file; /* The name of the source file calling this * procedure; used for debugging. */ @@ -163,11 +163,11 @@ #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_DbNewStringObj(bytes, length, file, line) - register char *bytes; /* Points to the first of the length bytes + CONST char *bytes; /* Points to the first of the length bytes * used to initialize the new object. */ register int length; /* The number of bytes to copy from "bytes" * when initializing the new object. If * negative, use bytes up to the first * NULL byte. */ @@ -222,11 +222,11 @@ panic("Tcl_SetStringObj called with shared object"); } Tcl_InvalidateStringRep(objPtr); if (length < 0) { - length = strlen(bytes); + length = (bytes? strlen(bytes) : 0); } TclInitStringRep(objPtr, bytes, length); /* * Set the type to NULL and free any internal rep for the old type. @@ -333,11 +333,11 @@ } if (objPtr->typePtr != &tclStringType) { ConvertToStringType(objPtr); } if (length < 0) { - length = strlen(bytes); + length = (bytes? strlen(bytes) : 0); } if (length == 0) { return; } oldLength = objPtr->length; @@ -361,11 +361,40 @@ } /* *---------------------------------------------------------------------- * - * Tcl_AppendStringsToObj -- + * Tcl_AppendObjToObj -- + * + * This procedure appends the string rep of one object to another. + * + * Results: + * None. + * + * Side effects: + * The string rep of appendObjPtr is appended to the string + * representation of objPtr. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_AppendObjToObj(objPtr, appendObjPtr) + Tcl_Obj *objPtr; /* Points to the object to append to. */ + Tcl_Obj *appendObjPtr; /* Object to append. */ +{ + int length; + char *stringRep; + + stringRep = Tcl_GetStringFromObj(appendObjPtr, &length); + Tcl_AppendToObj(objPtr, stringRep, length); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppendStringsToObjVA -- * * This procedure appends one or more null-terminated strings * to an object. * * Results: @@ -377,18 +406,18 @@ * *---------------------------------------------------------------------- */ void -Tcl_AppendStringsToObj TCL_VARARGS_DEF(Tcl_Obj *,arg1) +Tcl_AppendStringsToObjVA (objPtr, argList) + Tcl_Obj *objPtr; /* Points to the object to append to. */ + va_list argList; /* Variable argument list. */ { - va_list argList; - register Tcl_Obj *objPtr; + va_list tmpArgList; int newLength, oldLength; register char *string, *dst; - objPtr = (Tcl_Obj *) TCL_VARARGS_START(Tcl_Obj *,arg1,argList); if (Tcl_IsShared(objPtr)) { panic("Tcl_AppendStringsToObj called with shared object"); } if (objPtr->typePtr != &tclStringType) { ConvertToStringType(objPtr); @@ -398,13 +427,14 @@ * Figure out how much space is needed for all the strings, and * expand the string representation if it isn't big enough. If no * bytes would be appended, just return. */ + tmpArgList = argList; newLength = oldLength = objPtr->length; while (1) { - string = va_arg(argList, char *); + string = va_arg(tmpArgList, char *); if (string == NULL) { break; } newLength += strlen(string); } @@ -428,11 +458,10 @@ /* * Make a second pass through the arguments, appending all the * strings to the object. */ - TCL_VARARGS_START(Tcl_Obj *,arg1,argList); dst = objPtr->bytes + oldLength; while (1) { string = va_arg(argList, char *); if (string == NULL) { break; @@ -453,10 +482,38 @@ if (dst != NULL) { *dst = 0; } objPtr->length = newLength; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppendStringsToObj -- + * + * This procedure 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_VARARGS_DEF(Tcl_Obj *,arg1) +{ + register Tcl_Obj *objPtr; + va_list argList; + + objPtr = TCL_VARARGS_START(Tcl_Obj *,arg1,argList); + Tcl_AppendStringsToObjVA(objPtr, argList); va_end(argList); } /* *---------------------------------------------------------------------- ADDED generic/tclStubInit.c Index: generic/tclStubInit.c ================================================================== --- /dev/null +++ generic/tclStubInit.c @@ -0,0 +1,687 @@ +/* + * 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. + * + * RCS: @(#) $Id: tclStubInit.c,v 1.3.2.12 1999/04/06 03:13:19 redman Exp $ + */ + +#include "tclInt.h" +#include "tclPort.h" + +/* + * 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 + +/* + * 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. + */ + +/* !BEGIN!: Do not edit below this line. */ + +static TclStubHooks tclStubHooks; + +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_TCL) /* UNIX */ + Tcl_CreateFileHandler, /* 9 */ +#endif /* UNIX */ +#ifdef __WIN32__ + NULL, /* 9 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + NULL, /* 9 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + Tcl_DeleteFileHandler, /* 10 */ +#endif /* UNIX */ +#ifdef __WIN32__ + NULL, /* 10 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + NULL, /* 10 */ +#endif /* MAC_TCL */ + 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_TCL) /* UNIX */ + Tcl_GetOpenFile, /* 167 */ +#endif /* UNIX */ +#ifdef __WIN32__ + NULL, /* 167 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + NULL, /* 167 */ +#endif /* MAC_TCL */ + 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 */ + NULL, /* 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_Seek, /* 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_Tell, /* 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 */ + NULL, /* 281 */ + NULL, /* 282 */ + NULL, /* 283 */ + NULL, /* 284 */ + NULL, /* 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 */ +}; + +TclIntStubs tclIntStubs = { + TCL_STUB_MAGIC, + NULL, + TclAccess, /* 0 */ + TclAccessDeleteProc, /* 1 */ + TclAccessInsertProc, /* 2 */ + TclAllocateFreeObjects, /* 3 */ + NULL, /* 4 */ + TclCleanupChildren, /* 5 */ + TclCleanupCommand, /* 6 */ + TclCopyAndCollapse, /* 7 */ + TclCopyChannel, /* 8 */ + TclCreatePipeline, /* 9 */ + TclCreateProc, /* 10 */ + TclDeleteCompiledLocalVars, /* 11 */ + TclDeleteVars, /* 12 */ + TclDoGlob, /* 13 */ + TclDumpMemoryInfo, /* 14 */ + NULL, /* 15 */ + TclExprFloatError, /* 16 */ + TclFileAttrsCmd, /* 17 */ + TclFileCopyCmd, /* 18 */ + TclFileDeleteCmd, /* 19 */ + TclFileMakeDirsCmd, /* 20 */ + TclFileRenameCmd, /* 21 */ + TclFindElement, /* 22 */ + TclFindProc, /* 23 */ + TclFormatInt, /* 24 */ + TclFreePackageInfo, /* 25 */ + NULL, /* 26 */ + TclGetDate, /* 27 */ + TclpGetDefaultStdChannel, /* 28 */ + TclGetElementOfIndexedArray, /* 29 */ + NULL, /* 30 */ + TclGetExtension, /* 31 */ + TclGetFrame, /* 32 */ + TclGetInterpProc, /* 33 */ + TclGetIntForIndex, /* 34 */ + TclGetIndexedScalar, /* 35 */ + TclGetLong, /* 36 */ + TclGetLoadedPackages, /* 37 */ + TclGetNamespaceForQualName, /* 38 */ + TclGetObjInterpProc, /* 39 */ + TclGetOpenMode, /* 40 */ + TclGetOriginalCommand, /* 41 */ + TclpGetUserHome, /* 42 */ + TclGlobalInvoke, /* 43 */ + TclGuessPackageName, /* 44 */ + TclHideUnsafeCommands, /* 45 */ + TclInExit, /* 46 */ + TclIncrElementOfIndexedArray, /* 47 */ + TclIncrIndexedScalar, /* 48 */ + TclIncrVar2, /* 49 */ + TclInitCompiledLocals, /* 50 */ + TclInterpInit, /* 51 */ + TclInvoke, /* 52 */ + TclInvokeObjectCommand, /* 53 */ + TclInvokeStringCommand, /* 54 */ + TclIsProc, /* 55 */ + NULL, /* 56 */ + NULL, /* 57 */ + TclLookupVar, /* 58 */ + TclpMatchFiles, /* 59 */ + TclNeedSpace, /* 60 */ + TclNewProcBodyObj, /* 61 */ + TclObjCommandComplete, /* 62 */ + TclObjInterpProc, /* 63 */ + TclObjInvoke, /* 64 */ + TclObjInvokeGlobal, /* 65 */ + TclOpenFileChannelDeleteProc, /* 66 */ + TclOpenFileChannelInsertProc, /* 67 */ + TclpAccess, /* 68 */ + TclpAlloc, /* 69 */ + TclpCopyFile, /* 70 */ + TclpCopyDirectory, /* 71 */ + TclpCreateDirectory, /* 72 */ + TclpDeleteFile, /* 73 */ + TclpFree, /* 74 */ + TclpGetClicks, /* 75 */ + TclpGetSeconds, /* 76 */ + TclpGetTime, /* 77 */ + TclpGetTimeZone, /* 78 */ + TclpListVolumes, /* 79 */ + TclpOpenFileChannel, /* 80 */ + TclpRealloc, /* 81 */ + TclpRemoveDirectory, /* 82 */ + TclpRenameFile, /* 83 */ + NULL, /* 84 */ + NULL, /* 85 */ + NULL, /* 86 */ + NULL, /* 87 */ + TclPrecTraceProc, /* 88 */ + TclPreventAliasLoop, /* 89 */ + NULL, /* 90 */ + TclProcCleanupProc, /* 91 */ + TclProcCompileProc, /* 92 */ + TclProcDeleteProc, /* 93 */ + TclProcInterpProc, /* 94 */ + TclpStat, /* 95 */ + TclRenameCommand, /* 96 */ + TclResetShadowedCmdRefs, /* 97 */ + TclServiceIdle, /* 98 */ + TclSetElementOfIndexedArray, /* 99 */ + TclSetIndexedScalar, /* 100 */ + NULL, /* 101 */ + TclSetupEnv, /* 102 */ + TclSockGetPort, /* 103 */ + TclSockMinimumBuffers, /* 104 */ + TclStat, /* 105 */ + TclStatDeleteProc, /* 106 */ + TclStatInsertProc, /* 107 */ + TclTeardownNamespace, /* 108 */ + TclUpdateReturnInfo, /* 109 */ + NULL, /* 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 */ + TclpStrftime, /* 134 */ + TclpCheckStackSpace, /* 135 */ + NULL, /* 136 */ + TclpChdir, /* 137 */ + TclGetEnv, /* 138 */ + TclpLoadFile, /* 139 */ + TclLooksLikeInt, /* 140 */ + TclpGetCwd, /* 141 */ +}; + +TclIntPlatStubs tclIntPlatStubs = { + TCL_STUB_MAGIC, + NULL, +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + TclGetAndDetachPids, /* 0 */ + TclpCloseFile, /* 1 */ + TclpCreateCommandChannel, /* 2 */ + TclpCreatePipe, /* 3 */ + TclpCreateProcess, /* 4 */ + NULL, /* 5 */ + TclpMakeFile, /* 6 */ + TclpOpenFile, /* 7 */ + TclUnixWaitForFile, /* 8 */ + TclpCreateTempFile, /* 9 */ +#endif /* UNIX */ +#ifdef __WIN32__ + TclWinConvertError, /* 0 */ + TclWinConvertWSAError, /* 1 */ + TclWinGetServByName, /* 2 */ + TclWinGetSockOpt, /* 3 */ + TclWinGetTclInstance, /* 4 */ + NULL, /* 5 */ + TclWinNToHS, /* 6 */ + TclWinSetSockOpt, /* 7 */ + TclpGetPid, /* 8 */ + TclWinGetPlatformId, /* 9 */ + TclWinSynchSpawn, /* 10 */ + TclGetAndDetachPids, /* 11 */ + TclpCloseFile, /* 12 */ + TclpCreateCommandChannel, /* 13 */ + TclpCreatePipe, /* 14 */ + TclpCreateProcess, /* 15 */ + NULL, /* 16 */ + NULL, /* 17 */ + TclpMakeFile, /* 18 */ + TclpOpenFile, /* 19 */ + TclWinAddProcess, /* 20 */ + TclpAsyncMark, /* 21 */ + TclpCreateTempFile, /* 22 */ + TclpGetTZName, /* 23 */ + TclWinNoBackslash, /* 24 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + TclpSysAlloc, /* 0 */ + TclpSysFree, /* 1 */ + TclpSysRealloc, /* 2 */ + TclpExit, /* 3 */ + FSpGetDefaultDir, /* 4 */ + FSpSetDefaultDir, /* 5 */ + FSpFindFolder, /* 6 */ + GetGlobalMouse, /* 7 */ + FSpGetDirectoryID, /* 8 */ + FSpOpenResFileCompat, /* 9 */ + FSpCreateResFileCompat, /* 10 */ + FSpLocationFromPath, /* 11 */ + FSpPathFromLocation, /* 12 */ + TclMacExitHandler, /* 13 */ + TclMacInitExitToShell, /* 14 */ + TclMacInstallExitToShellPatch, /* 15 */ + TclMacOSErrorToPosixError, /* 16 */ + TclMacRemoveTimer, /* 17 */ + TclMacStartTimer, /* 18 */ + TclMacTimerExpired, /* 19 */ + TclMacRegisterResourceFork, /* 20 */ + TclMacUnRegisterResourceFork, /* 21 */ + TclMacCreateEnv, /* 22 */ + TclMacFOpenHack, /* 23 */ + NULL, /* 24 */ + TclMacChmod, /* 25 */ +#endif /* MAC_TCL */ +}; + +TclPlatStubs tclPlatStubs = { + TCL_STUB_MAGIC, + NULL, +#ifdef __WIN32__ + Tcl_WinUtfToTChar, /* 0 */ + Tcl_WinTCharToUtf, /* 1 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + Tcl_MacSetEventProc, /* 0 */ + Tcl_MacConvertTextResource, /* 1 */ + Tcl_MacEvalResource, /* 2 */ + Tcl_MacFindResource, /* 3 */ + Tcl_GetOSTypeFromObj, /* 4 */ + Tcl_SetOSTypeObj, /* 5 */ + Tcl_NewOSTypeObj, /* 6 */ + strncasecmp, /* 7 */ + strcasecmp, /* 8 */ +#endif /* MAC_TCL */ +}; + +static TclStubHooks tclStubHooks = { + &tclPlatStubs, + &tclIntStubs, + &tclIntPlatStubs +}; + + +/* !END!: Do not edit above this line. */ ADDED generic/tclStubLib.c Index: generic/tclStubLib.c ================================================================== --- /dev/null +++ generic/tclStubLib.c @@ -0,0 +1,113 @@ +/* + * tclStubLib.c -- + * + * Stub object that will be statically linked into extensions that wish + * 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. + * + * RCS: @(#) $Id: tclStubLib.c,v 1.3.2.2 1999/03/14 03:14:29 stanton Exp $ + */ + +/* + * We need to ensure that we use the stub macros so that this file contains + * no references to any of the stub functions. This will make it possible + * to build an extension that references Tcl_InitStubs but doesn't end up + * including the rest of the stub functions. + */ + +#ifndef USE_TCL_STUBS +#define USE_TCL_STUBS +#endif +#undef USE_TCL_STUB_PROCS + +#include "tclInt.h" +#include "tclPort.h" + +/* + * Ensure that Tcl_InitStubs is built as an exported symbol. The other stub + * functions should be built as non-exported symbols. + */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT + +TclStubs *tclStubsPtr; +TclPlatStubs *tclPlatStubsPtr; +TclIntStubs *tclIntStubsPtr; +TclIntPlatStubs *tclIntPlatStubsPtr; + +static TclStubs * HasStubSupport _ANSI_ARGS_((Tcl_Interp *interp)); + +static TclStubs * +HasStubSupport (interp) + Tcl_Interp *interp; +{ + Interp *iPtr = (Interp *) interp; + + if (iPtr->stubTable && (iPtr->stubTable->magic == TCL_STUB_MAGIC)) { + return iPtr->stubTable; + } + interp->result = "This interpreter does not support stubs-enabled extensions."; + interp->freeProc = TCL_STATIC; + + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + *---------------------------------------------------------------------- + */ + +char * +Tcl_InitStubs (interp, version, exact) + Tcl_Interp *interp; + char *version; + int exact; +{ + char *actualVersion; + TclStubs *tmp; + + if (!tclStubsPtr) { + tclStubsPtr = HasStubSupport(interp); + if (!tclStubsPtr) { + return NULL; + } + } + + actualVersion = Tcl_PkgRequireEx(interp, "Tcl", version, exact, + (ClientData *) &tmp); + if (actualVersion == NULL) { + tclStubsPtr = NULL; + return NULL; + } + + if (tclStubsPtr->hooks) { + tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs; + tclIntStubsPtr = tclStubsPtr->hooks->tclIntStubs; + tclIntPlatStubsPtr = tclStubsPtr->hooks->tclIntPlatStubs; + } else { + tclPlatStubsPtr = NULL; + tclIntStubsPtr = NULL; + tclIntPlatStubsPtr = NULL; + } + + return actualVersion; +} ADDED generic/tclStubs.c Index: generic/tclStubs.c ================================================================== --- /dev/null +++ generic/tclStubs.c @@ -0,0 +1,3267 @@ +/* + * tclStubs.c -- + * + * This file contains the wrapper functions for 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. + * + * RCS: @(#) $Id: tclStubs.c,v 1.3.2.10 1999/03/30 03:45:34 stanton Exp $ + */ + +#include "tcl.h" + +/* + * Undefine function macros that will interfere with the defintions 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_InitMemory +#undef Tcl_DumpActiveMemory +#undef Tcl_ValidateAllMemory +#undef Tcl_EvalObj +#undef Tcl_GlobalEvalObj +#undef Tcl_MutexLock +#undef Tcl_MutexUnlock +#undef Tcl_ConditionNotify +#undef Tcl_ConditionWait + +/* + * 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. */ + +/* + * Exported stub functions: + */ + +/* Slot 0 */ +int +Tcl_PkgProvideEx(interp, name, version, clientData) + Tcl_Interp * interp; + char * name; + char * version; + ClientData clientData; +{ + return (tclStubsPtr->tcl_PkgProvideEx)(interp, name, version, clientData); +} + +/* Slot 1 */ +char * +Tcl_PkgRequireEx(interp, name, version, exact, clientDataPtr) + Tcl_Interp * interp; + char * name; + char * version; + int exact; + ClientData * clientDataPtr; +{ + return (tclStubsPtr->tcl_PkgRequireEx)(interp, name, version, exact, clientDataPtr); +} + +/* Slot 2 */ +void +Tcl_Panic TCL_VARARGS_DEF(char *,format) +{ + char * var; + va_list argList; + + var = (char *) TCL_VARARGS_START(char *,format,argList); + + (tclStubsPtr->tcl_PanicVA)(var, argList); + va_end(argList); +} + +/* Slot 3 */ +char * +Tcl_Alloc(size) + unsigned int size; +{ + return (tclStubsPtr->tcl_Alloc)(size); +} + +/* Slot 4 */ +void +Tcl_Free(ptr) + char * ptr; +{ + (tclStubsPtr->tcl_Free)(ptr); +} + +/* Slot 5 */ +char * +Tcl_Realloc(ptr, size) + char * ptr; + unsigned int size; +{ + return (tclStubsPtr->tcl_Realloc)(ptr, size); +} + +/* Slot 6 */ +char * +Tcl_DbCkalloc(size, file, line) + unsigned int size; + char * file; + int line; +{ + return (tclStubsPtr->tcl_DbCkalloc)(size, file, line); +} + +/* Slot 7 */ +int +Tcl_DbCkfree(ptr, file, line) + char * ptr; + char * file; + int line; +{ + return (tclStubsPtr->tcl_DbCkfree)(ptr, file, line); +} + +/* Slot 8 */ +char * +Tcl_DbCkrealloc(ptr, size, file, line) + char * ptr; + unsigned int size; + char * file; + int line; +{ + return (tclStubsPtr->tcl_DbCkrealloc)(ptr, size, file, line); +} + +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* Slot 9 */ +void +Tcl_CreateFileHandler(fd, mask, proc, clientData) + int fd; + int mask; + Tcl_FileProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_CreateFileHandler)(fd, mask, proc, clientData); +} + +#endif /* UNIX */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* Slot 10 */ +void +Tcl_DeleteFileHandler(fd) + int fd; +{ + (tclStubsPtr->tcl_DeleteFileHandler)(fd); +} + +#endif /* UNIX */ +/* Slot 11 */ +void +Tcl_SetTimer(timePtr) + Tcl_Time * timePtr; +{ + (tclStubsPtr->tcl_SetTimer)(timePtr); +} + +/* Slot 12 */ +void +Tcl_Sleep(ms) + int ms; +{ + (tclStubsPtr->tcl_Sleep)(ms); +} + +/* Slot 13 */ +int +Tcl_WaitForEvent(timePtr) + Tcl_Time * timePtr; +{ + return (tclStubsPtr->tcl_WaitForEvent)(timePtr); +} + +/* Slot 14 */ +int +Tcl_AppendAllObjTypes(interp, objPtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; +{ + return (tclStubsPtr->tcl_AppendAllObjTypes)(interp, objPtr); +} + +/* Slot 15 */ +void +Tcl_AppendStringsToObj TCL_VARARGS_DEF(Tcl_Obj *,objPtr) +{ + Tcl_Obj * var; + va_list argList; + + var = (Tcl_Obj *) TCL_VARARGS_START(Tcl_Obj *,objPtr,argList); + + (tclStubsPtr->tcl_AppendStringsToObjVA)(var, argList); + va_end(argList); +} + +/* Slot 16 */ +void +Tcl_AppendToObj(objPtr, bytes, length) + Tcl_Obj * objPtr; + char * bytes; + int length; +{ + (tclStubsPtr->tcl_AppendToObj)(objPtr, bytes, length); +} + +/* Slot 17 */ +Tcl_Obj * +Tcl_ConcatObj(objc, objv) + int objc; + Tcl_Obj *CONST objv[]; +{ + return (tclStubsPtr->tcl_ConcatObj)(objc, objv); +} + +/* Slot 18 */ +int +Tcl_ConvertToType(interp, objPtr, typePtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + Tcl_ObjType * typePtr; +{ + return (tclStubsPtr->tcl_ConvertToType)(interp, objPtr, typePtr); +} + +/* Slot 19 */ +void +Tcl_DbDecrRefCount(objPtr, file, line) + Tcl_Obj * objPtr; + char * file; + int line; +{ + (tclStubsPtr->tcl_DbDecrRefCount)(objPtr, file, line); +} + +/* Slot 20 */ +void +Tcl_DbIncrRefCount(objPtr, file, line) + Tcl_Obj * objPtr; + char * file; + int line; +{ + (tclStubsPtr->tcl_DbIncrRefCount)(objPtr, file, line); +} + +/* Slot 21 */ +int +Tcl_DbIsShared(objPtr, file, line) + Tcl_Obj * objPtr; + char * file; + int line; +{ + return (tclStubsPtr->tcl_DbIsShared)(objPtr, file, line); +} + +/* Slot 22 */ +Tcl_Obj * +Tcl_DbNewBooleanObj(boolValue, file, line) + int boolValue; + char * file; + int line; +{ + return (tclStubsPtr->tcl_DbNewBooleanObj)(boolValue, file, line); +} + +/* Slot 23 */ +Tcl_Obj * +Tcl_DbNewByteArrayObj(bytes, length, file, line) + unsigned char * bytes; + int length; + char * file; + int line; +{ + return (tclStubsPtr->tcl_DbNewByteArrayObj)(bytes, length, file, line); +} + +/* Slot 24 */ +Tcl_Obj * +Tcl_DbNewDoubleObj(doubleValue, file, line) + double doubleValue; + char * file; + int line; +{ + return (tclStubsPtr->tcl_DbNewDoubleObj)(doubleValue, file, line); +} + +/* Slot 25 */ +Tcl_Obj * +Tcl_DbNewListObj(objc, objv, file, line) + int objc; + Tcl_Obj *CONST objv[]; + char * file; + int line; +{ + return (tclStubsPtr->tcl_DbNewListObj)(objc, objv, file, line); +} + +/* Slot 26 */ +Tcl_Obj * +Tcl_DbNewLongObj(longValue, file, line) + long longValue; + char * file; + int line; +{ + return (tclStubsPtr->tcl_DbNewLongObj)(longValue, file, line); +} + +/* Slot 27 */ +Tcl_Obj * +Tcl_DbNewObj(file, line) + char * file; + int line; +{ + return (tclStubsPtr->tcl_DbNewObj)(file, line); +} + +/* Slot 28 */ +Tcl_Obj * +Tcl_DbNewStringObj(bytes, length, file, line) + CONST char * bytes; + int length; + char * file; + int line; +{ + return (tclStubsPtr->tcl_DbNewStringObj)(bytes, length, file, line); +} + +/* Slot 29 */ +Tcl_Obj * +Tcl_DuplicateObj(objPtr) + Tcl_Obj * objPtr; +{ + return (tclStubsPtr->tcl_DuplicateObj)(objPtr); +} + +/* Slot 30 */ +void +TclFreeObj(objPtr) + Tcl_Obj * objPtr; +{ + (tclStubsPtr->tclFreeObj)(objPtr); +} + +/* Slot 31 */ +int +Tcl_GetBoolean(interp, str, boolPtr) + Tcl_Interp * interp; + char * str; + int * boolPtr; +{ + return (tclStubsPtr->tcl_GetBoolean)(interp, str, boolPtr); +} + +/* Slot 32 */ +int +Tcl_GetBooleanFromObj(interp, objPtr, boolPtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + int * boolPtr; +{ + return (tclStubsPtr->tcl_GetBooleanFromObj)(interp, objPtr, boolPtr); +} + +/* Slot 33 */ +unsigned char * +Tcl_GetByteArrayFromObj(objPtr, lengthPtr) + Tcl_Obj * objPtr; + int * lengthPtr; +{ + return (tclStubsPtr->tcl_GetByteArrayFromObj)(objPtr, lengthPtr); +} + +/* Slot 34 */ +int +Tcl_GetDouble(interp, str, doublePtr) + Tcl_Interp * interp; + char * str; + double * doublePtr; +{ + return (tclStubsPtr->tcl_GetDouble)(interp, str, doublePtr); +} + +/* Slot 35 */ +int +Tcl_GetDoubleFromObj(interp, objPtr, doublePtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + double * doublePtr; +{ + return (tclStubsPtr->tcl_GetDoubleFromObj)(interp, objPtr, doublePtr); +} + +/* Slot 36 */ +int +Tcl_GetIndexFromObj(interp, objPtr, tablePtr, msg, flags, indexPtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + char ** tablePtr; + char * msg; + int flags; + int * indexPtr; +{ + return (tclStubsPtr->tcl_GetIndexFromObj)(interp, objPtr, tablePtr, msg, flags, indexPtr); +} + +/* Slot 37 */ +int +Tcl_GetInt(interp, str, intPtr) + Tcl_Interp * interp; + char * str; + int * intPtr; +{ + return (tclStubsPtr->tcl_GetInt)(interp, str, intPtr); +} + +/* Slot 38 */ +int +Tcl_GetIntFromObj(interp, objPtr, intPtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + int * intPtr; +{ + return (tclStubsPtr->tcl_GetIntFromObj)(interp, objPtr, intPtr); +} + +/* Slot 39 */ +int +Tcl_GetLongFromObj(interp, objPtr, longPtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + long * longPtr; +{ + return (tclStubsPtr->tcl_GetLongFromObj)(interp, objPtr, longPtr); +} + +/* Slot 40 */ +Tcl_ObjType * +Tcl_GetObjType(typeName) + char * typeName; +{ + return (tclStubsPtr->tcl_GetObjType)(typeName); +} + +/* Slot 41 */ +char * +Tcl_GetStringFromObj(objPtr, lengthPtr) + Tcl_Obj * objPtr; + int * lengthPtr; +{ + return (tclStubsPtr->tcl_GetStringFromObj)(objPtr, lengthPtr); +} + +/* Slot 42 */ +void +Tcl_InvalidateStringRep(objPtr) + Tcl_Obj * objPtr; +{ + (tclStubsPtr->tcl_InvalidateStringRep)(objPtr); +} + +/* Slot 43 */ +int +Tcl_ListObjAppendList(interp, listPtr, elemListPtr) + Tcl_Interp * interp; + Tcl_Obj * listPtr; + Tcl_Obj * elemListPtr; +{ + return (tclStubsPtr->tcl_ListObjAppendList)(interp, listPtr, elemListPtr); +} + +/* Slot 44 */ +int +Tcl_ListObjAppendElement(interp, listPtr, objPtr) + Tcl_Interp * interp; + Tcl_Obj * listPtr; + Tcl_Obj * objPtr; +{ + return (tclStubsPtr->tcl_ListObjAppendElement)(interp, listPtr, objPtr); +} + +/* Slot 45 */ +int +Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr) + Tcl_Interp * interp; + Tcl_Obj * listPtr; + int * objcPtr; + Tcl_Obj *** objvPtr; +{ + return (tclStubsPtr->tcl_ListObjGetElements)(interp, listPtr, objcPtr, objvPtr); +} + +/* Slot 46 */ +int +Tcl_ListObjIndex(interp, listPtr, index, objPtrPtr) + Tcl_Interp * interp; + Tcl_Obj * listPtr; + int index; + Tcl_Obj ** objPtrPtr; +{ + return (tclStubsPtr->tcl_ListObjIndex)(interp, listPtr, index, objPtrPtr); +} + +/* Slot 47 */ +int +Tcl_ListObjLength(interp, listPtr, intPtr) + Tcl_Interp * interp; + Tcl_Obj * listPtr; + int * intPtr; +{ + return (tclStubsPtr->tcl_ListObjLength)(interp, listPtr, intPtr); +} + +/* Slot 48 */ +int +Tcl_ListObjReplace(interp, listPtr, first, count, objc, objv) + Tcl_Interp * interp; + Tcl_Obj * listPtr; + int first; + int count; + int objc; + Tcl_Obj *CONST objv[]; +{ + return (tclStubsPtr->tcl_ListObjReplace)(interp, listPtr, first, count, objc, objv); +} + +/* Slot 49 */ +Tcl_Obj * +Tcl_NewBooleanObj(boolValue) + int boolValue; +{ + return (tclStubsPtr->tcl_NewBooleanObj)(boolValue); +} + +/* Slot 50 */ +Tcl_Obj * +Tcl_NewByteArrayObj(bytes, length) + unsigned char * bytes; + int length; +{ + return (tclStubsPtr->tcl_NewByteArrayObj)(bytes, length); +} + +/* Slot 51 */ +Tcl_Obj * +Tcl_NewDoubleObj(doubleValue) + double doubleValue; +{ + return (tclStubsPtr->tcl_NewDoubleObj)(doubleValue); +} + +/* Slot 52 */ +Tcl_Obj * +Tcl_NewIntObj(intValue) + int intValue; +{ + return (tclStubsPtr->tcl_NewIntObj)(intValue); +} + +/* Slot 53 */ +Tcl_Obj * +Tcl_NewListObj(objc, objv) + int objc; + Tcl_Obj *CONST objv[]; +{ + return (tclStubsPtr->tcl_NewListObj)(objc, objv); +} + +/* Slot 54 */ +Tcl_Obj * +Tcl_NewLongObj(longValue) + long longValue; +{ + return (tclStubsPtr->tcl_NewLongObj)(longValue); +} + +/* Slot 55 */ +Tcl_Obj * +Tcl_NewObj() +{ + return (tclStubsPtr->tcl_NewObj)(); +} + +/* Slot 56 */ +Tcl_Obj * +Tcl_NewStringObj(bytes, length) + CONST char * bytes; + int length; +{ + return (tclStubsPtr->tcl_NewStringObj)(bytes, length); +} + +/* Slot 57 */ +void +Tcl_SetBooleanObj(objPtr, boolValue) + Tcl_Obj * objPtr; + int boolValue; +{ + (tclStubsPtr->tcl_SetBooleanObj)(objPtr, boolValue); +} + +/* Slot 58 */ +unsigned char * +Tcl_SetByteArrayLength(objPtr, length) + Tcl_Obj * objPtr; + int length; +{ + return (tclStubsPtr->tcl_SetByteArrayLength)(objPtr, length); +} + +/* Slot 59 */ +void +Tcl_SetByteArrayObj(objPtr, bytes, length) + Tcl_Obj * objPtr; + unsigned char * bytes; + int length; +{ + (tclStubsPtr->tcl_SetByteArrayObj)(objPtr, bytes, length); +} + +/* Slot 60 */ +void +Tcl_SetDoubleObj(objPtr, doubleValue) + Tcl_Obj * objPtr; + double doubleValue; +{ + (tclStubsPtr->tcl_SetDoubleObj)(objPtr, doubleValue); +} + +/* Slot 61 */ +void +Tcl_SetIntObj(objPtr, intValue) + Tcl_Obj * objPtr; + int intValue; +{ + (tclStubsPtr->tcl_SetIntObj)(objPtr, intValue); +} + +/* Slot 62 */ +void +Tcl_SetListObj(objPtr, objc, objv) + Tcl_Obj * objPtr; + int objc; + Tcl_Obj *CONST objv[]; +{ + (tclStubsPtr->tcl_SetListObj)(objPtr, objc, objv); +} + +/* Slot 63 */ +void +Tcl_SetLongObj(objPtr, longValue) + Tcl_Obj * objPtr; + long longValue; +{ + (tclStubsPtr->tcl_SetLongObj)(objPtr, longValue); +} + +/* Slot 64 */ +void +Tcl_SetObjLength(objPtr, length) + Tcl_Obj * objPtr; + int length; +{ + (tclStubsPtr->tcl_SetObjLength)(objPtr, length); +} + +/* Slot 65 */ +void +Tcl_SetStringObj(objPtr, bytes, length) + Tcl_Obj * objPtr; + char * bytes; + int length; +{ + (tclStubsPtr->tcl_SetStringObj)(objPtr, bytes, length); +} + +/* Slot 66 */ +void +Tcl_AddErrorInfo(interp, message) + Tcl_Interp * interp; + CONST char * message; +{ + (tclStubsPtr->tcl_AddErrorInfo)(interp, message); +} + +/* Slot 67 */ +void +Tcl_AddObjErrorInfo(interp, message, length) + Tcl_Interp * interp; + CONST char * message; + int length; +{ + (tclStubsPtr->tcl_AddObjErrorInfo)(interp, message, length); +} + +/* Slot 68 */ +void +Tcl_AllowExceptions(interp) + Tcl_Interp * interp; +{ + (tclStubsPtr->tcl_AllowExceptions)(interp); +} + +/* Slot 69 */ +void +Tcl_AppendElement(interp, string) + Tcl_Interp * interp; + CONST char * string; +{ + (tclStubsPtr->tcl_AppendElement)(interp, string); +} + +/* Slot 70 */ +void +Tcl_AppendResult TCL_VARARGS_DEF(Tcl_Interp *,interp) +{ + Tcl_Interp * var; + va_list argList; + + var = (Tcl_Interp *) TCL_VARARGS_START(Tcl_Interp *,interp,argList); + + (tclStubsPtr->tcl_AppendResultVA)(var, argList); + va_end(argList); +} + +/* Slot 71 */ +Tcl_AsyncHandler +Tcl_AsyncCreate(proc, clientData) + Tcl_AsyncProc * proc; + ClientData clientData; +{ + return (tclStubsPtr->tcl_AsyncCreate)(proc, clientData); +} + +/* Slot 72 */ +void +Tcl_AsyncDelete(async) + Tcl_AsyncHandler async; +{ + (tclStubsPtr->tcl_AsyncDelete)(async); +} + +/* Slot 73 */ +int +Tcl_AsyncInvoke(interp, code) + Tcl_Interp * interp; + int code; +{ + return (tclStubsPtr->tcl_AsyncInvoke)(interp, code); +} + +/* Slot 74 */ +void +Tcl_AsyncMark(async) + Tcl_AsyncHandler async; +{ + (tclStubsPtr->tcl_AsyncMark)(async); +} + +/* Slot 75 */ +int +Tcl_AsyncReady() +{ + return (tclStubsPtr->tcl_AsyncReady)(); +} + +/* Slot 76 */ +void +Tcl_BackgroundError(interp) + Tcl_Interp * interp; +{ + (tclStubsPtr->tcl_BackgroundError)(interp); +} + +/* Slot 77 */ +char +Tcl_Backslash(src, readPtr) + CONST char * src; + int * readPtr; +{ + return (tclStubsPtr->tcl_Backslash)(src, readPtr); +} + +/* Slot 78 */ +int +Tcl_BadChannelOption(interp, optionName, optionList) + Tcl_Interp * interp; + char * optionName; + char * optionList; +{ + return (tclStubsPtr->tcl_BadChannelOption)(interp, optionName, optionList); +} + +/* Slot 79 */ +void +Tcl_CallWhenDeleted(interp, proc, clientData) + Tcl_Interp * interp; + Tcl_InterpDeleteProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_CallWhenDeleted)(interp, proc, clientData); +} + +/* Slot 80 */ +void +Tcl_CancelIdleCall(idleProc, clientData) + Tcl_IdleProc * idleProc; + ClientData clientData; +{ + (tclStubsPtr->tcl_CancelIdleCall)(idleProc, clientData); +} + +/* Slot 81 */ +int +Tcl_Close(interp, chan) + Tcl_Interp * interp; + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_Close)(interp, chan); +} + +/* Slot 82 */ +int +Tcl_CommandComplete(cmd) + char * cmd; +{ + return (tclStubsPtr->tcl_CommandComplete)(cmd); +} + +/* Slot 83 */ +char * +Tcl_Concat(argc, argv) + int argc; + char ** argv; +{ + return (tclStubsPtr->tcl_Concat)(argc, argv); +} + +/* Slot 84 */ +int +Tcl_ConvertElement(src, dst, flags) + CONST char * src; + char * dst; + int flags; +{ + return (tclStubsPtr->tcl_ConvertElement)(src, dst, flags); +} + +/* Slot 85 */ +int +Tcl_ConvertCountedElement(src, length, dst, flags) + CONST char * src; + int length; + char * dst; + int flags; +{ + return (tclStubsPtr->tcl_ConvertCountedElement)(src, length, dst, flags); +} + +/* Slot 86 */ +int +Tcl_CreateAlias(slave, slaveCmd, target, targetCmd, argc, argv) + Tcl_Interp * slave; + char * slaveCmd; + Tcl_Interp * target; + char * targetCmd; + int argc; + char ** argv; +{ + return (tclStubsPtr->tcl_CreateAlias)(slave, slaveCmd, target, targetCmd, argc, argv); +} + +/* Slot 87 */ +int +Tcl_CreateAliasObj(slave, slaveCmd, target, targetCmd, objc, objv) + Tcl_Interp * slave; + char * slaveCmd; + Tcl_Interp * target; + char * targetCmd; + int objc; + Tcl_Obj *CONST objv[]; +{ + return (tclStubsPtr->tcl_CreateAliasObj)(slave, slaveCmd, target, targetCmd, objc, objv); +} + +/* Slot 88 */ +Tcl_Channel +Tcl_CreateChannel(typePtr, chanName, instanceData, mask) + Tcl_ChannelType * typePtr; + char * chanName; + ClientData instanceData; + int mask; +{ + return (tclStubsPtr->tcl_CreateChannel)(typePtr, chanName, instanceData, mask); +} + +/* Slot 89 */ +void +Tcl_CreateChannelHandler(chan, mask, proc, clientData) + Tcl_Channel chan; + int mask; + Tcl_ChannelProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_CreateChannelHandler)(chan, mask, proc, clientData); +} + +/* Slot 90 */ +void +Tcl_CreateCloseHandler(chan, proc, clientData) + Tcl_Channel chan; + Tcl_CloseProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_CreateCloseHandler)(chan, proc, clientData); +} + +/* Slot 91 */ +Tcl_Command +Tcl_CreateCommand(interp, cmdName, proc, clientData, deleteProc) + Tcl_Interp * interp; + char * cmdName; + Tcl_CmdProc * proc; + ClientData clientData; + Tcl_CmdDeleteProc * deleteProc; +{ + return (tclStubsPtr->tcl_CreateCommand)(interp, cmdName, proc, clientData, deleteProc); +} + +/* Slot 92 */ +void +Tcl_CreateEventSource(setupProc, checkProc, clientData) + Tcl_EventSetupProc * setupProc; + Tcl_EventCheckProc * checkProc; + ClientData clientData; +{ + (tclStubsPtr->tcl_CreateEventSource)(setupProc, checkProc, clientData); +} + +/* Slot 93 */ +void +Tcl_CreateExitHandler(proc, clientData) + Tcl_ExitProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_CreateExitHandler)(proc, clientData); +} + +/* Slot 94 */ +Tcl_Interp * +Tcl_CreateInterp() +{ + return (tclStubsPtr->tcl_CreateInterp)(); +} + +/* Slot 95 */ +void +Tcl_CreateMathFunc(interp, name, numArgs, argTypes, proc, clientData) + Tcl_Interp * interp; + char * name; + int numArgs; + Tcl_ValueType * argTypes; + Tcl_MathProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_CreateMathFunc)(interp, name, numArgs, argTypes, proc, clientData); +} + +/* Slot 96 */ +Tcl_Command +Tcl_CreateObjCommand(interp, cmdName, proc, clientData, deleteProc) + Tcl_Interp * interp; + char * cmdName; + Tcl_ObjCmdProc * proc; + ClientData clientData; + Tcl_CmdDeleteProc * deleteProc; +{ + return (tclStubsPtr->tcl_CreateObjCommand)(interp, cmdName, proc, clientData, deleteProc); +} + +/* Slot 97 */ +Tcl_Interp * +Tcl_CreateSlave(interp, slaveName, isSafe) + Tcl_Interp * interp; + char * slaveName; + int isSafe; +{ + return (tclStubsPtr->tcl_CreateSlave)(interp, slaveName, isSafe); +} + +/* Slot 98 */ +Tcl_TimerToken +Tcl_CreateTimerHandler(milliseconds, proc, clientData) + int milliseconds; + Tcl_TimerProc * proc; + ClientData clientData; +{ + return (tclStubsPtr->tcl_CreateTimerHandler)(milliseconds, proc, clientData); +} + +/* Slot 99 */ +Tcl_Trace +Tcl_CreateTrace(interp, level, proc, clientData) + Tcl_Interp * interp; + int level; + Tcl_CmdTraceProc * proc; + ClientData clientData; +{ + return (tclStubsPtr->tcl_CreateTrace)(interp, level, proc, clientData); +} + +/* Slot 100 */ +void +Tcl_DeleteAssocData(interp, name) + Tcl_Interp * interp; + char * name; +{ + (tclStubsPtr->tcl_DeleteAssocData)(interp, name); +} + +/* Slot 101 */ +void +Tcl_DeleteChannelHandler(chan, proc, clientData) + Tcl_Channel chan; + Tcl_ChannelProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_DeleteChannelHandler)(chan, proc, clientData); +} + +/* Slot 102 */ +void +Tcl_DeleteCloseHandler(chan, proc, clientData) + Tcl_Channel chan; + Tcl_CloseProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_DeleteCloseHandler)(chan, proc, clientData); +} + +/* Slot 103 */ +int +Tcl_DeleteCommand(interp, cmdName) + Tcl_Interp * interp; + char * cmdName; +{ + return (tclStubsPtr->tcl_DeleteCommand)(interp, cmdName); +} + +/* Slot 104 */ +int +Tcl_DeleteCommandFromToken(interp, command) + Tcl_Interp * interp; + Tcl_Command command; +{ + return (tclStubsPtr->tcl_DeleteCommandFromToken)(interp, command); +} + +/* Slot 105 */ +void +Tcl_DeleteEvents(proc, clientData) + Tcl_EventDeleteProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_DeleteEvents)(proc, clientData); +} + +/* Slot 106 */ +void +Tcl_DeleteEventSource(setupProc, checkProc, clientData) + Tcl_EventSetupProc * setupProc; + Tcl_EventCheckProc * checkProc; + ClientData clientData; +{ + (tclStubsPtr->tcl_DeleteEventSource)(setupProc, checkProc, clientData); +} + +/* Slot 107 */ +void +Tcl_DeleteExitHandler(proc, clientData) + Tcl_ExitProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_DeleteExitHandler)(proc, clientData); +} + +/* Slot 108 */ +void +Tcl_DeleteHashEntry(entryPtr) + Tcl_HashEntry * entryPtr; +{ + (tclStubsPtr->tcl_DeleteHashEntry)(entryPtr); +} + +/* Slot 109 */ +void +Tcl_DeleteHashTable(tablePtr) + Tcl_HashTable * tablePtr; +{ + (tclStubsPtr->tcl_DeleteHashTable)(tablePtr); +} + +/* Slot 110 */ +void +Tcl_DeleteInterp(interp) + Tcl_Interp * interp; +{ + (tclStubsPtr->tcl_DeleteInterp)(interp); +} + +/* Slot 111 */ +void +Tcl_DetachPids(numPids, pidPtr) + int numPids; + Tcl_Pid * pidPtr; +{ + (tclStubsPtr->tcl_DetachPids)(numPids, pidPtr); +} + +/* Slot 112 */ +void +Tcl_DeleteTimerHandler(token) + Tcl_TimerToken token; +{ + (tclStubsPtr->tcl_DeleteTimerHandler)(token); +} + +/* Slot 113 */ +void +Tcl_DeleteTrace(interp, trace) + Tcl_Interp * interp; + Tcl_Trace trace; +{ + (tclStubsPtr->tcl_DeleteTrace)(interp, trace); +} + +/* Slot 114 */ +void +Tcl_DontCallWhenDeleted(interp, proc, clientData) + Tcl_Interp * interp; + Tcl_InterpDeleteProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_DontCallWhenDeleted)(interp, proc, clientData); +} + +/* Slot 115 */ +int +Tcl_DoOneEvent(flags) + int flags; +{ + return (tclStubsPtr->tcl_DoOneEvent)(flags); +} + +/* Slot 116 */ +void +Tcl_DoWhenIdle(proc, clientData) + Tcl_IdleProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_DoWhenIdle)(proc, clientData); +} + +/* Slot 117 */ +char * +Tcl_DStringAppend(dsPtr, str, length) + Tcl_DString * dsPtr; + CONST char * str; + int length; +{ + return (tclStubsPtr->tcl_DStringAppend)(dsPtr, str, length); +} + +/* Slot 118 */ +char * +Tcl_DStringAppendElement(dsPtr, string) + Tcl_DString * dsPtr; + CONST char * string; +{ + return (tclStubsPtr->tcl_DStringAppendElement)(dsPtr, string); +} + +/* Slot 119 */ +void +Tcl_DStringEndSublist(dsPtr) + Tcl_DString * dsPtr; +{ + (tclStubsPtr->tcl_DStringEndSublist)(dsPtr); +} + +/* Slot 120 */ +void +Tcl_DStringFree(dsPtr) + Tcl_DString * dsPtr; +{ + (tclStubsPtr->tcl_DStringFree)(dsPtr); +} + +/* Slot 121 */ +void +Tcl_DStringGetResult(interp, dsPtr) + Tcl_Interp * interp; + Tcl_DString * dsPtr; +{ + (tclStubsPtr->tcl_DStringGetResult)(interp, dsPtr); +} + +/* Slot 122 */ +void +Tcl_DStringInit(dsPtr) + Tcl_DString * dsPtr; +{ + (tclStubsPtr->tcl_DStringInit)(dsPtr); +} + +/* Slot 123 */ +void +Tcl_DStringResult(interp, dsPtr) + Tcl_Interp * interp; + Tcl_DString * dsPtr; +{ + (tclStubsPtr->tcl_DStringResult)(interp, dsPtr); +} + +/* Slot 124 */ +void +Tcl_DStringSetLength(dsPtr, length) + Tcl_DString * dsPtr; + int length; +{ + (tclStubsPtr->tcl_DStringSetLength)(dsPtr, length); +} + +/* Slot 125 */ +void +Tcl_DStringStartSublist(dsPtr) + Tcl_DString * dsPtr; +{ + (tclStubsPtr->tcl_DStringStartSublist)(dsPtr); +} + +/* Slot 126 */ +int +Tcl_Eof(chan) + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_Eof)(chan); +} + +/* Slot 127 */ +char * +Tcl_ErrnoId() +{ + return (tclStubsPtr->tcl_ErrnoId)(); +} + +/* Slot 128 */ +char * +Tcl_ErrnoMsg(err) + int err; +{ + return (tclStubsPtr->tcl_ErrnoMsg)(err); +} + +/* Slot 129 */ +int +Tcl_Eval(interp, string) + Tcl_Interp * interp; + char * string; +{ + return (tclStubsPtr->tcl_Eval)(interp, string); +} + +/* Slot 130 */ +int +Tcl_EvalFile(interp, fileName) + Tcl_Interp * interp; + char * fileName; +{ + return (tclStubsPtr->tcl_EvalFile)(interp, fileName); +} + +/* Slot 131 */ +int +Tcl_EvalObj(interp, objPtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; +{ + return (tclStubsPtr->tcl_EvalObj)(interp, objPtr); +} + +/* Slot 132 */ +void +Tcl_EventuallyFree(clientData, freeProc) + ClientData clientData; + Tcl_FreeProc * freeProc; +{ + (tclStubsPtr->tcl_EventuallyFree)(clientData, freeProc); +} + +/* Slot 133 */ +void +Tcl_Exit(status) + int status; +{ + (tclStubsPtr->tcl_Exit)(status); +} + +/* Slot 134 */ +int +Tcl_ExposeCommand(interp, hiddenCmdToken, cmdName) + Tcl_Interp * interp; + char * hiddenCmdToken; + char * cmdName; +{ + return (tclStubsPtr->tcl_ExposeCommand)(interp, hiddenCmdToken, cmdName); +} + +/* Slot 135 */ +int +Tcl_ExprBoolean(interp, str, ptr) + Tcl_Interp * interp; + char * str; + int * ptr; +{ + return (tclStubsPtr->tcl_ExprBoolean)(interp, str, ptr); +} + +/* Slot 136 */ +int +Tcl_ExprBooleanObj(interp, objPtr, ptr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + int * ptr; +{ + return (tclStubsPtr->tcl_ExprBooleanObj)(interp, objPtr, ptr); +} + +/* Slot 137 */ +int +Tcl_ExprDouble(interp, str, ptr) + Tcl_Interp * interp; + char * str; + double * ptr; +{ + return (tclStubsPtr->tcl_ExprDouble)(interp, str, ptr); +} + +/* Slot 138 */ +int +Tcl_ExprDoubleObj(interp, objPtr, ptr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + double * ptr; +{ + return (tclStubsPtr->tcl_ExprDoubleObj)(interp, objPtr, ptr); +} + +/* Slot 139 */ +int +Tcl_ExprLong(interp, str, ptr) + Tcl_Interp * interp; + char * str; + long * ptr; +{ + return (tclStubsPtr->tcl_ExprLong)(interp, str, ptr); +} + +/* Slot 140 */ +int +Tcl_ExprLongObj(interp, objPtr, ptr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + long * ptr; +{ + return (tclStubsPtr->tcl_ExprLongObj)(interp, objPtr, ptr); +} + +/* Slot 141 */ +int +Tcl_ExprObj(interp, objPtr, resultPtrPtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + Tcl_Obj ** resultPtrPtr; +{ + return (tclStubsPtr->tcl_ExprObj)(interp, objPtr, resultPtrPtr); +} + +/* Slot 142 */ +int +Tcl_ExprString(interp, string) + Tcl_Interp * interp; + char * string; +{ + return (tclStubsPtr->tcl_ExprString)(interp, string); +} + +/* Slot 143 */ +void +Tcl_Finalize() +{ + (tclStubsPtr->tcl_Finalize)(); +} + +/* Slot 144 */ +void +Tcl_FindExecutable(argv0) + CONST char * argv0; +{ + (tclStubsPtr->tcl_FindExecutable)(argv0); +} + +/* Slot 145 */ +Tcl_HashEntry * +Tcl_FirstHashEntry(tablePtr, searchPtr) + Tcl_HashTable * tablePtr; + Tcl_HashSearch * searchPtr; +{ + return (tclStubsPtr->tcl_FirstHashEntry)(tablePtr, searchPtr); +} + +/* Slot 146 */ +int +Tcl_Flush(chan) + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_Flush)(chan); +} + +/* Slot 147 */ +void +Tcl_FreeResult(interp) + Tcl_Interp * interp; +{ + (tclStubsPtr->tcl_FreeResult)(interp); +} + +/* Slot 148 */ +int +Tcl_GetAlias(interp, slaveCmd, targetInterpPtr, targetCmdPtr, argcPtr, argvPtr) + Tcl_Interp * interp; + char * slaveCmd; + Tcl_Interp ** targetInterpPtr; + char ** targetCmdPtr; + int * argcPtr; + char *** argvPtr; +{ + return (tclStubsPtr->tcl_GetAlias)(interp, slaveCmd, targetInterpPtr, targetCmdPtr, argcPtr, argvPtr); +} + +/* Slot 149 */ +int +Tcl_GetAliasObj(interp, slaveCmd, targetInterpPtr, targetCmdPtr, objcPtr, objv) + Tcl_Interp * interp; + char * slaveCmd; + Tcl_Interp ** targetInterpPtr; + char ** targetCmdPtr; + int * objcPtr; + Tcl_Obj *** objv; +{ + return (tclStubsPtr->tcl_GetAliasObj)(interp, slaveCmd, targetInterpPtr, targetCmdPtr, objcPtr, objv); +} + +/* Slot 150 */ +ClientData +Tcl_GetAssocData(interp, name, procPtr) + Tcl_Interp * interp; + char * name; + Tcl_InterpDeleteProc ** procPtr; +{ + return (tclStubsPtr->tcl_GetAssocData)(interp, name, procPtr); +} + +/* Slot 151 */ +Tcl_Channel +Tcl_GetChannel(interp, chanName, modePtr) + Tcl_Interp * interp; + char * chanName; + int * modePtr; +{ + return (tclStubsPtr->tcl_GetChannel)(interp, chanName, modePtr); +} + +/* Slot 152 */ +int +Tcl_GetChannelBufferSize(chan) + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_GetChannelBufferSize)(chan); +} + +/* Slot 153 */ +int +Tcl_GetChannelHandle(chan, direction, handlePtr) + Tcl_Channel chan; + int direction; + ClientData * handlePtr; +{ + return (tclStubsPtr->tcl_GetChannelHandle)(chan, direction, handlePtr); +} + +/* Slot 154 */ +ClientData +Tcl_GetChannelInstanceData(chan) + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_GetChannelInstanceData)(chan); +} + +/* Slot 155 */ +int +Tcl_GetChannelMode(chan) + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_GetChannelMode)(chan); +} + +/* Slot 156 */ +char * +Tcl_GetChannelName(chan) + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_GetChannelName)(chan); +} + +/* Slot 157 */ +int +Tcl_GetChannelOption(interp, chan, optionName, dsPtr) + Tcl_Interp * interp; + Tcl_Channel chan; + char * optionName; + Tcl_DString * dsPtr; +{ + return (tclStubsPtr->tcl_GetChannelOption)(interp, chan, optionName, dsPtr); +} + +/* Slot 158 */ +Tcl_ChannelType * +Tcl_GetChannelType(chan) + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_GetChannelType)(chan); +} + +/* Slot 159 */ +int +Tcl_GetCommandInfo(interp, cmdName, infoPtr) + Tcl_Interp * interp; + char * cmdName; + Tcl_CmdInfo * infoPtr; +{ + return (tclStubsPtr->tcl_GetCommandInfo)(interp, cmdName, infoPtr); +} + +/* Slot 160 */ +char * +Tcl_GetCommandName(interp, command) + Tcl_Interp * interp; + Tcl_Command command; +{ + return (tclStubsPtr->tcl_GetCommandName)(interp, command); +} + +/* Slot 161 */ +int +Tcl_GetErrno() +{ + return (tclStubsPtr->tcl_GetErrno)(); +} + +/* Slot 162 */ +char * +Tcl_GetHostName() +{ + return (tclStubsPtr->tcl_GetHostName)(); +} + +/* Slot 163 */ +int +Tcl_GetInterpPath(askInterp, slaveInterp) + Tcl_Interp * askInterp; + Tcl_Interp * slaveInterp; +{ + return (tclStubsPtr->tcl_GetInterpPath)(askInterp, slaveInterp); +} + +/* Slot 164 */ +Tcl_Interp * +Tcl_GetMaster(interp) + Tcl_Interp * interp; +{ + return (tclStubsPtr->tcl_GetMaster)(interp); +} + +/* Slot 165 */ +CONST char * +Tcl_GetNameOfExecutable() +{ + return (tclStubsPtr->tcl_GetNameOfExecutable)(); +} + +/* Slot 166 */ +Tcl_Obj * +Tcl_GetObjResult(interp) + Tcl_Interp * interp; +{ + return (tclStubsPtr->tcl_GetObjResult)(interp); +} + +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* Slot 167 */ +int +Tcl_GetOpenFile(interp, str, write, checkUsage, filePtr) + Tcl_Interp * interp; + char * str; + int write; + int checkUsage; + ClientData * filePtr; +{ + return (tclStubsPtr->tcl_GetOpenFile)(interp, str, write, checkUsage, filePtr); +} + +#endif /* UNIX */ +/* Slot 168 */ +Tcl_PathType +Tcl_GetPathType(path) + char * path; +{ + return (tclStubsPtr->tcl_GetPathType)(path); +} + +/* Slot 169 */ +int +Tcl_Gets(chan, dsPtr) + Tcl_Channel chan; + Tcl_DString * dsPtr; +{ + return (tclStubsPtr->tcl_Gets)(chan, dsPtr); +} + +/* Slot 170 */ +int +Tcl_GetsObj(chan, objPtr) + Tcl_Channel chan; + Tcl_Obj * objPtr; +{ + return (tclStubsPtr->tcl_GetsObj)(chan, objPtr); +} + +/* Slot 171 */ +int +Tcl_GetServiceMode() +{ + return (tclStubsPtr->tcl_GetServiceMode)(); +} + +/* Slot 172 */ +Tcl_Interp * +Tcl_GetSlave(interp, slaveName) + Tcl_Interp * interp; + char * slaveName; +{ + return (tclStubsPtr->tcl_GetSlave)(interp, slaveName); +} + +/* Slot 173 */ +Tcl_Channel +Tcl_GetStdChannel(type) + int type; +{ + return (tclStubsPtr->tcl_GetStdChannel)(type); +} + +/* Slot 174 */ +char * +Tcl_GetStringResult(interp) + Tcl_Interp * interp; +{ + return (tclStubsPtr->tcl_GetStringResult)(interp); +} + +/* Slot 175 */ +char * +Tcl_GetVar(interp, varName, flags) + Tcl_Interp * interp; + char * varName; + int flags; +{ + return (tclStubsPtr->tcl_GetVar)(interp, varName, flags); +} + +/* Slot 176 */ +char * +Tcl_GetVar2(interp, part1, part2, flags) + Tcl_Interp * interp; + char * part1; + char * part2; + int flags; +{ + return (tclStubsPtr->tcl_GetVar2)(interp, part1, part2, flags); +} + +/* Slot 177 */ +int +Tcl_GlobalEval(interp, command) + Tcl_Interp * interp; + char * command; +{ + return (tclStubsPtr->tcl_GlobalEval)(interp, command); +} + +/* Slot 178 */ +int +Tcl_GlobalEvalObj(interp, objPtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; +{ + return (tclStubsPtr->tcl_GlobalEvalObj)(interp, objPtr); +} + +/* Slot 179 */ +int +Tcl_HideCommand(interp, cmdName, hiddenCmdToken) + Tcl_Interp * interp; + char * cmdName; + char * hiddenCmdToken; +{ + return (tclStubsPtr->tcl_HideCommand)(interp, cmdName, hiddenCmdToken); +} + +/* Slot 180 */ +int +Tcl_Init(interp) + Tcl_Interp * interp; +{ + return (tclStubsPtr->tcl_Init)(interp); +} + +/* Slot 181 */ +void +Tcl_InitHashTable(tablePtr, keyType) + Tcl_HashTable * tablePtr; + int keyType; +{ + (tclStubsPtr->tcl_InitHashTable)(tablePtr, keyType); +} + +/* Slot 182 */ +int +Tcl_InputBlocked(chan) + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_InputBlocked)(chan); +} + +/* Slot 183 */ +int +Tcl_InputBuffered(chan) + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_InputBuffered)(chan); +} + +/* Slot 184 */ +int +Tcl_InterpDeleted(interp) + Tcl_Interp * interp; +{ + return (tclStubsPtr->tcl_InterpDeleted)(interp); +} + +/* Slot 185 */ +int +Tcl_IsSafe(interp) + Tcl_Interp * interp; +{ + return (tclStubsPtr->tcl_IsSafe)(interp); +} + +/* Slot 186 */ +char * +Tcl_JoinPath(argc, argv, resultPtr) + int argc; + CONST char ** argv; + Tcl_DString * resultPtr; +{ + return (tclStubsPtr->tcl_JoinPath)(argc, argv, resultPtr); +} + +/* Slot 187 */ +int +Tcl_LinkVar(interp, varName, addr, type) + Tcl_Interp * interp; + char * varName; + char * addr; + int type; +{ + return (tclStubsPtr->tcl_LinkVar)(interp, varName, addr, type); +} + +/* Slot 188 is reserved */ +/* Slot 189 */ +Tcl_Channel +Tcl_MakeFileChannel(handle, mode) + ClientData handle; + int mode; +{ + return (tclStubsPtr->tcl_MakeFileChannel)(handle, mode); +} + +/* Slot 190 */ +int +Tcl_MakeSafe(interp) + Tcl_Interp * interp; +{ + return (tclStubsPtr->tcl_MakeSafe)(interp); +} + +/* Slot 191 */ +Tcl_Channel +Tcl_MakeTcpClientChannel(tcpSocket) + ClientData tcpSocket; +{ + return (tclStubsPtr->tcl_MakeTcpClientChannel)(tcpSocket); +} + +/* Slot 192 */ +char * +Tcl_Merge(argc, argv) + int argc; + char ** argv; +{ + return (tclStubsPtr->tcl_Merge)(argc, argv); +} + +/* Slot 193 */ +Tcl_HashEntry * +Tcl_NextHashEntry(searchPtr) + Tcl_HashSearch * searchPtr; +{ + return (tclStubsPtr->tcl_NextHashEntry)(searchPtr); +} + +/* Slot 194 */ +void +Tcl_NotifyChannel(channel, mask) + Tcl_Channel channel; + int mask; +{ + (tclStubsPtr->tcl_NotifyChannel)(channel, mask); +} + +/* Slot 195 */ +Tcl_Obj * +Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags) + Tcl_Interp * interp; + Tcl_Obj * part1Ptr; + Tcl_Obj * part2Ptr; + int flags; +{ + return (tclStubsPtr->tcl_ObjGetVar2)(interp, part1Ptr, part2Ptr, flags); +} + +/* Slot 196 */ +Tcl_Obj * +Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, newValuePtr, flags) + Tcl_Interp * interp; + Tcl_Obj * part1Ptr; + Tcl_Obj * part2Ptr; + Tcl_Obj * newValuePtr; + int flags; +{ + return (tclStubsPtr->tcl_ObjSetVar2)(interp, part1Ptr, part2Ptr, newValuePtr, flags); +} + +/* Slot 197 */ +Tcl_Channel +Tcl_OpenCommandChannel(interp, argc, argv, flags) + Tcl_Interp * interp; + int argc; + char ** argv; + int flags; +{ + return (tclStubsPtr->tcl_OpenCommandChannel)(interp, argc, argv, flags); +} + +/* Slot 198 */ +Tcl_Channel +Tcl_OpenFileChannel(interp, fileName, modeString, permissions) + Tcl_Interp * interp; + char * fileName; + char * modeString; + int permissions; +{ + return (tclStubsPtr->tcl_OpenFileChannel)(interp, fileName, modeString, permissions); +} + +/* Slot 199 */ +Tcl_Channel +Tcl_OpenTcpClient(interp, port, address, myaddr, myport, async) + Tcl_Interp * interp; + int port; + char * address; + char * myaddr; + int myport; + int async; +{ + return (tclStubsPtr->tcl_OpenTcpClient)(interp, port, address, myaddr, myport, async); +} + +/* Slot 200 */ +Tcl_Channel +Tcl_OpenTcpServer(interp, port, host, acceptProc, callbackData) + Tcl_Interp * interp; + int port; + char * host; + Tcl_TcpAcceptProc * acceptProc; + ClientData callbackData; +{ + return (tclStubsPtr->tcl_OpenTcpServer)(interp, port, host, acceptProc, callbackData); +} + +/* Slot 201 */ +void +Tcl_Preserve(data) + ClientData data; +{ + (tclStubsPtr->tcl_Preserve)(data); +} + +/* Slot 202 */ +void +Tcl_PrintDouble(interp, value, dst) + Tcl_Interp * interp; + double value; + char * dst; +{ + (tclStubsPtr->tcl_PrintDouble)(interp, value, dst); +} + +/* Slot 203 */ +int +Tcl_PutEnv(string) + CONST char * string; +{ + return (tclStubsPtr->tcl_PutEnv)(string); +} + +/* Slot 204 */ +char * +Tcl_PosixError(interp) + Tcl_Interp * interp; +{ + return (tclStubsPtr->tcl_PosixError)(interp); +} + +/* Slot 205 */ +void +Tcl_QueueEvent(evPtr, position) + Tcl_Event * evPtr; + Tcl_QueuePosition position; +{ + (tclStubsPtr->tcl_QueueEvent)(evPtr, position); +} + +/* Slot 206 */ +int +Tcl_Read(chan, bufPtr, toRead) + Tcl_Channel chan; + char * bufPtr; + int toRead; +{ + return (tclStubsPtr->tcl_Read)(chan, bufPtr, toRead); +} + +/* Slot 207 */ +void +Tcl_ReapDetachedProcs() +{ + (tclStubsPtr->tcl_ReapDetachedProcs)(); +} + +/* Slot 208 */ +int +Tcl_RecordAndEval(interp, cmd, flags) + Tcl_Interp * interp; + char * cmd; + int flags; +{ + return (tclStubsPtr->tcl_RecordAndEval)(interp, cmd, flags); +} + +/* Slot 209 */ +int +Tcl_RecordAndEvalObj(interp, cmdPtr, flags) + Tcl_Interp * interp; + Tcl_Obj * cmdPtr; + int flags; +{ + return (tclStubsPtr->tcl_RecordAndEvalObj)(interp, cmdPtr, flags); +} + +/* Slot 210 */ +void +Tcl_RegisterChannel(interp, chan) + Tcl_Interp * interp; + Tcl_Channel chan; +{ + (tclStubsPtr->tcl_RegisterChannel)(interp, chan); +} + +/* Slot 211 */ +void +Tcl_RegisterObjType(typePtr) + Tcl_ObjType * typePtr; +{ + (tclStubsPtr->tcl_RegisterObjType)(typePtr); +} + +/* Slot 212 */ +Tcl_RegExp +Tcl_RegExpCompile(interp, string) + Tcl_Interp * interp; + char * string; +{ + return (tclStubsPtr->tcl_RegExpCompile)(interp, string); +} + +/* Slot 213 */ +int +Tcl_RegExpExec(interp, regexp, str, start) + Tcl_Interp * interp; + Tcl_RegExp regexp; + CONST char * str; + CONST char * start; +{ + return (tclStubsPtr->tcl_RegExpExec)(interp, regexp, str, start); +} + +/* Slot 214 */ +int +Tcl_RegExpMatch(interp, str, pattern) + Tcl_Interp * interp; + char * str; + char * pattern; +{ + return (tclStubsPtr->tcl_RegExpMatch)(interp, str, pattern); +} + +/* Slot 215 */ +void +Tcl_RegExpRange(regexp, index, startPtr, endPtr) + Tcl_RegExp regexp; + int index; + char ** startPtr; + char ** endPtr; +{ + (tclStubsPtr->tcl_RegExpRange)(regexp, index, startPtr, endPtr); +} + +/* Slot 216 */ +void +Tcl_Release(clientData) + ClientData clientData; +{ + (tclStubsPtr->tcl_Release)(clientData); +} + +/* Slot 217 */ +void +Tcl_ResetResult(interp) + Tcl_Interp * interp; +{ + (tclStubsPtr->tcl_ResetResult)(interp); +} + +/* Slot 218 */ +int +Tcl_ScanElement(str, flagPtr) + CONST char * str; + int * flagPtr; +{ + return (tclStubsPtr->tcl_ScanElement)(str, flagPtr); +} + +/* Slot 219 */ +int +Tcl_ScanCountedElement(str, length, flagPtr) + CONST char * str; + int length; + int * flagPtr; +{ + return (tclStubsPtr->tcl_ScanCountedElement)(str, length, flagPtr); +} + +/* Slot 220 */ +int +Tcl_Seek(chan, offset, mode) + Tcl_Channel chan; + int offset; + int mode; +{ + return (tclStubsPtr->tcl_Seek)(chan, offset, mode); +} + +/* Slot 221 */ +int +Tcl_ServiceAll() +{ + return (tclStubsPtr->tcl_ServiceAll)(); +} + +/* Slot 222 */ +int +Tcl_ServiceEvent(flags) + int flags; +{ + return (tclStubsPtr->tcl_ServiceEvent)(flags); +} + +/* Slot 223 */ +void +Tcl_SetAssocData(interp, name, proc, clientData) + Tcl_Interp * interp; + char * name; + Tcl_InterpDeleteProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_SetAssocData)(interp, name, proc, clientData); +} + +/* Slot 224 */ +void +Tcl_SetChannelBufferSize(chan, sz) + Tcl_Channel chan; + int sz; +{ + (tclStubsPtr->tcl_SetChannelBufferSize)(chan, sz); +} + +/* Slot 225 */ +int +Tcl_SetChannelOption(interp, chan, optionName, newValue) + Tcl_Interp * interp; + Tcl_Channel chan; + char * optionName; + char * newValue; +{ + return (tclStubsPtr->tcl_SetChannelOption)(interp, chan, optionName, newValue); +} + +/* Slot 226 */ +int +Tcl_SetCommandInfo(interp, cmdName, infoPtr) + Tcl_Interp * interp; + char * cmdName; + Tcl_CmdInfo * infoPtr; +{ + return (tclStubsPtr->tcl_SetCommandInfo)(interp, cmdName, infoPtr); +} + +/* Slot 227 */ +void +Tcl_SetErrno(err) + int err; +{ + (tclStubsPtr->tcl_SetErrno)(err); +} + +/* Slot 228 */ +void +Tcl_SetErrorCode TCL_VARARGS_DEF(Tcl_Interp *,interp) +{ + Tcl_Interp * var; + va_list argList; + + var = (Tcl_Interp *) TCL_VARARGS_START(Tcl_Interp *,interp,argList); + + (tclStubsPtr->tcl_SetErrorCodeVA)(var, argList); + va_end(argList); +} + +/* Slot 229 */ +void +Tcl_SetMaxBlockTime(timePtr) + Tcl_Time * timePtr; +{ + (tclStubsPtr->tcl_SetMaxBlockTime)(timePtr); +} + +/* Slot 230 */ +void +Tcl_SetPanicProc(panicProc) + Tcl_PanicProc * panicProc; +{ + (tclStubsPtr->tcl_SetPanicProc)(panicProc); +} + +/* Slot 231 */ +int +Tcl_SetRecursionLimit(interp, depth) + Tcl_Interp * interp; + int depth; +{ + return (tclStubsPtr->tcl_SetRecursionLimit)(interp, depth); +} + +/* Slot 232 */ +void +Tcl_SetResult(interp, str, freeProc) + Tcl_Interp * interp; + char * str; + Tcl_FreeProc * freeProc; +{ + (tclStubsPtr->tcl_SetResult)(interp, str, freeProc); +} + +/* Slot 233 */ +int +Tcl_SetServiceMode(mode) + int mode; +{ + return (tclStubsPtr->tcl_SetServiceMode)(mode); +} + +/* Slot 234 */ +void +Tcl_SetObjErrorCode(interp, errorObjPtr) + Tcl_Interp * interp; + Tcl_Obj * errorObjPtr; +{ + (tclStubsPtr->tcl_SetObjErrorCode)(interp, errorObjPtr); +} + +/* Slot 235 */ +void +Tcl_SetObjResult(interp, resultObjPtr) + Tcl_Interp * interp; + Tcl_Obj * resultObjPtr; +{ + (tclStubsPtr->tcl_SetObjResult)(interp, resultObjPtr); +} + +/* Slot 236 */ +void +Tcl_SetStdChannel(channel, type) + Tcl_Channel channel; + int type; +{ + (tclStubsPtr->tcl_SetStdChannel)(channel, type); +} + +/* Slot 237 */ +char * +Tcl_SetVar(interp, varName, newValue, flags) + Tcl_Interp * interp; + char * varName; + char * newValue; + int flags; +{ + return (tclStubsPtr->tcl_SetVar)(interp, varName, newValue, flags); +} + +/* Slot 238 */ +char * +Tcl_SetVar2(interp, part1, part2, newValue, flags) + Tcl_Interp * interp; + char * part1; + char * part2; + char * newValue; + int flags; +{ + return (tclStubsPtr->tcl_SetVar2)(interp, part1, part2, newValue, flags); +} + +/* Slot 239 */ +char * +Tcl_SignalId(sig) + int sig; +{ + return (tclStubsPtr->tcl_SignalId)(sig); +} + +/* Slot 240 */ +char * +Tcl_SignalMsg(sig) + int sig; +{ + return (tclStubsPtr->tcl_SignalMsg)(sig); +} + +/* Slot 241 */ +void +Tcl_SourceRCFile(interp) + Tcl_Interp * interp; +{ + (tclStubsPtr->tcl_SourceRCFile)(interp); +} + +/* Slot 242 */ +int +Tcl_SplitList(interp, listStr, argcPtr, argvPtr) + Tcl_Interp * interp; + CONST char * listStr; + int * argcPtr; + char *** argvPtr; +{ + return (tclStubsPtr->tcl_SplitList)(interp, listStr, argcPtr, argvPtr); +} + +/* Slot 243 */ +void +Tcl_SplitPath(path, argcPtr, argvPtr) + CONST char * path; + int * argcPtr; + char *** argvPtr; +{ + (tclStubsPtr->tcl_SplitPath)(path, argcPtr, argvPtr); +} + +/* Slot 244 */ +void +Tcl_StaticPackage(interp, pkgName, initProc, safeInitProc) + Tcl_Interp * interp; + char * pkgName; + Tcl_PackageInitProc * initProc; + Tcl_PackageInitProc * safeInitProc; +{ + (tclStubsPtr->tcl_StaticPackage)(interp, pkgName, initProc, safeInitProc); +} + +/* Slot 245 */ +int +Tcl_StringMatch(str, pattern) + CONST char * str; + CONST char * pattern; +{ + return (tclStubsPtr->tcl_StringMatch)(str, pattern); +} + +/* Slot 246 */ +int +Tcl_Tell(chan) + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_Tell)(chan); +} + +/* Slot 247 */ +int +Tcl_TraceVar(interp, varName, flags, proc, clientData) + Tcl_Interp * interp; + char * varName; + int flags; + Tcl_VarTraceProc * proc; + ClientData clientData; +{ + return (tclStubsPtr->tcl_TraceVar)(interp, varName, flags, proc, clientData); +} + +/* Slot 248 */ +int +Tcl_TraceVar2(interp, part1, part2, flags, proc, clientData) + Tcl_Interp * interp; + char * part1; + char * part2; + int flags; + Tcl_VarTraceProc * proc; + ClientData clientData; +{ + return (tclStubsPtr->tcl_TraceVar2)(interp, part1, part2, flags, proc, clientData); +} + +/* Slot 249 */ +char * +Tcl_TranslateFileName(interp, name, bufferPtr) + Tcl_Interp * interp; + CONST char * name; + Tcl_DString * bufferPtr; +{ + return (tclStubsPtr->tcl_TranslateFileName)(interp, name, bufferPtr); +} + +/* Slot 250 */ +int +Tcl_Ungets(chan, str, len, atHead) + Tcl_Channel chan; + char * str; + int len; + int atHead; +{ + return (tclStubsPtr->tcl_Ungets)(chan, str, len, atHead); +} + +/* Slot 251 */ +void +Tcl_UnlinkVar(interp, varName) + Tcl_Interp * interp; + char * varName; +{ + (tclStubsPtr->tcl_UnlinkVar)(interp, varName); +} + +/* Slot 252 */ +int +Tcl_UnregisterChannel(interp, chan) + Tcl_Interp * interp; + Tcl_Channel chan; +{ + return (tclStubsPtr->tcl_UnregisterChannel)(interp, chan); +} + +/* Slot 253 */ +int +Tcl_UnsetVar(interp, varName, flags) + Tcl_Interp * interp; + char * varName; + int flags; +{ + return (tclStubsPtr->tcl_UnsetVar)(interp, varName, flags); +} + +/* Slot 254 */ +int +Tcl_UnsetVar2(interp, part1, part2, flags) + Tcl_Interp * interp; + char * part1; + char * part2; + int flags; +{ + return (tclStubsPtr->tcl_UnsetVar2)(interp, part1, part2, flags); +} + +/* Slot 255 */ +void +Tcl_UntraceVar(interp, varName, flags, proc, clientData) + Tcl_Interp * interp; + char * varName; + int flags; + Tcl_VarTraceProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_UntraceVar)(interp, varName, flags, proc, clientData); +} + +/* Slot 256 */ +void +Tcl_UntraceVar2(interp, part1, part2, flags, proc, clientData) + Tcl_Interp * interp; + char * part1; + char * part2; + int flags; + Tcl_VarTraceProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_UntraceVar2)(interp, part1, part2, flags, proc, clientData); +} + +/* Slot 257 */ +void +Tcl_UpdateLinkedVar(interp, varName) + Tcl_Interp * interp; + char * varName; +{ + (tclStubsPtr->tcl_UpdateLinkedVar)(interp, varName); +} + +/* Slot 258 */ +int +Tcl_UpVar(interp, frameName, varName, localName, flags) + Tcl_Interp * interp; + char * frameName; + char * varName; + char * localName; + int flags; +{ + return (tclStubsPtr->tcl_UpVar)(interp, frameName, varName, localName, flags); +} + +/* Slot 259 */ +int +Tcl_UpVar2(interp, frameName, part1, part2, localName, flags) + Tcl_Interp * interp; + char * frameName; + char * part1; + char * part2; + char * localName; + int flags; +{ + return (tclStubsPtr->tcl_UpVar2)(interp, frameName, part1, part2, localName, flags); +} + +/* Slot 260 */ +int +Tcl_VarEval TCL_VARARGS_DEF(Tcl_Interp *,interp) +{ + Tcl_Interp * var; + va_list argList; + int resultValue; + + var = (Tcl_Interp *) TCL_VARARGS_START(Tcl_Interp *,interp,argList); + + resultValue = (tclStubsPtr->tcl_VarEvalVA)(var, argList); + va_end(argList); +return resultValue; +} + +/* Slot 261 */ +ClientData +Tcl_VarTraceInfo(interp, varName, flags, procPtr, prevClientData) + Tcl_Interp * interp; + char * varName; + int flags; + Tcl_VarTraceProc * procPtr; + ClientData prevClientData; +{ + return (tclStubsPtr->tcl_VarTraceInfo)(interp, varName, flags, procPtr, prevClientData); +} + +/* Slot 262 */ +ClientData +Tcl_VarTraceInfo2(interp, part1, part2, flags, procPtr, prevClientData) + Tcl_Interp * interp; + char * part1; + char * part2; + int flags; + Tcl_VarTraceProc * procPtr; + ClientData prevClientData; +{ + return (tclStubsPtr->tcl_VarTraceInfo2)(interp, part1, part2, flags, procPtr, prevClientData); +} + +/* Slot 263 */ +int +Tcl_Write(chan, s, slen) + Tcl_Channel chan; + char * s; + int slen; +{ + return (tclStubsPtr->tcl_Write)(chan, s, slen); +} + +/* Slot 264 */ +void +Tcl_WrongNumArgs(interp, objc, objv, message) + Tcl_Interp * interp; + int objc; + Tcl_Obj *CONST objv[]; + char * message; +{ + (tclStubsPtr->tcl_WrongNumArgs)(interp, objc, objv, message); +} + +/* Slot 265 */ +int +Tcl_DumpActiveMemory(fileName) + char * fileName; +{ + return (tclStubsPtr->tcl_DumpActiveMemory)(fileName); +} + +/* Slot 266 */ +void +Tcl_ValidateAllMemory(file, line) + char * file; + int line; +{ + (tclStubsPtr->tcl_ValidateAllMemory)(file, line); +} + +/* Slot 267 */ +void +Tcl_AppendResultVA(interp, argList) + Tcl_Interp * interp; + va_list argList; +{ + (tclStubsPtr->tcl_AppendResultVA)(interp, argList); +} + +/* Slot 268 */ +void +Tcl_AppendStringsToObjVA(objPtr, argList) + Tcl_Obj * objPtr; + va_list argList; +{ + (tclStubsPtr->tcl_AppendStringsToObjVA)(objPtr, argList); +} + +/* Slot 269 */ +char * +Tcl_HashStats(tablePtr) + Tcl_HashTable * tablePtr; +{ + return (tclStubsPtr->tcl_HashStats)(tablePtr); +} + +/* Slot 270 */ +char * +Tcl_ParseVar(interp, str, termPtr) + Tcl_Interp * interp; + char * str; + char ** termPtr; +{ + return (tclStubsPtr->tcl_ParseVar)(interp, str, termPtr); +} + +/* Slot 271 */ +char * +Tcl_PkgPresent(interp, name, version, exact) + Tcl_Interp * interp; + char * name; + char * version; + int exact; +{ + return (tclStubsPtr->tcl_PkgPresent)(interp, name, version, exact); +} + +/* Slot 272 */ +char * +Tcl_PkgPresentEx(interp, name, version, exact, clientDataPtr) + Tcl_Interp * interp; + char * name; + char * version; + int exact; + ClientData * clientDataPtr; +{ + return (tclStubsPtr->tcl_PkgPresentEx)(interp, name, version, exact, clientDataPtr); +} + +/* Slot 273 */ +int +Tcl_PkgProvide(interp, name, version) + Tcl_Interp * interp; + char * name; + char * version; +{ + return (tclStubsPtr->tcl_PkgProvide)(interp, name, version); +} + +/* Slot 274 */ +char * +Tcl_PkgRequire(interp, name, version, exact) + Tcl_Interp * interp; + char * name; + char * version; + int exact; +{ + return (tclStubsPtr->tcl_PkgRequire)(interp, name, version, exact); +} + +/* Slot 275 */ +void +Tcl_SetErrorCodeVA(interp, argList) + Tcl_Interp * interp; + va_list argList; +{ + (tclStubsPtr->tcl_SetErrorCodeVA)(interp, argList); +} + +/* Slot 276 */ +int +Tcl_VarEvalVA(interp, argList) + Tcl_Interp * interp; + va_list argList; +{ + return (tclStubsPtr->tcl_VarEvalVA)(interp, argList); +} + +/* Slot 277 */ +Tcl_Pid +Tcl_WaitPid(pid, statPtr, options) + Tcl_Pid pid; + int * statPtr; + int options; +{ + return (tclStubsPtr->tcl_WaitPid)(pid, statPtr, options); +} + +/* Slot 278 */ +void +Tcl_PanicVA(format, argList) + char * format; + va_list argList; +{ + (tclStubsPtr->tcl_PanicVA)(format, argList); +} + +/* Slot 279 */ +void +Tcl_GetVersion(major, minor, patchLevel, type) + int * major; + int * minor; + int * patchLevel; + int * type; +{ + (tclStubsPtr->tcl_GetVersion)(major, minor, patchLevel, type); +} + +/* Slot 280 is reserved */ +/* Slot 281 is reserved */ +/* Slot 282 is reserved */ +/* Slot 283 is reserved */ +/* Slot 284 is reserved */ +/* Slot 285 is reserved */ +/* Slot 286 */ +void +Tcl_AppendObjToObj(objPtr, appendObjPtr) + Tcl_Obj * objPtr; + Tcl_Obj * appendObjPtr; +{ + (tclStubsPtr->tcl_AppendObjToObj)(objPtr, appendObjPtr); +} + +/* Slot 287 */ +Tcl_Encoding +Tcl_CreateEncoding(typePtr) + Tcl_EncodingType * typePtr; +{ + return (tclStubsPtr->tcl_CreateEncoding)(typePtr); +} + +/* Slot 288 */ +void +Tcl_CreateThreadExitHandler(proc, clientData) + Tcl_ExitProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_CreateThreadExitHandler)(proc, clientData); +} + +/* Slot 289 */ +void +Tcl_DeleteThreadExitHandler(proc, clientData) + Tcl_ExitProc * proc; + ClientData clientData; +{ + (tclStubsPtr->tcl_DeleteThreadExitHandler)(proc, clientData); +} + +/* Slot 290 */ +void +Tcl_DiscardResult(statePtr) + Tcl_SavedResult * statePtr; +{ + (tclStubsPtr->tcl_DiscardResult)(statePtr); +} + +/* Slot 291 */ +int +Tcl_EvalEx(interp, script, numBytes, flags) + Tcl_Interp * interp; + char * script; + int numBytes; + int flags; +{ + return (tclStubsPtr->tcl_EvalEx)(interp, script, numBytes, flags); +} + +/* Slot 292 */ +int +Tcl_EvalObjv(interp, objc, objv, flags) + Tcl_Interp * interp; + int objc; + Tcl_Obj *CONST objv[]; + int flags; +{ + return (tclStubsPtr->tcl_EvalObjv)(interp, objc, objv, flags); +} + +/* Slot 293 */ +int +Tcl_EvalObjEx(interp, objPtr, flags) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + int flags; +{ + return (tclStubsPtr->tcl_EvalObjEx)(interp, objPtr, flags); +} + +/* Slot 294 */ +void +Tcl_ExitThread(status) + int status; +{ + (tclStubsPtr->tcl_ExitThread)(status); +} + +/* Slot 295 */ +int +Tcl_ExternalToUtf(interp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr) + 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; +{ + return (tclStubsPtr->tcl_ExternalToUtf)(interp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr); +} + +/* Slot 296 */ +char * +Tcl_ExternalToUtfDString(encoding, src, srcLen, dsPtr) + Tcl_Encoding encoding; + CONST char * src; + int srcLen; + Tcl_DString * dsPtr; +{ + return (tclStubsPtr->tcl_ExternalToUtfDString)(encoding, src, srcLen, dsPtr); +} + +/* Slot 297 */ +void +Tcl_FinalizeThread() +{ + (tclStubsPtr->tcl_FinalizeThread)(); +} + +/* Slot 298 */ +void +Tcl_FinalizeNotifier(clientData) + ClientData clientData; +{ + (tclStubsPtr->tcl_FinalizeNotifier)(clientData); +} + +/* Slot 299 */ +void +Tcl_FreeEncoding(encoding) + Tcl_Encoding encoding; +{ + (tclStubsPtr->tcl_FreeEncoding)(encoding); +} + +/* Slot 300 */ +Tcl_ThreadId +Tcl_GetCurrentThread() +{ + return (tclStubsPtr->tcl_GetCurrentThread)(); +} + +/* Slot 301 */ +Tcl_Encoding +Tcl_GetEncoding(interp, name) + Tcl_Interp * interp; + CONST char * name; +{ + return (tclStubsPtr->tcl_GetEncoding)(interp, name); +} + +/* Slot 302 */ +char * +Tcl_GetEncodingName(encoding) + Tcl_Encoding encoding; +{ + return (tclStubsPtr->tcl_GetEncodingName)(encoding); +} + +/* Slot 303 */ +void +Tcl_GetEncodingNames(interp) + Tcl_Interp * interp; +{ + (tclStubsPtr->tcl_GetEncodingNames)(interp); +} + +/* Slot 304 */ +int +Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) + Tcl_Interp * interp; + Tcl_Obj * objPtr; + char ** tablePtr; + int offset; + char * msg; + int flags; + int * indexPtr; +{ + return (tclStubsPtr->tcl_GetIndexFromObjStruct)(interp, objPtr, tablePtr, offset, msg, flags, indexPtr); +} + +/* Slot 305 */ +VOID * +Tcl_GetThreadData(keyPtr, size) + Tcl_ThreadDataKey * keyPtr; + int size; +{ + return (tclStubsPtr->tcl_GetThreadData)(keyPtr, size); +} + +/* Slot 306 */ +Tcl_Obj * +Tcl_GetVar2Ex(interp, part1, part2, flags) + Tcl_Interp * interp; + char * part1; + char * part2; + int flags; +{ + return (tclStubsPtr->tcl_GetVar2Ex)(interp, part1, part2, flags); +} + +/* Slot 307 */ +ClientData +Tcl_InitNotifier() +{ + return (tclStubsPtr->tcl_InitNotifier)(); +} + +/* Slot 308 */ +void +Tcl_MutexLock(mutexPtr) + Tcl_Mutex * mutexPtr; +{ + (tclStubsPtr->tcl_MutexLock)(mutexPtr); +} + +/* Slot 309 */ +void +Tcl_MutexUnlock(mutexPtr) + Tcl_Mutex * mutexPtr; +{ + (tclStubsPtr->tcl_MutexUnlock)(mutexPtr); +} + +/* Slot 310 */ +void +Tcl_ConditionNotify(condPtr) + Tcl_Condition * condPtr; +{ + (tclStubsPtr->tcl_ConditionNotify)(condPtr); +} + +/* Slot 311 */ +void +Tcl_ConditionWait(condPtr, mutexPtr, timePtr) + Tcl_Condition * condPtr; + Tcl_Mutex * mutexPtr; + Tcl_Time * timePtr; +{ + (tclStubsPtr->tcl_ConditionWait)(condPtr, mutexPtr, timePtr); +} + +/* Slot 312 */ +int +Tcl_NumUtfChars(src, len) + CONST char * src; + int len; +{ + return (tclStubsPtr->tcl_NumUtfChars)(src, len); +} + +/* Slot 313 */ +int +Tcl_ReadChars(channel, objPtr, charsToRead, appendFlag) + Tcl_Channel channel; + Tcl_Obj * objPtr; + int charsToRead; + int appendFlag; +{ + return (tclStubsPtr->tcl_ReadChars)(channel, objPtr, charsToRead, appendFlag); +} + +/* Slot 314 */ +void +Tcl_RestoreResult(interp, statePtr) + Tcl_Interp * interp; + Tcl_SavedResult * statePtr; +{ + (tclStubsPtr->tcl_RestoreResult)(interp, statePtr); +} + +/* Slot 315 */ +void +Tcl_SaveResult(interp, statePtr) + Tcl_Interp * interp; + Tcl_SavedResult * statePtr; +{ + (tclStubsPtr->tcl_SaveResult)(interp, statePtr); +} + +/* Slot 316 */ +int +Tcl_SetSystemEncoding(interp, name) + Tcl_Interp * interp; + CONST char * name; +{ + return (tclStubsPtr->tcl_SetSystemEncoding)(interp, name); +} + +/* Slot 317 */ +Tcl_Obj * +Tcl_SetVar2Ex(interp, part1, part2, newValuePtr, flags) + Tcl_Interp * interp; + char * part1; + char * part2; + Tcl_Obj * newValuePtr; + int flags; +{ + return (tclStubsPtr->tcl_SetVar2Ex)(interp, part1, part2, newValuePtr, flags); +} + +/* Slot 318 */ +void +Tcl_ThreadAlert(threadId) + Tcl_ThreadId threadId; +{ + (tclStubsPtr->tcl_ThreadAlert)(threadId); +} + +/* Slot 319 */ +void +Tcl_ThreadQueueEvent(threadId, evPtr, position) + Tcl_ThreadId threadId; + Tcl_Event* evPtr; + Tcl_QueuePosition position; +{ + (tclStubsPtr->tcl_ThreadQueueEvent)(threadId, evPtr, position); +} + +/* Slot 320 */ +Tcl_UniChar +Tcl_UniCharAtIndex(src, index) + CONST char * src; + int index; +{ + return (tclStubsPtr->tcl_UniCharAtIndex)(src, index); +} + +/* Slot 321 */ +Tcl_UniChar +Tcl_UniCharToLower(ch) + int ch; +{ + return (tclStubsPtr->tcl_UniCharToLower)(ch); +} + +/* Slot 322 */ +Tcl_UniChar +Tcl_UniCharToTitle(ch) + int ch; +{ + return (tclStubsPtr->tcl_UniCharToTitle)(ch); +} + +/* Slot 323 */ +Tcl_UniChar +Tcl_UniCharToUpper(ch) + int ch; +{ + return (tclStubsPtr->tcl_UniCharToUpper)(ch); +} + +/* Slot 324 */ +int +Tcl_UniCharToUtf(ch, buf) + int ch; + char * buf; +{ + return (tclStubsPtr->tcl_UniCharToUtf)(ch, buf); +} + +/* Slot 325 */ +char * +Tcl_UtfAtIndex(src, index) + CONST char * src; + int index; +{ + return (tclStubsPtr->tcl_UtfAtIndex)(src, index); +} + +/* Slot 326 */ +int +Tcl_UtfCharComplete(src, len) + CONST char * src; + int len; +{ + return (tclStubsPtr->tcl_UtfCharComplete)(src, len); +} + +/* Slot 327 */ +int +Tcl_UtfBackslash(src, readPtr, dst) + CONST char * src; + int * readPtr; + char * dst; +{ + return (tclStubsPtr->tcl_UtfBackslash)(src, readPtr, dst); +} + +/* Slot 328 */ +char * +Tcl_UtfFindFirst(src, ch) + CONST char * src; + int ch; +{ + return (tclStubsPtr->tcl_UtfFindFirst)(src, ch); +} + +/* Slot 329 */ +char * +Tcl_UtfFindLast(src, ch) + CONST char * src; + int ch; +{ + return (tclStubsPtr->tcl_UtfFindLast)(src, ch); +} + +/* Slot 330 */ +char * +Tcl_UtfNext(src) + CONST char * src; +{ + return (tclStubsPtr->tcl_UtfNext)(src); +} + +/* Slot 331 */ +char * +Tcl_UtfPrev(src, start) + CONST char * src; + CONST char * start; +{ + return (tclStubsPtr->tcl_UtfPrev)(src, start); +} + +/* Slot 332 */ +int +Tcl_UtfToExternal(interp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr) + 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; +{ + return (tclStubsPtr->tcl_UtfToExternal)(interp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr); +} + +/* Slot 333 */ +char * +Tcl_UtfToExternalDString(encoding, src, srcLen, dsPtr) + Tcl_Encoding encoding; + CONST char * src; + int srcLen; + Tcl_DString * dsPtr; +{ + return (tclStubsPtr->tcl_UtfToExternalDString)(encoding, src, srcLen, dsPtr); +} + +/* Slot 334 */ +int +Tcl_UtfToLower(src) + char * src; +{ + return (tclStubsPtr->tcl_UtfToLower)(src); +} + +/* Slot 335 */ +int +Tcl_UtfToTitle(src) + char * src; +{ + return (tclStubsPtr->tcl_UtfToTitle)(src); +} + +/* Slot 336 */ +int +Tcl_UtfToUniChar(src, chPtr) + CONST char * src; + Tcl_UniChar * chPtr; +{ + return (tclStubsPtr->tcl_UtfToUniChar)(src, chPtr); +} + +/* Slot 337 */ +int +Tcl_UtfToUpper(src) + char * src; +{ + return (tclStubsPtr->tcl_UtfToUpper)(src); +} + +/* Slot 338 */ +int +Tcl_WriteChars(chan, src, srcLen) + Tcl_Channel chan; + CONST char * src; + int srcLen; +{ + return (tclStubsPtr->tcl_WriteChars)(chan, src, srcLen); +} + +/* Slot 339 */ +int +Tcl_WriteObj(chan, objPtr) + Tcl_Channel chan; + Tcl_Obj * objPtr; +{ + return (tclStubsPtr->tcl_WriteObj)(chan, objPtr); +} + +/* Slot 340 */ +char * +Tcl_GetString(objPtr) + Tcl_Obj * objPtr; +{ + return (tclStubsPtr->tcl_GetString)(objPtr); +} + +/* Slot 341 */ +char * +Tcl_GetDefaultEncodingDir() +{ + return (tclStubsPtr->tcl_GetDefaultEncodingDir)(); +} + +/* Slot 342 */ +void +Tcl_SetDefaultEncodingDir(path) + char * path; +{ + (tclStubsPtr->tcl_SetDefaultEncodingDir)(path); +} + +/* Slot 343 */ +void +Tcl_AlertNotifier(clientData) + ClientData clientData; +{ + (tclStubsPtr->tcl_AlertNotifier)(clientData); +} + +/* Slot 344 */ +void +Tcl_ServiceModeHook(mode) + int mode; +{ + (tclStubsPtr->tcl_ServiceModeHook)(mode); +} + + +/* !END!: Do not edit above this line. */ Index: generic/tclTest.c ================================================================== --- generic/tclTest.c +++ generic/tclTest.c @@ -6,28 +6,32 @@ * 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-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. * - * SCCS: @(#) tclTest.c 1.119 97/10/31 15:57:28 + * RCS: @(#) $Id: tclTest.c,v 1.1.2.16 1999/04/14 00:33:27 surles Exp $ */ #define TCL_TEST #include "tclInt.h" #include "tclPort.h" +#include "tclRegexp.h" +#include /* * Declare external functions used in Windows tests. */ #if defined(__WIN32__) -extern TclPlatformType * TclWinGetPlatform _ANSI_ARGS_((void)); +extern TclPlatformType *TclWinGetPlatform(void); +EXTERN void TclWinSetInterfaces(int); #endif /* * Dynamic string shared by TestdcallCmd and DelCallbackProc; used * to collect the results of the various deletion callbacks. @@ -74,10 +78,28 @@ 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; + /* * Forward declarations for procedures defined later in this file: */ int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp)); @@ -109,20 +131,42 @@ static void DelCallbackProc _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp)); static int DelCmdProc _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv)); static void DelDeleteProc _ANSI_ARGS_((ClientData clientData)); +static void EncodingFreeProc _ANSI_ARGS_((ClientData clientData)); +static int EncodingToUtfProc _ANSI_ARGS_((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 _ANSI_ARGS_((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 _ANSI_ARGS_((ClientData clientData)); static void ExitProcOdd _ANSI_ARGS_((ClientData clientData)); static int GetTimesCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv)); static int NoopCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv)); static int NoopObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static void PrintParse _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr)); static void SpecialFree _ANSI_ARGS_((char *blockPtr)); static int StaticInitProc _ANSI_ARGS_((Tcl_Interp *interp)); +static int TestaccessprocCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int argc, char **argv)); +static int TestAccessProc1 _ANSI_ARGS_((CONST char *path, + int mode)); +static int TestAccessProc2 _ANSI_ARGS_((CONST char *path, + int mode)); +static int TestAccessProc3 _ANSI_ARGS_((CONST char *path, + int mode)); static int TestasyncCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); static int TestcmdinfoCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); static int TestcmdtokenCmd _ANSI_ARGS_((ClientData dummy, @@ -139,14 +183,26 @@ Tcl_Interp *interp, int argc, char **argv)); static int TestdelassocdataCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); static int TestdstringCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); +static int TestencodingObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int TestevalexObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int TestevalobjvObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); static int TestexithandlerCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); static int TestexprlongCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); +static int TestexprparserObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); static int TestexprstringCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); static int TestfileCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); static int TestfeventCmd _ANSI_ARGS_((ClientData dummy, @@ -160,46 +216,82 @@ int objc, Tcl_Obj *CONST objv[])); static int TestinterpdeleteCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); static int TestlinkCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); +static int TestlocaleCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); static int TestMathFunc _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, Tcl_Value *args, Tcl_Value *resultPtr)); static int TestMathFunc2 _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, Tcl_Value *args, Tcl_Value *resultPtr)); -static int TestPanicCmd _ANSI_ARGS_((ClientData dummy, +static Tcl_Channel TestOpenFileChannelProc1 _ANSI_ARGS_((Tcl_Interp *interp, + char *filename, char *modeString, int permissions)); +static Tcl_Channel TestOpenFileChannelProc2 _ANSI_ARGS_((Tcl_Interp *interp, + char *filename, char *modeString, int permissions)); +static Tcl_Channel TestOpenFileChannelProc3 _ANSI_ARGS_((Tcl_Interp *interp, + char *filename, char *modeString, int permissions)); +static int TestpanicCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); +static int TestparserObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int TestparsevarObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int TestparsevarnameObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int TestregexpObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static void TestregexpXflags _ANSI_ARGS_((char *string, + int length, int *cflagsPtr, int *eflagsPtr)); +static int TestsaveresultCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static void TestsaveresultFree _ANSI_ARGS_((char *blockPtr)); static int TestsetassocdataCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); -static int TestsetnoerrCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int argc, char **argv)); +static int TestsetCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int argc, char **argv)); static int TestsetobjerrorcodeCmd _ANSI_ARGS_(( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +static int TestopenfilechannelprocCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int argc, char **argv)); static int TestsetplatformCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); static int TestsetrecursionlimitCmd _ANSI_ARGS_(( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); static int TeststaticpkgCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); +static int TestStatProc1 _ANSI_ARGS_((CONST char *path, + TclStat_ *buf)); +static int TestStatProc2 _ANSI_ARGS_((CONST char *path, + TclStat_ *buf)); +static int TestStatProc3 _ANSI_ARGS_((CONST char *path, + TclStat_ *buf)); +static int TeststatprocCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int argc, char **argv)); static int TesttranslatefilenameCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); static int TestupvarCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int argc, char **argv)); -static int TestwordendObjCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); /* - * External (platform specific) initialization routine: + * External (platform specific) initialization routine, these declarations + * explicitly don't use EXTERN since this code does not get compiled + * into the library: */ -EXTERN int TclplatformtestInit _ANSI_ARGS_(( - Tcl_Interp *interp)); +extern int TclplatformtestInit _ANSI_ARGS_((Tcl_Interp *interp)); +extern int TclThread_Init _ANSI_ARGS_((Tcl_Interp *interp)); /* *---------------------------------------------------------------------- * * Tcltest_Init -- @@ -208,11 +300,11 @@ * 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 interp->result if an error occurs. + * message in the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- @@ -230,13 +322,17 @@ /* * Create additional commands and math functions for testing Tcl. */ + Tcl_CreateCommand(interp, "gettimes", GetTimesCmd, (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "noop", NoopCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "noop", NoopObjCmd, (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateCommand(interp, "testaccessproc", TestaccessprocCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testasync", TestasyncCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testchannel", TclTestChannelCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); @@ -259,16 +355,26 @@ Tcl_CreateCommand(interp, "testdelassocdata", TestdelassocdataCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_DStringInit(&dstring); Tcl_CreateCommand(interp, "testdstring", TestdstringCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "testencoding", TestencodingObjCmd, (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "testevalex", TestevalexObjCmd, + (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "testevalobjv", TestevalobjvObjCmd, + (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testexithandler", TestexithandlerCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testexprlong", TestexprlongCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "testexprparser", TestexprparserObjCmd, + (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testexprstring", TestexprstringCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateCommand(interp, "testfevent", TestfeventCmd, (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testfile", TestfileCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testgetassocdata", TestgetassocdataCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testgetplatform", TestgetplatformCmd, @@ -278,14 +384,33 @@ (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testinterpdelete", TestinterpdeleteCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testlink", TestlinkCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "testlocale", TestlocaleCmd, (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateCommand(interp, "testopenfilechannelproc", + TestopenfilechannelprocCmd, (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateCommand(interp, "testpanic", TestpanicCmd, (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "testparser", TestparserObjCmd, + (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "testparsevar", TestparsevarObjCmd, + (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "testparsevarname", TestparsevarnameObjCmd, + (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "testregexp", TestregexpObjCmd, + (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "testsaveresult", TestsaveresultCmd, + (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testsetassocdata", TestsetassocdataCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); - Tcl_CreateCommand(interp, "testsetnoerr", TestsetnoerrCmd, + Tcl_CreateCommand(interp, "testsetnoerr", TestsetCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateCommand(interp, "testseterr", TestsetCmd, + (ClientData) TCL_LEAVE_ERR_MSG, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "testsetobjerrorcode", TestsetobjerrorcodeCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); @@ -297,26 +422,26 @@ Tcl_CreateCommand(interp, "testtranslatefilename", TesttranslatefilenameCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); - Tcl_CreateObjCommand(interp, "testwordend", TestwordendObjCmd, - (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); - Tcl_CreateCommand(interp, "testfevent", TestfeventCmd, (ClientData) 0, - (Tcl_CmdDeleteProc *) NULL); - Tcl_CreateCommand(interp, "testpanic", TestPanicCmd, (ClientData) 0, - (Tcl_CmdDeleteProc *) NULL); - Tcl_CreateCommand(interp, "gettimes", GetTimesCmd, (ClientData) 0, - (Tcl_CmdDeleteProc *) NULL); Tcl_CreateMathFunc(interp, "T1", 0, (Tcl_ValueType *) NULL, TestMathFunc, (ClientData) 123); Tcl_CreateMathFunc(interp, "T2", 0, (Tcl_ValueType *) NULL, TestMathFunc, (ClientData) 345); + Tcl_CreateCommand(interp, "teststatproc", TeststatprocCmd, (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); t3ArgTypes[0] = TCL_EITHER; t3ArgTypes[1] = TCL_EITHER; Tcl_CreateMathFunc(interp, "T3", 2, t3ArgTypes, TestMathFunc2, (ClientData) 0); + +#ifdef TCL_THREADS + if (TclThread_Init(interp) != TCL_OK) { + return TCL_ERROR; + } +#endif /* * And finally add any platform specific test commands. */ @@ -349,11 +474,11 @@ char **argv; /* Argument strings. */ { TestAsyncHandler *asyncPtr, *prevPtr; int id, code; static int nextId = 1; - char buf[30]; + char buf[TCL_INTEGER_SPACE]; if (argc < 2) { wrongNumArgs: Tcl_SetResult(interp, "wrong # args", TCL_STATIC); return TCL_ERROR; @@ -369,11 +494,11 @@ (ClientData) asyncPtr); asyncPtr->command = (char *) ckalloc((unsigned) (strlen(argv[2]) + 1)); strcpy(asyncPtr->command, argv[2]); asyncPtr->nextPtr = firstHandler; firstHandler = asyncPtr; - sprintf(buf, "%d", asyncPtr->id); + TclFormatInt(buf, asyncPtr->id); Tcl_SetResult(interp, buf, TCL_VOLATILE); } else if (strcmp(argv[1], "delete") == 0) { if (argc == 2) { while (firstHandler != NULL) { asyncPtr = firstHandler; @@ -438,15 +563,15 @@ * executed, or NULL. */ int code; /* Current return code from command. */ { TestAsyncHandler *asyncPtr = (TestAsyncHandler *) clientData; char *listArgv[4]; - char string[20], *cmd; + char string[TCL_INTEGER_SPACE], *cmd; - sprintf(string, "%d", code); + TclFormatInt(string, code); listArgv[0] = asyncPtr->command; - listArgv[1] = interp->result; + listArgv[1] = Tcl_GetStringResult(interp); listArgv[2] = string; listArgv[3] = NULL; cmd = Tcl_Merge(3, listArgv); code = Tcl_Eval(interp, cmd); ckfree(cmd); @@ -640,12 +765,11 @@ objPtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, (Tcl_Command) l, objPtr); Tcl_AppendElement(interp, Tcl_GetCommandName(interp, (Tcl_Command) l)); - Tcl_AppendElement(interp, - Tcl_GetStringFromObj(objPtr, (int *) NULL)); + Tcl_AppendElement(interp, Tcl_GetString(objPtr)); Tcl_DecrRefCount(objPtr); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create or name", (char *) NULL); return TCL_ERROR; @@ -707,11 +831,11 @@ * TclExecuteByteCode. */ cmdTrace = Tcl_CreateTrace(interp, 50000, (Tcl_CmdTraceProc *) CmdTraceDeleteProc, (ClientData) NULL); - result = Tcl_Eval(interp, argv[2]); + Tcl_Eval(interp, argv[2]); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be tracetest or deletetest", (char *) NULL); return TCL_ERROR; } @@ -921,13 +1045,13 @@ ClientData clientData; /* Numerical value to append to * delString. */ Tcl_Interp *interp; /* Interpreter being deleted. */ { int id = (int) clientData; - char buffer[10]; + char buffer[TCL_INTEGER_SPACE]; - sprintf(buffer, "%d", id); + TclFormatInt(buffer, id); Tcl_DStringAppendElement(&delString, buffer); if (interp != delInterp) { Tcl_DStringAppendElement(&delString, "bogus interpreter argument!"); } } @@ -1123,16 +1247,16 @@ (char *) NULL); return TCL_ERROR; } Tcl_DStringGetResult(interp, &dstring); } else if (strcmp(argv[1], "length") == 0) { - char buf[30]; + char buf[TCL_INTEGER_SPACE]; if (argc != 2) { goto wrongNumArgs; } - sprintf(buf, "%d", Tcl_DStringLength(&dstring)); + TclFormatInt(buf, Tcl_DStringLength(&dstring)); Tcl_SetResult(interp, buf, TCL_VOLATILE); } else if (strcmp(argv[1], "result") == 0) { if (argc != 2) { goto wrongNumArgs; } @@ -1167,10 +1291,289 @@ static void SpecialFree(blockPtr) char *blockPtr; /* Block to free. */ { ckfree(blockPtr - 4); } + +/* + *---------------------------------------------------------------------- + * + * 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(dummy, interp, objc, objv) + 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; + char *string; + TclEncoding *encodingPtr; + static char *optionStrings[] = { + "create", "delete", "path", + NULL + }; + enum options { + ENC_CREATE, ENC_DELETE, ENC_PATH + }; + + 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 = (TclEncoding *) ckalloc(sizeof(TclEncoding)); + encodingPtr->interp = interp; + + string = Tcl_GetStringFromObj(objv[3], &length); + encodingPtr->toUtfCmd = (char *) ckalloc((unsigned) (length + 1)); + memcpy(encodingPtr->toUtfCmd, string, (unsigned) length + 1); + + string = Tcl_GetStringFromObj(objv[4], &length); + encodingPtr->fromUtfCmd = (char *) ckalloc((unsigned) (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; + } + case ENC_PATH: { + if (objc == 2) { + Tcl_SetObjResult(interp, TclGetLibraryPath()); + } else { + TclSetLibraryPath(objv[2]); + } + break; + } + } + return TCL_OK; +} +static int +EncodingToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen, + srcReadPtr, dstWrotePtr, dstCharsPtr) + 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_GlobalEval(encodingPtr->interp, encodingPtr->toUtfCmd); + + 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, src, srcLen, flags, statePtr, dst, dstLen, + srcReadPtr, dstWrotePtr, dstCharsPtr) + 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_GlobalEval(encodingPtr->interp, encodingPtr->fromUtfCmd); + + 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; /* ClientData associated with type. */ +{ + TclEncoding *encodingPtr; + + encodingPtr = (TclEncoding *) clientData; + ckfree((char *) encodingPtr->toUtfCmd); + ckfree((char *) encodingPtr->fromUtfCmd); + ckfree((char *) 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(dummy, interp, objc, objv) + 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 code, oldFlags, length, flags; + char *string; + + if (objc == 1) { + /* + * The command was invoked with no arguments, so just toggle + * the flag that determines whether we use Tcl_EvalEx. + */ + + if (iPtr->flags & USE_EVAL_DIRECT) { + iPtr->flags &= ~USE_EVAL_DIRECT; + Tcl_SetResult(interp, "disabling direct evaluation", TCL_STATIC); + } else { + iPtr->flags |= USE_EVAL_DIRECT; + Tcl_SetResult(interp, "enabling direct evaluation", TCL_STATIC); + } + return TCL_OK; + } + + flags = 0; + if (objc == 3) { + string = Tcl_GetStringFromObj(objv[2], &length); + if (strcmp(string, "global") != 0) { + Tcl_AppendResult(interp, "bad value \"", string, + "\": must be global", (char *) NULL); + return TCL_ERROR; + } + flags = TCL_EVAL_GLOBAL; + } else if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "script ?global?"); + return TCL_ERROR; + } + Tcl_SetResult(interp, "xxx", TCL_STATIC); + + /* + * Note, we have to set the USE_EVAL_DIRECT flag in the interpreter + * in addition to calling Tcl_EvalEx. This is needed so that even nested + * commands are evaluated directly. + */ + + oldFlags = iPtr->flags; + iPtr->flags |= USE_EVAL_DIRECT; + string = Tcl_GetStringFromObj(objv[1], &length); + code = Tcl_EvalEx(interp, string, length, flags); + iPtr->flags = (iPtr->flags & ~USE_EVAL_DIRECT) + | (oldFlags & USE_EVAL_DIRECT); + return code; +} + +/* + *---------------------------------------------------------------------- + * + * 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(dummy, interp, objc, objv) + 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); +} /* *---------------------------------------------------------------------- * * TestexithandlerCmd -- @@ -1220,21 +1623,21 @@ static void ExitProcOdd(clientData) ClientData clientData; /* Integer value to print. */ { - char buf[100]; + char buf[16 + TCL_INTEGER_SPACE]; sprintf(buf, "odd %d\n", (int) clientData); write(1, buf, strlen(buf)); } static void ExitProcEven(clientData) ClientData clientData; /* Integer value to print. */ { - char buf[100]; + char buf[16 + TCL_INTEGER_SPACE]; sprintf(buf, "even %d\n", (int) clientData); write(1, buf, strlen(buf)); } @@ -1261,11 +1664,11 @@ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */ { long exprResult; - char buf[30]; + char buf[4 + TCL_INTEGER_SPACE]; int result; Tcl_SetResult(interp, "This is a result", TCL_STATIC); result = Tcl_ExprLong(interp, "4+1", &exprResult); if (result != TCL_OK) { @@ -1426,12 +1829,10 @@ (char *) NULL); return TCL_ERROR; } slaveToDelete = Tcl_GetSlave(interp, argv[1]); if (slaveToDelete == (Tcl_Interp *) NULL) { - Tcl_AppendResult(interp, "could not find interpreter \"", - argv[1], "\"", (char *) NULL); return TCL_ERROR; } Tcl_DeleteInterp(slaveToDelete); return TCL_OK; } @@ -1520,15 +1921,15 @@ Tcl_UnlinkVar(interp, "real"); Tcl_UnlinkVar(interp, "bool"); Tcl_UnlinkVar(interp, "string"); created = 0; } else if (strcmp(argv[1], "get") == 0) { - sprintf(buffer, "%d", intVar); + TclFormatInt(buffer, intVar); Tcl_AppendElement(interp, buffer); Tcl_PrintDouble((Tcl_Interp *) NULL, realVar, buffer); Tcl_AppendElement(interp, buffer); - sprintf(buffer, "%d", boolVar); + TclFormatInt(buffer, boolVar); Tcl_AppendElement(interp, buffer); Tcl_AppendElement(interp, (stringVar == NULL) ? "-" : stringVar); } else if (strcmp(argv[1], "set") == 0) { if (argc != 6) { Tcl_AppendResult(interp, "wrong # args: should be \"", @@ -1609,10 +2010,72 @@ } /* *---------------------------------------------------------------------- * + * 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, interp, objc, objv) + ClientData clientData; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* The argument objects. */ +{ + int index; + char *locale; + + static char *optionStrings[] = { + "ctype", "numeric", "time", "collate", "monetary", + "all", NULL + }; + static 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. * @@ -1659,12 +2122,12 @@ static int TestMathFunc2(clientData, interp, args, resultPtr) ClientData clientData; /* Integer value to return. */ Tcl_Interp *interp; /* Used to report errors. */ Tcl_Value *args; /* Points to an array of two - * Tcl_Values for the two - * arguments. */ + * Tcl_Value structs for the + * two arguments. */ Tcl_Value *resultPtr; /* Where to store the result. */ { int result = TCL_OK; /* @@ -1735,10 +2198,621 @@ ClientData clientData; /* Data to be released. */ Tcl_Interp *interp; /* Interpreter being deleted. */ { ckfree((char *) 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, interp, objc, objv) + ClientData clientData; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* The argument objects. */ +{ + 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, interp, objc, objv) + ClientData clientData; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* The argument objects. */ +{ + 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; + } + 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(interp, parsePtr) + 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; + char *typeString; + Tcl_Token *tokenPtr; + int i; + + objPtr = Tcl_GetObjResult(interp); + if (parsePtr->commentSize > 0) { + Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr, + Tcl_NewStringObj(parsePtr->commentStart, + parsePtr->commentSize)); + } else { + Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr, + Tcl_NewStringObj("-", 1)); + } + Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr, + Tcl_NewStringObj(parsePtr->commandStart, parsePtr->commandSize)); + Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr, + Tcl_NewIntObj(parsePtr->numWords)); + for (i = 0; i < parsePtr->numTokens; i++) { + tokenPtr = &parsePtr->tokenPtr[i]; + switch (tokenPtr->type) { + 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((Tcl_Interp *) NULL, objPtr, + Tcl_NewStringObj(typeString, -1)); + Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr, + Tcl_NewStringObj(tokenPtr->start, tokenPtr->size)); + Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr, + Tcl_NewIntObj(tokenPtr->numComponents)); + } + Tcl_ListObjAppendElement((Tcl_Interp *) 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, interp, objc, objv) + ClientData clientData; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* The argument objects. */ +{ + char *name, *value, *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, interp, objc, objv) + ClientData clientData; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* The argument objects. */ +{ + 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 REGEXP_TEST define, which + * enables the -xflags option. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +TestregexpObjCmd(dummy, interp, objc, objv) + ClientData dummy; /* Not used. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + int i, result, indices, stringLength, wLen, match, about; + int hasxflags, cflags, eflags; + Tcl_RegExp regExpr; + char *string; + Tcl_DString stringBuffer, valueBuffer; + Tcl_UniChar *wStart; +# define REGEXP_TEST /* yes */ + static char *options[] = { + "-indices", "-nocase", "-about", "-expanded", + "-line", "-linestop", "-lineanchor", +#ifdef REGEXP_TEST + "-xflags", +#endif + "--", (char *) NULL + }; + enum options { + REGEXP_INDICES, REGEXP_NOCASE, REGEXP_ABOUT, REGEXP_EXPANDED, + REGEXP_MULTI, REGEXP_NOCROSS, REGEXP_NEWL, +#ifdef REGEXP_TEST + REGEXP_XFLAGS, +#endif + REGEXP_LAST + }; +#ifndef REGEXP_TEST +# define REGEXP_XFLAGS -1 /* impossible value */ +# define TestregexpXflags(a,b,c,d) /* do nothing */ +#endif + + indices = 0; + about = 0; + cflags = REG_ADVANCED; + eflags = 0; + hasxflags = 0; + + for (i = 1; i < objc; i++) { + 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, + "?switches? exp string ?matchVar? ?subMatchVar 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; + } + + result = TCL_OK; + string = Tcl_GetStringFromObj(objv[1], &stringLength); + + Tcl_DStringInit(&valueBuffer); + + Tcl_DStringInit(&stringBuffer); + wStart = Tcl_UtfToUniCharDString(string, stringLength, &stringBuffer); + wLen = Tcl_DStringLength(&stringBuffer) / sizeof(Tcl_UniChar); + + match = TclRegExpExecUniChar(interp, regExpr, wStart, wLen, objc-2, eflags); + if (match < 0) { + result = TCL_ERROR; + goto done; + } + if (match == 0) { + /* + * Set the interpreter's object result to an integer object w/ value 0. + */ + + Tcl_SetIntObj(Tcl_GetObjResult(interp), 0); + goto done; + } + + /* + * If additional variable names have been specified, return + * index information in those variables. + */ + + objc -= 2; + objv += 2; + + for (i = 0; i < objc; i++) { + char *varName, *value; + int start, end; + + varName = Tcl_GetString(objv[i]); + + TclRegExpRangeUniChar(regExpr, i, &start, &end); + if (start < 0) { + if (indices) { + value = Tcl_SetVar(interp, varName, "-1 -1", 0); + } else { + value = Tcl_SetVar(interp, varName, "", 0); + } + } else { + if (indices) { + char info[TCL_INTEGER_SPACE * 2]; + + sprintf(info, "%d %d", start, end - 1); + value = Tcl_SetVar(interp, varName, info, 0); + } else { + value = Tcl_UniCharToUtfDString(wStart + start, end - start, + &valueBuffer); + value = Tcl_SetVar(interp, varName, value, 0); + Tcl_DStringSetLength(&valueBuffer, 0); + } + } + if (value == NULL) { + Tcl_AppendResult(interp, "couldn't set variable \"", + varName, "\"", (char *) NULL); + result = TCL_ERROR; + goto done; + } + } + + /* + * Set the interpreter's object result to an integer object w/ value 1. + */ + + Tcl_SetIntObj(Tcl_GetObjResult(interp), 1); + + done: + Tcl_DStringFree(&stringBuffer); + Tcl_DStringFree(&valueBuffer); + return result; +} + +/* + *--------------------------------------------------------------------------- + * + * 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(string, length, cflagsPtr, eflagsPtr) + 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; + int cflags; + int 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 '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 '+': { + cflags |= REG_FAKEEC; + 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 '%': { + eflags |= REG_SMALL; + break; + } + } + } + + *cflagsPtr = cflags; + *eflagsPtr = eflags; +} /* *---------------------------------------------------------------------- * * TestsetassocdataCmd -- @@ -2033,50 +3107,10 @@ } /* *---------------------------------------------------------------------- * - * TestwordendCmd -- - * - * This procedure implements the "testwordend" command. It is used - * to test TclWordEnd. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - - /* ARGSUSED */ -static int -TestwordendObjCmd(dummy, interp, objc, objv) - ClientData dummy; /* Not used. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* The argument objects. */ -{ - Tcl_Obj *objPtr; - char *string, *end; - int length; - - if (objc != 2) { - Tcl_WrongNumArgs(interp, 1, objv, "string"); - return TCL_ERROR; - } - objPtr = Tcl_GetObjResult(interp); - string = Tcl_GetStringFromObj(objv[1], &length); - end = TclWordEnd(string, string+length, 0, NULL); - Tcl_AppendToObj(objPtr, end, length - (end - string)); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * * TestsetobjerrorcodeCmd -- * * This procedure implements the "testsetobjerrorcodeCmd". * This tests up to five elements passed to the * Tcl_SetObjErrorCode command. @@ -2152,11 +3186,11 @@ " cmd script", (char *) NULL); return TCL_ERROR; } if (interp2 != (Tcl_Interp *) NULL) { code = Tcl_GlobalEval(interp2, argv[2]); - interp->result = interp2->result; + Tcl_SetObjResult(interp, Tcl_GetObjResult(interp2)); return code; } else { Tcl_AppendResult(interp, "called \"testfevent code\" before \"testfevent create\"", (char *) NULL); @@ -2187,11 +3221,11 @@ } /* *---------------------------------------------------------------------- * - * TestPanicCmd -- + * TestpanicCmd -- * * Calls the panic routine. * * Results: * Always returns TCL_OK. @@ -2201,11 +3235,11 @@ * *---------------------------------------------------------------------- */ static int -TestPanicCmd(dummy, interp, argc, argv) +TestpanicCmd(dummy, interp, argc, argv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */ { @@ -2383,13 +3417,13 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "name scope"); return TCL_ERROR; } - name = Tcl_GetStringFromObj(objv[1], (int *) NULL); + name = Tcl_GetString(objv[1]); - arg = Tcl_GetStringFromObj(objv[2], (int *) NULL); + arg = Tcl_GetString(objv[2]); if (strcmp(arg, "global") == 0) { flags = TCL_GLOBAL_ONLY; } else if (strcmp(arg, "namespace") == 0) { flags = TCL_NAMESPACE_ONLY; } @@ -2458,11 +3492,11 @@ double timePer; Tcl_Time start, stop; Tcl_Obj *objPtr; Tcl_Obj **objv; char *s; - char newString[30]; + char newString[TCL_INTEGER_SPACE]; /* alloc & free 100000 times */ fprintf(stderr, "alloc & free 100000 6 word items\n"); TclpGetTime(&start); for (i = 0; i < 100000; i++) { @@ -2514,16 +3548,16 @@ TclpGetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per Tcl_DecrRefCount\n", timePer/5000); ckfree((char *) objv); - /* TclGetStringFromObj 100000 times */ + /* TclGetString 100000 times */ fprintf(stderr, "TclGetStringFromObj of \"12345\" 100000 times\n"); objPtr = Tcl_NewStringObj("12345", -1); TclpGetTime(&start); for (i = 0; i < 100000; i++) { - (void) TclGetStringFromObj(objPtr, &n); + (void) TclGetString(objPtr); } TclpGetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per TclGetStringFromObj of \"12345\"\n", timePer/100000); @@ -2664,14 +3698,66 @@ } /* *---------------------------------------------------------------------- * - * TestsetnoerrCmd -- + * 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(data, interp, argc, argv) + ClientData data; /* Additional flags for Get/SetVar2. */ + register Tcl_Interp *interp; /* Current interpreter. */ + int argc; /* Number of arguments. */ + char **argv; /* Argument strings. */ +{ + int flags = (int) data; + char *value; + + if (argc == 2) { + Tcl_SetResult(interp, "before get", TCL_STATIC); + value = Tcl_GetVar2(interp, argv[1], (char *) 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], (char *) 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?\"", (char *) NULL); + return TCL_ERROR; + } +} + +/* + *---------------------------------------------------------------------- + * + * TestsaveresultCmd -- * - * Implements the "testsetnoerr" cmd that is used when testing - * the Tcl_Set/GetVar C Api without TCL_LEAVE_ERR_MSG flag + * 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: @@ -2680,42 +3766,461 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ static int -TestsetnoerrCmd(dummy, interp, argc, argv) +TestsaveresultCmd(dummy, interp, objc, objv) + ClientData dummy; /* Not used. */ + register Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* The argument objects. */ +{ + int discard, result, index; + Tcl_SavedResult state; + Tcl_Obj *objPtr; + static char *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, "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 = interp->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(blockPtr) + char *blockPtr; +{ + freeCount++; +} + +/* + *---------------------------------------------------------------------- + * + * TeststatprocCmd -- + * + * Implements the "testTclStatProc" cmd that is used to test the + * 'TclStatInsertProc' & 'TclStatDeleteProc' C Apis. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +TeststatprocCmd (dummy, interp, argc, argv) + ClientData dummy; /* Not used. */ + register Tcl_Interp *interp; /* Current interpreter. */ + int argc; /* Number of arguments. */ + char **argv; /* Argument strings. */ +{ + TclStatProc_ *proc; + int retVal; + + if (argc != 3) { + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], " option arg\"", (char *) NULL); + return TCL_ERROR; + } + + if (strcmp(argv[2], "TclpStat") == 0) { + proc = TclpStat; + } else if (strcmp(argv[2], "TestStatProc1") == 0) { + proc = TestStatProc1; + } else if (strcmp(argv[2], "TestStatProc2") == 0) { + proc = TestStatProc2; + } else if (strcmp(argv[2], "TestStatProc3") == 0) { + proc = TestStatProc3; + } else { + Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ", + "must be TclpStat, ", + "TestStatProc1, TestStatProc2, or TestStatProc3", + (char *) NULL); + return TCL_ERROR; + } + + if (strcmp(argv[1], "insert") == 0) { + if (proc == TclpStat) { + Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ", + "must be ", + "TestStatProc1, TestStatProc2, or TestStatProc3", + (char *) NULL); + return TCL_ERROR; + } + retVal = TclStatInsertProc(proc); + } else if (strcmp(argv[1], "delete") == 0) { + retVal = TclStatDeleteProc(proc); + } else { + Tcl_AppendResult(interp, "bad option \"", argv[1], "\": ", + "must be insert or delete", (char *) NULL); + return TCL_ERROR; + } + + if (retVal == TCL_ERROR) { + Tcl_AppendResult(interp, "\"", argv[2], "\": ", + "could not be ", argv[1], "ed", (char *) NULL); + } + + return retVal; +} + +/* Be careful in the compares in these tests, since the Macintosh puts a + * leading : in the beginning of non-absolute paths before passing them + * into the file command procedures. + */ + +static int +TestStatProc1(path, buf) + CONST char *path; + TclStat_ *buf; +{ + buf->st_size = 1234; + return ((strstr(path, "testStat1%.fil") == NULL) ? -1 : 0); +} + + +static int +TestStatProc2(path, buf) + CONST char *path; + TclStat_ *buf; +{ + buf->st_size = 2345; + return ((strstr(path, "testStat2%.fil") == NULL) ? -1 : 0); +} + + +static int +TestStatProc3(path, buf) + CONST char *path; + TclStat_ *buf; +{ + buf->st_size = 3456; + return ((strstr(path, "testStat3%.fil") == NULL) ? -1 : 0); +} + +/* + *---------------------------------------------------------------------- + * + * TestaccessprocCmd -- + * + * Implements the "testTclAccessProc" cmd that is used to test the + * 'TclAccessInsertProc' & 'TclAccessDeleteProc' C Apis. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +TestaccessprocCmd (dummy, interp, argc, argv) + ClientData dummy; /* Not used. */ + register Tcl_Interp *interp; /* Current interpreter. */ + int argc; /* Number of arguments. */ + char **argv; /* Argument strings. */ +{ + TclAccessProc_ *proc; + int retVal; + + if (argc != 3) { + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], " option arg\"", (char *) NULL); + return TCL_ERROR; + } + + if (strcmp(argv[2], "TclpAccess") == 0) { + proc = TclpAccess; + } else if (strcmp(argv[2], "TestAccessProc1") == 0) { + proc = TestAccessProc1; + } else if (strcmp(argv[2], "TestAccessProc2") == 0) { + proc = TestAccessProc2; + } else if (strcmp(argv[2], "TestAccessProc3") == 0) { + proc = TestAccessProc3; + } else { + Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ", + "must be TclpAccess, ", + "TestAccessProc1, TestAccessProc2, or TestAccessProc3", + (char *) NULL); + return TCL_ERROR; + } + + if (strcmp(argv[1], "insert") == 0) { + if (proc == TclpAccess) { + Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ", + "must be ", + "TestAccessProc1, TestAccessProc2, or TestAccessProc3", + (char *) NULL); + return TCL_ERROR; + } + retVal = TclAccessInsertProc(proc); + } else if (strcmp(argv[1], "delete") == 0) { + retVal = TclAccessDeleteProc(proc); + } else { + Tcl_AppendResult(interp, "bad option \"", argv[1], "\": ", + "must be insert or delete", (char *) NULL); + return TCL_ERROR; + } + + if (retVal == TCL_ERROR) { + Tcl_AppendResult(interp, "\"", argv[2], "\": ", + "could not be ", argv[1], "ed", (char *) NULL); + } + + return retVal; +} + + +static int +TestAccessProc1(path, mode) + CONST char *path; + int mode; +{ + return ((strstr(path, "testAccess1%.fil") == NULL) ? -1 : 0); +} + + +static int +TestAccessProc2(path, mode) + CONST char *path; + int mode; +{ + return ((strstr(path, "testAccess2%.fil") == NULL) ? -1 : 0); +} + + +static int +TestAccessProc3(path, mode) + CONST char *path; + int mode; +{ + return ((strstr(path, "testAccess3%.fil") == NULL) ? -1 : 0); +} + +/* + *---------------------------------------------------------------------- + * + * TestopenfilechannelprocCmd -- + * + * Implements the "testTclOpenFileChannelProc" cmd that is used to test the + * 'TclOpenFileChannelInsertProc' & 'TclOpenFileChannelDeleteProc' C Apis. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +TestopenfilechannelprocCmd (dummy, interp, argc, argv) ClientData dummy; /* Not used. */ register Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */ { - char *value; - if (argc == 2) { - Tcl_SetResult(interp, "before get", TCL_STATIC); - value = Tcl_GetVar2(interp, argv[1], (char *) NULL, TCL_PARSE_PART1); - if (value == NULL) { - return TCL_ERROR; - } - Tcl_SetResult(interp, value, TCL_VOLATILE); - return TCL_OK; - } else if (argc == 3) { - char *m1 = "before set"; - char *message=Tcl_Alloc(strlen(m1)+1); - - strcpy(message,m1); - - Tcl_SetResult(interp, message, TCL_DYNAMIC); - - value = Tcl_SetVar2(interp, argv[1], (char *) NULL, argv[2], - TCL_PARSE_PART1); - if (value == NULL) { - return TCL_ERROR; - } - Tcl_SetResult(interp, value, TCL_VOLATILE); - return TCL_OK; - } else { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " varName ?newValue?\"", (char *) NULL); - return TCL_ERROR; - } -} - + TclOpenFileChannelProc_ *proc; + int retVal; + + if (argc != 3) { + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], " option arg\"", (char *) NULL); + return TCL_ERROR; + } + + if (strcmp(argv[2], "TclpOpenFileChannel") == 0) { + proc = TclpOpenFileChannel; + } else if (strcmp(argv[2], "TestOpenFileChannelProc1") == 0) { + proc = TestOpenFileChannelProc1; + } else if (strcmp(argv[2], "TestOpenFileChannelProc2") == 0) { + proc = TestOpenFileChannelProc2; + } else if (strcmp(argv[2], "TestOpenFileChannelProc3") == 0) { + proc = TestOpenFileChannelProc3; + } else { + Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ", + "must be TclpOpenFileChannel, ", + "TestOpenFileChannelProc1, TestOpenFileChannelProc2, or ", + "TestOpenFileChannelProc3", + (char *) NULL); + return TCL_ERROR; + } + + if (strcmp(argv[1], "insert") == 0) { + if (proc == TclpOpenFileChannel) { + Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ", + "must be ", + "TestOpenFileChannelProc1, TestOpenFileChannelProc2, or ", + "TestOpenFileChannelProc3", + (char *) NULL); + return TCL_ERROR; + } + retVal = TclOpenFileChannelInsertProc(proc); + } else if (strcmp(argv[1], "delete") == 0) { + retVal = TclOpenFileChannelDeleteProc(proc); + } else { + Tcl_AppendResult(interp, "bad option \"", argv[1], "\": ", + "must be insert or delete", (char *) NULL); + return TCL_ERROR; + } + + if (retVal == TCL_ERROR) { + Tcl_AppendResult(interp, "\"", argv[2], "\": ", + "could not be ", argv[1], "ed", (char *) NULL); + } + + return retVal; +} + + +static Tcl_Channel +TestOpenFileChannelProc1(interp, fileName, modeString, permissions) + Tcl_Interp *interp; /* Interpreter for error reporting; + * can be NULL. */ + char *fileName; /* Name of file to open. */ + 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? */ +{ + if (!strcmp("testOpenFileChannel1%.fil", fileName)) { + return (TclpOpenFileChannel(interp, "__testOpenFileChannel1%__.fil", + modeString, permissions)); + } else { + return (NULL); + } +} + + +static Tcl_Channel +TestOpenFileChannelProc2(interp, fileName, modeString, permissions) + Tcl_Interp *interp; /* Interpreter for error reporting; + * can be NULL. */ + char *fileName; /* Name of file to open. */ + 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? */ +{ + if (!strcmp("testOpenFileChannel2%.fil", fileName)) { + return (TclpOpenFileChannel(interp, "__testOpenFileChannel2%__.fil", + modeString, permissions)); + } else { + return (NULL); + } +} + + +static Tcl_Channel +TestOpenFileChannelProc3(interp, fileName, modeString, permissions) + Tcl_Interp *interp; /* Interpreter for error reporting; + * can be NULL. */ + char *fileName; /* Name of file to open. */ + 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? */ +{ + if (!strcmp("testOpenFileChannel3%.fil", fileName)) { + return (TclpOpenFileChannel(interp, "__testOpenFileChannel3%__.fil", + modeString, permissions)); + } else { + return (NULL); + } +} Index: generic/tclTestObj.c ================================================================== --- generic/tclTestObj.c +++ generic/tclTestObj.c @@ -4,16 +4,16 @@ * This file contains C command procedures 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, 1996 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclTestObj.c 1.27 97/05/19 17:37:31 + * RCS: @(#) $Id: tclTestObj.c,v 1.1.2.3 1998/12/01 05:01:01 stanton Exp $ */ #include "tclInt.h" /* @@ -66,11 +66,11 @@ * This procedure 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 interp->result if an error occurs. + * message in the interp's result if an error occurs. * * Side effects: * Creates and registers several new testing commands. * *---------------------------------------------------------------------- @@ -126,29 +126,25 @@ ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - int varIndex, boolValue, length; + int varIndex, boolValue; char *index, *subCmd; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } - /* - * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE. - */ - - index = Tcl_GetStringFromObj(objv[2], &length); + index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } - subCmd = Tcl_GetStringFromObj(objv[1], &length); + subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "set") == 0) { if (objc != 4) { goto wrongNumArgs; } if (Tcl_GetBooleanFromObj(interp, objv[3], &boolValue) != TCL_OK) { @@ -194,11 +190,11 @@ SetVarToObj(varIndex, Tcl_NewBooleanObj(!boolValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "bad option \"", Tcl_GetStringFromObj(objv[1], (int *) NULL), + "bad option \"", Tcl_GetString(objv[1]), "\": must be set, get, or not", (char *) NULL); return TCL_ERROR; } return TCL_OK; } @@ -225,25 +221,20 @@ ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - int length; char *subCmd; char buf[20]; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } - /* - * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE. - */ - - subCmd = Tcl_GetStringFromObj(objv[1], &length); + subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "double") == 0) { double d; if (objc != 3) { goto wrongNumArgs; @@ -253,11 +244,11 @@ } sprintf(buf, "%f", d); Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "bad option \"", Tcl_GetStringFromObj(objv[1], (int *) NULL), + "bad option \"", Tcl_GetString(objv[1]), "\": must be double", (char *) NULL); return TCL_ERROR; } return TCL_OK; } @@ -286,35 +277,31 @@ ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - int varIndex, length; + int varIndex; double doubleValue; char *index, *subCmd, *string; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } - /* - * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE. - */ - - index = Tcl_GetStringFromObj(objv[2], &length); + index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } - subCmd = Tcl_GetStringFromObj(objv[1], &length); + subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "set") == 0) { if (objc != 4) { goto wrongNumArgs; } - string = Tcl_GetStringFromObj(objv[3], &length); + string = Tcl_GetString(objv[3]); if (Tcl_GetDouble(interp, string, &doubleValue) != TCL_OK) { return TCL_ERROR; } /* @@ -373,11 +360,11 @@ SetVarToObj(varIndex, Tcl_NewDoubleObj( (doubleValue / 10.0) )); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "bad option \"", Tcl_GetStringFromObj(objv[1], (int *) NULL), + "bad option \"", Tcl_GetString(objv[1]), "\": must be set, get, mult10, or div10", (char *) NULL); return TCL_ERROR; } return TCL_OK; } @@ -405,15 +392,15 @@ 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, dummy, result; + int allowAbbrev, index, index2, setError, i, result; char **argv; static char *tablePtr[] = {"a", "b", "check", (char *) NULL}; - if ((objc == 3) && (strcmp(Tcl_GetStringFromObj(objv[1], &dummy), + 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. @@ -442,17 +429,31 @@ return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, objv[2], &allowAbbrev) != TCL_OK) { return TCL_ERROR; } + argv = (char **) ckalloc((unsigned) ((objc-3) * sizeof(char *))); for (i = 4; i < objc; i++) { - argv[i-4] = Tcl_GetStringFromObj(objv[i], &dummy); + argv[i-4] = Tcl_GetString(objv[i]); } argv[objc-4] = NULL; - result = Tcl_GetIndexFromObj(setError ? interp : NULL, objv[3], - argv, "token", allowAbbrev ? 0 : TCL_EXACT, &index); + + /* + * 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 == Tcl_GetObjType("index")) + && (objv[3]->internalRep.twoPtrValue.ptr1 == (VOID *) argv)) { + objv[3]->typePtr = NULL; + } + + result = Tcl_GetIndexFromObj((setError? interp : NULL), objv[3], + argv, "token", (allowAbbrev? 0 : TCL_EXACT), &index); ckfree((char *) argv); if (result == TCL_OK) { Tcl_SetIntObj(Tcl_GetObjResult(interp), index); } return result; @@ -481,35 +482,31 @@ ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - int intValue, varIndex, length, i; + int intValue, varIndex, i; long longValue; char *index, *subCmd, *string; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } - /* - * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE. - */ - - index = Tcl_GetStringFromObj(objv[2], &length); + index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } - subCmd = Tcl_GetStringFromObj(objv[1], &length); + subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "set") == 0) { if (objc != 4) { goto wrongNumArgs; } - string = Tcl_GetStringFromObj(objv[3], &length); + string = Tcl_GetString(objv[3]); if (Tcl_GetInt(interp, string, &i) != TCL_OK) { return TCL_ERROR; } intValue = i; @@ -529,11 +526,11 @@ Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "set2") == 0) { /* doesn't set result */ if (objc != 4) { goto wrongNumArgs; } - string = Tcl_GetStringFromObj(objv[3], &length); + 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])) { @@ -543,11 +540,11 @@ } } else if (strcmp(subCmd, "setlong") == 0) { if (objc != 4) { goto wrongNumArgs; } - string = Tcl_GetStringFromObj(objv[3], &length); + 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])) { @@ -584,38 +581,45 @@ } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); + } else if (strcmp(subCmd, "get2") == 0) { + if (objc != 3) { + goto wrongNumArgs; + } + if (CheckIfVarUnset(interp, 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. */ - long maxLong = LONG_MAX; - 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], maxLong); - } else { - SetVarToObj(varIndex, Tcl_NewLongObj(maxLong)); - } - 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); - } +#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(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, varIndex)) { @@ -648,12 +652,13 @@ SetVarToObj(varIndex, Tcl_NewIntObj( (intValue / 10) )); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "bad option \"", Tcl_GetStringFromObj(objv[1], (int *) NULL), - "\": must be set, get, mult10, or div10", (char *) NULL); + "bad option \"", Tcl_GetString(objv[1]), + "\": must be set, get, get2, mult10, or div10", + (char *) NULL); return TCL_ERROR; } return TCL_OK; } @@ -682,36 +687,30 @@ Tcl_Obj *CONST objv[]; /* Argument objects. */ { int varIndex, destIndex, i; char *index, *subCmd, *string; Tcl_ObjType *targetType; - char buf[20]; - int length; if (objc < 2) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } - /* - * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE. - */ - - subCmd = Tcl_GetStringFromObj(objv[1], &length); + subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "assign") == 0) { if (objc != 4) { goto wrongNumArgs; } - index = Tcl_GetStringFromObj(objv[2], &length); + index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - string = Tcl_GetStringFromObj(objv[3], &length); + string = Tcl_GetString(objv[3]); if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) { return TCL_ERROR; } SetVarToObj(destIndex, varPtr[varIndex]); Tcl_SetObjResult(interp, varPtr[destIndex]); @@ -718,18 +717,18 @@ } else if (strcmp(subCmd, "convert") == 0) { char *typeName; if (objc != 4) { goto wrongNumArgs; } - index = Tcl_GetStringFromObj(objv[2], &length); + index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - typeName = Tcl_GetStringFromObj(objv[3], &length); + typeName = Tcl_GetString(objv[3]); if ((targetType = Tcl_GetObjType(typeName)) == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no type ", typeName, " found", (char *) NULL); return TCL_ERROR; } @@ -740,18 +739,18 @@ Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "duplicate") == 0) { if (objc != 4) { goto wrongNumArgs; } - index = Tcl_GetStringFromObj(objv[2], &length); + index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - string = Tcl_GetStringFromObj(objv[3], &length); + string = Tcl_GetString(objv[3]); if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) { return TCL_ERROR; } SetVarToObj(destIndex, Tcl_DuplicateObj(varPtr[varIndex])); Tcl_SetObjResult(interp, varPtr[destIndex]); @@ -767,34 +766,36 @@ } } else if (strcmp(subCmd, "newobj") == 0) { if (objc != 3) { goto wrongNumArgs; } - index = Tcl_GetStringFromObj(objv[2], &length); + index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } SetVarToObj(varIndex, Tcl_NewObj()); Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "refcount") == 0) { + char buf[TCL_INTEGER_SPACE]; + if (objc != 3) { goto wrongNumArgs; } - index = Tcl_GetStringFromObj(objv[2], &length); + index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } - sprintf(buf, "%d", varPtr[varIndex]->refCount); - Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); + TclFormatInt(buf, varPtr[varIndex]->refCount); + Tcl_SetResult(interp, buf, TCL_VOLATILE); } else if (strcmp(subCmd, "type") == 0) { if (objc != 3) { goto wrongNumArgs; } - index = Tcl_GetStringFromObj(objv[2], &length); + index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; @@ -813,11 +814,11 @@ return TCL_ERROR; } } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", - Tcl_GetStringFromObj(objv[1], (int *) NULL), + Tcl_GetString(objv[1]), "\": must be assign, convert, duplicate, freeallvars, ", "newobj, objcount, refcount, type, or types", (char *) NULL); return TCL_ERROR; } @@ -848,24 +849,24 @@ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { int varIndex, option, i, length; -#define MAX_STRINGS 10 +#define MAX_STRINGS 11 char *index, *string, *strings[MAX_STRINGS+1]; static char *options[] = { - "append", "appendstrings", "get", "length", "length2", + "append", "appendstrings", "get", "get2", "length", "length2", "set", "set2", "setlength", (char *) NULL }; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } - index = Tcl_GetStringFromObj(objv[2], (int *) NULL); + 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) @@ -890,11 +891,11 @@ */ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } - string = Tcl_GetStringFromObj(objv[3], (int *) NULL); + 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)) { @@ -911,13 +912,15 @@ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } for (i = 3; i < objc; i++) { - strings[i-3] = Tcl_GetStringFromObj(objv[i], (int *) NULL); + strings[i-3] = Tcl_GetString(objv[i]); } - strings[objc-3] = NULL; + 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]); @@ -929,25 +932,35 @@ if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); break; - case 3: /* length */ + case 3: /* get2 */ + if (objc != 3) { + goto wrongNumArgs; + } + if (CheckIfVarUnset(interp, 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 4: /* length2 */ + case 5: /* length2 */ if (objc != 3) { goto wrongNumArgs; } Tcl_SetIntObj(Tcl_GetObjResult(interp), (varPtr[varIndex] != NULL) ? (int) varPtr[varIndex]->internalRep.longValue : -1); break; - case 5: /* set */ + case 6: /* set */ if (objc != 4) { goto wrongNumArgs; } /* @@ -966,17 +979,17 @@ } else { SetVarToObj(varIndex, Tcl_NewStringObj(string, length)); } Tcl_SetObjResult(interp, varPtr[varIndex]); break; - case 6: /* set2 */ + case 7: /* set2 */ if (objc != 4) { goto wrongNumArgs; } SetVarToObj(varIndex, objv[3]); break; - case 7: /* setlength */ + case 8: /* setlength */ if (objc != 4) { goto wrongNumArgs; } if (Tcl_GetIntFromObj(interp, objv[3], &length) != TCL_OK) { return TCL_ERROR; @@ -1084,14 +1097,14 @@ CheckIfVarUnset(interp, varIndex) Tcl_Interp *interp; /* Interpreter for error reporting. */ int varIndex; /* Index of the test variable to check. */ { if (varPtr[varIndex] == NULL) { - char buf[100]; + 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; } ADDED generic/tclTestProcBodyObj.c Index: generic/tclTestProcBodyObj.c ================================================================== --- /dev/null +++ generic/tclTestProcBodyObj.c @@ -0,0 +1,319 @@ +/* + * 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. + * + * RCS: @(#) $Id: tclTestProcBodyObj.c,v 1.1.2.2 1998/11/11 04:08:24 stanton Exp $ + */ + +#include "tclInt.h" + +/* + * name and version of this package + */ + +static char packageName[] = "procbodytest"; +static char packageVersion[] = "1.0"; + +/* + * Name of the commands exported by this package + */ + +static char procCommand[] = "proc"; + +/* + * this struct describes an entry in the table of command names and command + * procs + */ + +typedef struct CmdTable +{ + 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 _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +static int ProcBodyTestInitInternal _ANSI_ARGS_((Tcl_Interp *interp, + int isSafe)); +static int RegisterCommand _ANSI_ARGS_((Tcl_Interp* interp, + char *namespace, CONST CmdTable *cmdTablePtr)); +int Procbodytest_Init _ANSI_ARGS_((Tcl_Interp * interp)); +int Procbodytest_SafeInit _ANSI_ARGS_((Tcl_Interp * interp)); + +/* + * 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 procedure initializes the "procbodytest" package. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Procbodytest_Init(interp) + Tcl_Interp *interp; /* the Tcl interpreter for which the package + * is initialized */ +{ + return ProcBodyTestInitInternal(interp, 0); +} + +/* + *---------------------------------------------------------------------- + * + * Procbodytest_SafeInit -- + * + * This procedure initializes the "procbodytest" package. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Procbodytest_SafeInit(interp) + Tcl_Interp *interp; /* the Tcl interpreter for which the package + * is initialized */ +{ + return ProcBodyTestInitInternal(interp, 1); +} + +/* + *---------------------------------------------------------------------- + * + * RegisterCommand -- + * + * This procedure registers a command in the context of the given namespace. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int RegisterCommand(interp, namespace, cmdTablePtr) + Tcl_Interp* interp; /* the Tcl interpreter for which the + * operation is performed */ + 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_Eval(interp, buf) != 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 procedure 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(interp, isSafe) + 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 (dummy, interp, objc, objv) + ClientData dummy; /* context; not used */ + Tcl_Interp *interp; /* the current interpreter */ + int objc; /* argument count */ + Tcl_Obj *CONST objv[]; /* arguments */ +{ + char *fullName; + Tcl_Command procCmd; + Command *cmdPtr; + Proc *procPtr = (Proc *) 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_GetStringFromObj(objv[3], (int *) NULL); + procCmd = Tcl_FindCommand(interp, fullName, (Tcl_Namespace *) 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->objProc is either 0 or TclObjInterpProc, + * and cmdPtr->proc is either 0 or TclProcInterpProc. + * Also, the compile proc should be 0, but we don't check for that. + */ + + if (((cmdPtr->objProc != NULL) + && (cmdPtr->objProc != TclGetObjInterpProc())) + || ((cmdPtr->proc != NULL) + && (cmdPtr->proc != TclGetInterpProc()))) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "command \"", fullName, + "\" is not a Tcl procedure", (char *) NULL); + return TCL_ERROR; + } + + /* + * it is a Tcl procedure: the client data is the Proc structure + */ + + if (cmdPtr->objProc != NULL) { + procPtr = (Proc *) cmdPtr->objClientData; + } else if (cmdPtr->proc != NULL) { + procPtr = (Proc *) cmdPtr->clientData; + } + + if (procPtr == NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "procedure \"", fullName, + "\" does not have a Proc struct!", (char *) 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, "\"", (char *) NULL); + return TCL_ERROR; + } + Tcl_IncrRefCount(bodyObjPtr); + + myobjv[0] = objv[0]; + myobjv[1] = objv[1]; + myobjv[2] = objv[2]; + myobjv[3] = bodyObjPtr; + myobjv[4] = (Tcl_Obj *) NULL; + + result = Tcl_ProcObjCmd((ClientData) NULL, interp, objc, myobjv); + Tcl_DecrRefCount(bodyObjPtr); + + return result; +} ADDED generic/tclThread.c Index: generic/tclThread.c ================================================================== --- /dev/null +++ generic/tclThread.c @@ -0,0 +1,563 @@ +/* + * 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. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclThread.c,v 1.1.2.8 1999/04/14 00:33:27 surles Exp $ + */ + +#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 */ + char **list; /* List of pointers */ +} SyncObjRecord; + +static SyncObjRecord keyRecord; +static SyncObjRecord mutexRecord; +static SyncObjRecord condRecord; + +/* + * Prototypes of functions used only in this file + */ + +static void RememberSyncObject _ANSI_ARGS_((char *objPtr, + SyncObjRecord *recPtr)); +static void ForgetSyncObject _ANSI_ARGS_((char *objPtr, + SyncObjRecord *recPtr)); + + +/* + *---------------------------------------------------------------------- + * + * Tcl_GetThreadData -- + * + * This procedure 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(keyPtr, size) + Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk */ + int size; /* Size of storage block */ +{ + VOID *result; +#ifdef TCL_THREADS + + /* + * See if this is the first thread to init this key. + */ + + if (*keyPtr == NULL) { + TclpThreadDataKeyInit(keyPtr); + } + + /* + * Initialize the key for this thread. + */ + + result = TclpThreadDataKeyGet(keyPtr); + if (result == NULL) { + result = (VOID *)ckalloc((size_t)size); + memset(result, 0, (size_t)size); + TclpThreadDataKeySet(keyPtr, result); + } +#else + if (*keyPtr == NULL) { + result = (VOID *)ckalloc((size_t)size); + memset((char *)result, 0, (size_t)size); + *keyPtr = (Tcl_ThreadDataKey)result; + TclRememberDataKey(keyPtr); + } + result = *(VOID **)keyPtr; +#endif + return result; +} + +/* + *---------------------------------------------------------------------- + * + * TclThreadDataKeyGet -- + * + * This procedure 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(keyPtr) + Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, + * really (pthread_key_t **) */ +{ +#ifdef TCL_THREADS + return (VOID *)TclpThreadDataKeyGet(keyPtr); +#else + char *result = *(char **)keyPtr; + return (VOID *)result; +#endif /* TCL_THREADS */ +} + + +/* + *---------------------------------------------------------------------- + * + * TclThreadDataKeySet -- + * + * This procedure sets a thread local storage pointer. + * + * Results: + * None. + * + * Side effects: + * The assigned value will be returned by TclpThreadDataKeyGet. + * + *---------------------------------------------------------------------- + */ + +void +TclThreadDataKeySet(keyPtr, data) + Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, + * really (pthread_key_t **) */ + VOID *data; /* Thread local storage */ +{ +#ifdef TCL_THREADS + if (*keyPtr == NULL) { + TclpThreadDataKeyInit(keyPtr); + } + TclpThreadDataKeySet(keyPtr, data); +#else + *keyPtr = (Tcl_ThreadDataKey)data; +#endif /* TCL_THREADS */ +} + + + +/* + *---------------------------------------------------------------------- + * + * RememberSyncObject + * + * Keep a list of (mutexes/condition variable/data key) + * used during finalization. + * + * Results: + * None. + * + * Side effects: + * Add to the appropriate list. + * + *---------------------------------------------------------------------- + */ + +static void +RememberSyncObject(objPtr, recPtr) + char *objPtr; /* Pointer to sync object */ + SyncObjRecord *recPtr; /* Record of sync objects */ +{ + char **newList; + int i, j; + + /* + * Save the pointer to the allocated object so it can be finalized. + * 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 = (char **)ckalloc(recPtr->max * sizeof(char *)); + for (i=0,j=0 ; inum ; i++) { + if (recPtr->list[i] != NULL) { + newList[j++] = recPtr->list[i]; + } + } + if (recPtr->list != NULL) { + ckfree((char *)recPtr->list); + } + recPtr->list = newList; + recPtr->num = j; + } + recPtr->list[recPtr->num] = objPtr; + recPtr->num++; +} + +/* + *---------------------------------------------------------------------- + * + * ForgetSyncObject + * + * Remove a single object from the list. + * + * Results: + * None. + * + * Side effects: + * Remove from the appropriate list. + * + *---------------------------------------------------------------------- + */ + +static void +ForgetSyncObject(objPtr, recPtr) + char *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. + * + * Results: + * None. + * + * Side effects: + * Add to the mutex list. + * + *---------------------------------------------------------------------- + */ + +void +TclRememberMutex(mutexPtr) + Tcl_Mutex *mutexPtr; +{ + RememberSyncObject((char *)mutexPtr, &mutexRecord); +} + +/* + *---------------------------------------------------------------------- + * + * TclFinalizeMutex + * + * Finalize a single mutex and remove it from the + * list of remembered objects. + * + * Results: + * None. + * + * Side effects: + * Remove the mutex from the list. + * + *---------------------------------------------------------------------- + */ + +void +TclFinalizeMutex(mutexPtr) + Tcl_Mutex *mutexPtr; +{ +#ifdef TCL_THREADS + TclpFinalizeMutex(mutexPtr); +#endif + ForgetSyncObject((char *)mutexPtr, &mutexRecord); +} + +/* + *---------------------------------------------------------------------- + * + * TclRememberDataKey + * + * Keep a list of thread data keys used during finalization. + * + * Results: + * None. + * + * Side effects: + * Add to the key list. + * + *---------------------------------------------------------------------- + */ + +void +TclRememberDataKey(keyPtr) + Tcl_ThreadDataKey *keyPtr; +{ + RememberSyncObject((char *)keyPtr, &keyRecord); +} + +/* + *---------------------------------------------------------------------- + * + * TclRememberCondition + * + * Keep a list of condition variables used during finalization. + * + * Results: + * None. + * + * Side effects: + * Add to the condition variable list. + * + *---------------------------------------------------------------------- + */ + +void +TclRememberCondition(condPtr) + Tcl_Condition *condPtr; +{ + RememberSyncObject((char *)condPtr, &condRecord); +} + +/* + *---------------------------------------------------------------------- + * + * TclFinalizeCondition + * + * 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 +TclFinalizeCondition(condPtr) + Tcl_Condition *condPtr; +{ +#ifdef TCL_THREADS + TclpFinalizeCondition(condPtr); +#endif + ForgetSyncObject((char *)condPtr, &condRecord); +} + +/* + *---------------------------------------------------------------------- + * + * TclFinalizeThreadData -- + * + * This procedure cleans up the thread-local storage. This is + * called once for each thread. + * + * Results: + * None. + * + * Side effects: + * Frees up all thread local storage. + * + *---------------------------------------------------------------------- + */ + +void +TclFinalizeThreadData() +{ + int i; + Tcl_ThreadDataKey *keyPtr; + + TclpMasterLock(); + for (i=0 ; iinterp == NULL) { + Tcl_MutexLock(&threadMutex); + tsdPtr->interp = interp; + ListUpdateInner(tsdPtr); + Tcl_CreateThreadExitHandler(ThreadExitProc, NULL); + Tcl_MutexUnlock(&threadMutex); + } + + switch ((enum options)option) { + case THREAD_CREATE: { + char *script; + if (objc == 2) { + script = "testthread wait"; /* Just enter the event loop */ + } else if (objc == 3) { + script = Tcl_GetString(objv[2]); + } else { + Tcl_WrongNumArgs(interp, 2, objv, "?script?"); + return TCL_ERROR; + } + return TclCreateThread(interp, script); + } + case THREAD_EXIT: { + if (objc > 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return TCL_ERROR; + } + ListRemove(NULL); + Tcl_ExitThread(0); + return TCL_OK; + } + case THREAD_ID: + if (objc == 2) { + Tcl_Obj *idObj = Tcl_NewIntObj((int)Tcl_GetCurrentThread()); + Tcl_SetObjResult(interp, idObj); + return TCL_OK; + } else { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; + } + case THREAD_NAMES: { + if (objc > 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; + } + return TclThreadList(interp); + } + case THREAD_SEND: { + int id; + char *script; + int wait, arg; + + if ((objc != 4) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 1, objv, "send ?-async? id script"); + return TCL_ERROR; + } + if (objc == 5) { + if (strcmp("-async", Tcl_GetString(objv[2])) != 0) { + Tcl_WrongNumArgs(interp, 1, objv, "send ?-async? id script"); + return TCL_ERROR; + } + wait = 0; + arg = 3; + } else { + wait = 1; + arg = 2; + } + if (Tcl_GetIntFromObj(interp, objv[arg], &id) != TCL_OK) { + return TCL_ERROR; + } + arg++; + script = Tcl_GetString(objv[arg]); + return TclThreadSend(interp, (Tcl_ThreadId) id, script, wait); + } + case THREAD_WAIT: { + while (1) { + (void) Tcl_DoOneEvent(TCL_ALL_EVENTS); + } + } + case THREAD_ERRORPROC: { + /* + * Arrange for this proc to handle thread death errors. + */ + + char *proc; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "errorproc 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; + } + } + return TCL_OK; +} + + +/* + *---------------------------------------------------------------------- + * + * TclCreateThread -- + * + * 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 */ +int +TclCreateThread(interp, script) + Tcl_Interp *interp; /* Current interpreter. */ + CONST char *script; /* Script to execute */ +{ + ThreadCtrl ctrl; + Tcl_ThreadId id; + + ctrl.script = (char*)ckalloc( strlen(script) + 1 ); + strcpy(ctrl.script, script); + ctrl.condWait = NULL; + ctrl.flags = 0; + + Tcl_MutexLock(&threadMutex); + if (TclpThreadCreate(&id, NewThread, (ClientData) &ctrl) != TCL_OK) { + Tcl_MutexUnlock(&threadMutex); + Tcl_AppendResult(interp,"can't create a new thread",0); + ckfree((void*)ctrl.script); + 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); + TclFinalizeCondition(&ctrl.condWait); + Tcl_SetObjResult(interp, Tcl_NewIntObj((int)id)); + return TCL_OK; +} + +/* + *------------------------------------------------------------------------ + * + * NewThread -- + * + * 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. + * + *------------------------------------------------------------------------ + */ +#ifdef MAC_TCL +static pascal void * +#else +static void +#endif +NewThread(clientData) + ClientData clientData; +{ + ThreadCtrl *ctrlPtr = (ThreadCtrl*)clientData; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadCtrl ctrl; + int result; + + ctrl = *ctrlPtr; + + /* + * Initialize the interpreter. This should be more general. + */ + + tsdPtr->interp = Tcl_CreateInterp(); + result = Tcl_Init(tsdPtr->interp); + result = TclThread_Init(tsdPtr->interp); + + /* + * Update the list of threads. + */ + + Tcl_MutexLock(&threadMutex); + ListUpdateInner(tsdPtr); + Tcl_CreateThreadExitHandler(ThreadExitProc, NULL); + + /* + * Notify the parent we are alive. + */ + + Tcl_ConditionNotify(&ctrlPtr->condWait); + Tcl_MutexUnlock(&threadMutex); + + /* + * Run the script. + */ + + Tcl_Preserve((ClientData) tsdPtr->interp); + result = Tcl_Eval(tsdPtr->interp, ctrl.script); + if (result != TCL_OK) { + ThreadErrorProc(tsdPtr->interp); + } + + /* + * Clean up. + */ + + ListRemove(tsdPtr); + ckfree((char*)ctrl.script); + Tcl_Release((ClientData) tsdPtr->interp); + Tcl_DeleteInterp(tsdPtr->interp); + Tcl_ExitThread(result); +#ifdef MAC_TCL + return NULL; +#endif +} + +/* + *------------------------------------------------------------------------ + * + * ThreadErrorProc -- + * + * Send a message to the thread willing to hear about errors. + * + * Results: + * none + * + * Side effects: + * Send an event. + * + *------------------------------------------------------------------------ + */ +static void +ThreadErrorProc(interp) + Tcl_Interp *interp; /* Interp that failed */ +{ + Tcl_Channel errChannel; + char *errorInfo, *script; + char *argv[3]; + char buf[10]; + sprintf(buf, "%ld", (long) 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); + TclThreadSend(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(tsdPtr) + 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(tsdPtr) + 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; + Tcl_MutexUnlock(&threadMutex); +} + + +/* + *------------------------------------------------------------------------ + * + * TclThreadList -- + * + * Return a list of threads running Tcl interpreters. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ +int +TclThreadList(interp) + 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_NewIntObj((int)tsdPtr->threadId)); + } + Tcl_MutexUnlock(&threadMutex); + Tcl_SetObjResult(interp, listPtr); + return TCL_OK; +} + + +/* + *------------------------------------------------------------------------ + * + * TclThreadSend -- + * + * Send a script to another thread. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ +int +TclThreadSend(interp, id, script, wait) + Tcl_Interp *interp; /* The current interpreter. */ + Tcl_ThreadId id; /* Thread Id of other interpreter. */ + 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_GlobalEval(interp, script); + } + + /* + * Create the event for its event queue. + */ + + threadEventPtr = (ThreadEvent *) ckalloc(sizeof(ThreadEvent)); + threadEventPtr->script = ckalloc(strlen(script) + 1); + strcpy(threadEventPtr->script, script); + if (!wait) { + threadEventPtr->resultPtr = NULL; + } else { + resultPtr = (ThreadEventResult *) 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_MutexUnlock(&threadMutex); + Tcl_ThreadAlert(threadId); + + if (!wait) { + return TCL_OK; + } + + /* + * Block on the results and then get them. + */ + + Tcl_ResetResult(interp); + Tcl_MutexLock(&threadMutex); + 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_SetResult(interp, resultPtr->result, TCL_DYNAMIC); + TclFinalizeCondition(&resultPtr->done); + code = resultPtr->code; + + ckfree((char *) resultPtr); + + return code; +} + + +/* + *------------------------------------------------------------------------ + * + * 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. + * + *------------------------------------------------------------------------ + */ +int +ThreadEventProc(evPtr, mask) + 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; + char *result, *errorCode, *errorInfo; + + if (interp == NULL) { + code = TCL_ERROR; + result = "no target interp!"; + errorCode = "THREAD"; + errorInfo = ""; + } else { + Tcl_Preserve((ClientData) interp); + Tcl_ResetResult(interp); + code = Tcl_GlobalEval(interp, threadEventPtr->script); + result = Tcl_GetStringResult(interp); + if (code != TCL_OK) { + errorCode = Tcl_GetVar(interp, "errorCode", TCL_GLOBAL_ONLY); + errorInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); + } else { + errorCode = errorInfo = NULL; + } + } + 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((ClientData) interp); + } + return 1; +} + +/* + *------------------------------------------------------------------------ + * + * 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 */ +void +ThreadExitProc(dummy) + ClientData dummy; +{ + ThreadEventResult *resultPtr, *nextPtr; + Tcl_ThreadId self = Tcl_GetCurrentThread(); + + Tcl_MutexLock(&threadMutex); + 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((char *)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. + */ + + 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 */ Index: generic/tclTimer.c ================================================================== --- generic/tclTimer.c +++ generic/tclTimer.c @@ -7,22 +7,16 @@ * Copyright (c) 1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclTimer.c 1.9 97/07/29 16:21:53 + * RCS: @(#) $Id: tclTimer.c,v 1.1.2.3 1999/02/01 21:29:56 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" -/* - * This flag indicates whether this module has been initialized. - */ - -static int initialized = 0; - /* * 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). */ @@ -35,16 +29,10 @@ * deleted. */ struct TimerHandler *nextPtr; /* Next event in queue, or NULL for * end of queue. */ } TimerHandler; -static TimerHandler *firstTimerHandlerPtr = NULL; - /* First event in queue. */ -static int lastTimerId; /* Timer identifier of most recently - * created timer. */ -static int timerPending; /* 1 if a timer event is in the queue. */ - /* * 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. */ @@ -52,12 +40,11 @@ typedef struct AfterInfo { struct AfterAssocData *assocPtr; /* Pointer to the "tclAfter" assocData for * the interp in which command will be * executed. */ - char *command; /* Command to execute. Malloc'ed, so must - * be freed when structure is deallocated. */ + 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 @@ -94,20 +81,39 @@ int generation; /* Used to distinguish older handlers from * recently-created ones. */ struct IdleHandler *nextPtr;/* Next in list of active handlers. */ } IdleHandler; -static IdleHandler *idleList; - /* First in list of all idle handlers. */ -static IdleHandler *lastIdlePtr; - /* Last in list (or NULL for empty list). */ -static int idleGeneration; /* Used to fill in the "generation" fields +/* + * 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; /* * Prototypes for procedures referenced only in this file: */ @@ -114,12 +120,12 @@ static void AfterCleanupProc _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp)); static void AfterProc _ANSI_ARGS_((ClientData clientData)); static void FreeAfterPtr _ANSI_ARGS_((AfterInfo *afterPtr)); static AfterInfo * GetAfterEvent _ANSI_ARGS_((AfterAssocData *assocPtr, - char *string)); -static void InitTimer _ANSI_ARGS_((void)); + Tcl_Obj *commandPtr)); +static ThreadSpecificData *InitTimer _ANSI_ARGS_((void)); static void TimerExitProc _ANSI_ARGS_((ClientData clientData)); static int TimerHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr, int flags)); static void TimerCheckProc _ANSI_ARGS_((ClientData clientData, int flags)); @@ -132,31 +138,30 @@ * InitTimer -- * * This function initializes the timer module. * * Results: - * None. + * A pointer to the thread specific data. * * Side effects: * Registers the idle and timer event sources. * *---------------------------------------------------------------------- */ -static void +static ThreadSpecificData * InitTimer() { - initialized = 1; - lastTimerId = 0; - timerPending = 0; - idleGeneration = 0; - firstTimerHandlerPtr = NULL; - lastIdlePtr = NULL; - idleList = NULL; - - Tcl_CreateEventSource(TimerSetupProc, TimerCheckProc, NULL); - Tcl_CreateExitHandler(TimerExitProc, NULL); + ThreadSpecificData *tsdPtr = + (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); + + if (tsdPtr == NULL) { + tsdPtr = TCL_TSD_INIT(&dataKey); + Tcl_CreateEventSource(TimerSetupProc, TimerCheckProc, NULL); + Tcl_CreateThreadExitHandler(TimerExitProc, NULL); + } + return tsdPtr; } /* *---------------------------------------------------------------------- * @@ -177,11 +182,10 @@ static void TimerExitProc(clientData) ClientData clientData; /* Not used. */ { Tcl_DeleteEventSource(TimerSetupProc, TimerCheckProc, NULL); - initialized = 0; } /* *-------------------------------------------------------------- * @@ -208,14 +212,13 @@ Tcl_TimerProc *proc; /* Procedure to invoke. */ ClientData clientData; /* Arbitrary data to pass to proc. */ { register TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr; Tcl_Time time; + ThreadSpecificData *tsdPtr; - if (!initialized) { - InitTimer(); - } + tsdPtr = InitTimer(); timerHandlerPtr = (TimerHandler *) ckalloc(sizeof(TimerHandler)); /* * Compute when the event should fire. @@ -226,41 +229,42 @@ timerHandlerPtr->time.usec = time.usec + (milliseconds%1000)*1000; if (timerHandlerPtr->time.usec >= 1000000) { timerHandlerPtr->time.usec -= 1000000; timerHandlerPtr->time.sec += 1; } - + /* * Fill in other fields for the event. */ timerHandlerPtr->proc = proc; timerHandlerPtr->clientData = clientData; - lastTimerId++; - timerHandlerPtr->token = (Tcl_TimerToken) lastTimerId; + tsdPtr->lastTimerId++; + timerHandlerPtr->token = (Tcl_TimerToken) tsdPtr->lastTimerId; /* * Add the event to the queue in the correct position * (ordered by event firing time). */ - for (tPtr2 = firstTimerHandlerPtr, prevPtr = NULL; tPtr2 != NULL; + for (tPtr2 = tsdPtr->firstTimerHandlerPtr, prevPtr = NULL; tPtr2 != NULL; prevPtr = tPtr2, tPtr2 = tPtr2->nextPtr) { if ((tPtr2->time.sec > timerHandlerPtr->time.sec) || ((tPtr2->time.sec == timerHandlerPtr->time.sec) && (tPtr2->time.usec > timerHandlerPtr->time.usec))) { break; } } timerHandlerPtr->nextPtr = tPtr2; if (prevPtr == NULL) { - firstTimerHandlerPtr = timerHandlerPtr; + tsdPtr->firstTimerHandlerPtr = timerHandlerPtr; } else { prevPtr->nextPtr = timerHandlerPtr; } TimerSetupProc(NULL, TCL_ALL_EVENTS); + return timerHandlerPtr->token; } /* *-------------------------------------------------------------- @@ -285,19 +289,21 @@ Tcl_DeleteTimerHandler(token) Tcl_TimerToken token; /* Result previously returned by * Tcl_DeleteTimerHandler. */ { register TimerHandler *timerHandlerPtr, *prevPtr; + ThreadSpecificData *tsdPtr; - for (timerHandlerPtr = firstTimerHandlerPtr, prevPtr = NULL; + tsdPtr = InitTimer(); + for (timerHandlerPtr = tsdPtr->firstTimerHandlerPtr, prevPtr = NULL; timerHandlerPtr != NULL; prevPtr = timerHandlerPtr, timerHandlerPtr = timerHandlerPtr->nextPtr) { if (timerHandlerPtr->token != token) { continue; } if (prevPtr == NULL) { - firstTimerHandlerPtr = timerHandlerPtr->nextPtr; + tsdPtr->firstTimerHandlerPtr = timerHandlerPtr->nextPtr; } else { prevPtr->nextPtr = timerHandlerPtr->nextPtr; } ckfree((char *) timerHandlerPtr); return; @@ -326,28 +332,30 @@ TimerSetupProc(data, flags) ClientData data; /* Not used. */ int flags; /* Event flags as passed to Tcl_DoOneEvent. */ { Tcl_Time blockTime; + ThreadSpecificData *tsdPtr = InitTimer(); - if (((flags & TCL_IDLE_EVENTS) && idleList) - || ((flags & TCL_TIMER_EVENTS) && timerPending)) { + 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) && firstTimerHandlerPtr) { + } else if ((flags & TCL_TIMER_EVENTS) && tsdPtr->firstTimerHandlerPtr) { /* * Compute the timeout for the next timer on the list. */ TclpGetTime(&blockTime); - blockTime.sec = firstTimerHandlerPtr->time.sec - blockTime.sec; - blockTime.usec = firstTimerHandlerPtr->time.usec - blockTime.usec; + 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) { @@ -384,19 +392,21 @@ 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) && firstTimerHandlerPtr) { + if ((flags & TCL_TIMER_EVENTS) && tsdPtr->firstTimerHandlerPtr) { /* * Compute the timeout for the next timer on the list. */ TclpGetTime(&blockTime); - blockTime.sec = firstTimerHandlerPtr->time.sec - blockTime.sec; - blockTime.usec = firstTimerHandlerPtr->time.usec - blockTime.usec; + 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) { @@ -406,12 +416,13 @@ /* * If the first timer has expired, stick an event on the queue. */ - if (blockTime.sec == 0 && blockTime.usec == 0 && !timerPending) { - timerPending = 1; + if (blockTime.sec == 0 && blockTime.usec == 0 && + !tsdPtr->timerPending) { + tsdPtr->timerPending = 1; timerEvPtr = (Tcl_Event *) ckalloc(sizeof(Tcl_Event)); timerEvPtr->proc = TimerHandlerEventProc; Tcl_QueueEvent(timerEvPtr, TCL_QUEUE_TAIL); } } @@ -446,10 +457,11 @@ * 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. @@ -484,16 +496,16 @@ * handler appearing after earlier ones with the same expiration * time, we don't have to worry about newer generation timers * appearing before later ones. */ - timerPending = 0; - currentTimerId = lastTimerId; + tsdPtr->timerPending = 0; + currentTimerId = tsdPtr->lastTimerId; TclpGetTime(&time); while (1) { - nextPtrPtr = &firstTimerHandlerPtr; - timerHandlerPtr = firstTimerHandlerPtr; + nextPtrPtr = &tsdPtr->firstTimerHandlerPtr; + timerHandlerPtr = tsdPtr->firstTimerHandlerPtr; if (timerHandlerPtr == NULL) { break; } if ((timerHandlerPtr->time.sec > time.sec) @@ -547,26 +559,23 @@ Tcl_IdleProc *proc; /* Procedure to invoke. */ ClientData clientData; /* Arbitrary value to pass to proc. */ { register IdleHandler *idlePtr; Tcl_Time blockTime; - - if (!initialized) { - InitTimer(); - } + ThreadSpecificData *tsdPtr = InitTimer(); idlePtr = (IdleHandler *) ckalloc(sizeof(IdleHandler)); idlePtr->proc = proc; idlePtr->clientData = clientData; - idlePtr->generation = idleGeneration; + idlePtr->generation = tsdPtr->idleGeneration; idlePtr->nextPtr = NULL; - if (lastIdlePtr == NULL) { - idleList = idlePtr; + if (tsdPtr->lastIdlePtr == NULL) { + tsdPtr->idleList = idlePtr; } else { - lastIdlePtr->nextPtr = idlePtr; + tsdPtr->lastIdlePtr->nextPtr = idlePtr; } - lastIdlePtr = idlePtr; + tsdPtr->lastIdlePtr = idlePtr; blockTime.sec = 0; blockTime.usec = 0; Tcl_SetMaxBlockTime(&blockTime); } @@ -594,25 +603,26 @@ Tcl_IdleProc *proc; /* Procedure 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 = idleList; idlePtr != NULL; + for (prevPtr = NULL, idlePtr = tsdPtr->idleList; idlePtr != NULL; prevPtr = idlePtr, idlePtr = idlePtr->nextPtr) { while ((idlePtr->proc == proc) && (idlePtr->clientData == clientData)) { nextPtr = idlePtr->nextPtr; ckfree((char *) idlePtr); idlePtr = nextPtr; if (prevPtr == NULL) { - idleList = idlePtr; + tsdPtr->idleList = idlePtr; } else { prevPtr->nextPtr = idlePtr; } if (idlePtr == NULL) { - lastIdlePtr = prevPtr; + tsdPtr->lastIdlePtr = prevPtr; return; } } } } @@ -641,17 +651,18 @@ TclServiceIdle() { IdleHandler *idlePtr; int oldGeneration; Tcl_Time blockTime; + ThreadSpecificData *tsdPtr = InitTimer(); - if (idleList == NULL) { + if (tsdPtr->idleList == NULL) { return 0; } - oldGeneration = idleGeneration; - idleGeneration++; + oldGeneration = tsdPtr->idleGeneration; + tsdPtr->idleGeneration++; /* * The code below is trickier than it may look, for the following * reasons: * @@ -668,22 +679,22 @@ * 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 = idleList; + for (idlePtr = tsdPtr->idleList; ((idlePtr != NULL) && ((oldGeneration - idlePtr->generation) >= 0)); - idlePtr = idleList) { - idleList = idlePtr->nextPtr; - if (idleList == NULL) { - lastIdlePtr = NULL; + idlePtr = tsdPtr->idleList) { + tsdPtr->idleList = idlePtr->nextPtr; + if (tsdPtr->idleList == NULL) { + tsdPtr->lastIdlePtr = NULL; } (*idlePtr->proc)(idlePtr->clientData); ckfree((char *) idlePtr); } - if (idleList) { + if (tsdPtr->idleList) { blockTime.sec = 0; blockTime.usec = 0; Tcl_SetMaxBlockTime(&blockTime); } return 1; @@ -714,32 +725,22 @@ * hasn't been created yet.*/ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - /* - * 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. - */ - - static int nextId = 1; int ms; AfterInfo *afterPtr; AfterAssocData *assocPtr = (AfterAssocData *) clientData; Tcl_CmdInfo cmdInfo; int length; - char *arg; - int index, result; - static char *subCmds[] = { - "cancel", "idle", "info", - (char *) NULL}; - + char *argString; + int index; + char buf[16 + TCL_INTEGER_SPACE]; + static char *afterSubCmds[] = {"cancel", "idle", "info", (char *) NULL}; + enum afterSubCmds {AFTER_CANCEL, AFTER_IDLE, AFTER_INFO}; + ThreadSpecificData *tsdPtr = InitTimer(); + if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; } @@ -767,16 +768,21 @@ } /* * First lets see if the command was passed a number as the first argument. */ - - arg = Tcl_GetStringFromObj(objv[1], &length); - if (isdigit(UCHAR(arg[0]))) { + + if (objv[1]->typePtr == &tclIntType) { + ms = (int) objv[1]->internalRep.longValue; + goto processInteger; + } + argString = Tcl_GetStringFromObj(objv[1], &length); + if (isdigit(UCHAR(argString[0]))) { /* INTL: digit */ if (Tcl_GetIntFromObj(interp, objv[1], &ms) != TCL_OK) { return TCL_ERROR; } +processInteger: if (ms < 0) { ms = 0; } if (objc == 2) { Tcl_Sleep(ms); @@ -783,134 +789,143 @@ return TCL_OK; } afterPtr = (AfterInfo *) ckalloc((unsigned) (sizeof(AfterInfo))); afterPtr->assocPtr = assocPtr; if (objc == 3) { - arg = Tcl_GetStringFromObj(objv[2], &length); - afterPtr->command = (char *) ckalloc((unsigned) (length + 1)); - strcpy(afterPtr->command, arg); + afterPtr->commandPtr = objv[2]; } else { - Tcl_Obj *objPtr = Tcl_ConcatObj(objc-2, objv+2); - arg = Tcl_GetStringFromObj(objPtr, &length); - afterPtr->command = (char *) ckalloc((unsigned) (length + 1)); - strcpy(afterPtr->command, arg); - Tcl_DecrRefCount(objPtr); - } - afterPtr->id = nextId; - nextId += 1; + 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; afterPtr->token = Tcl_CreateTimerHandler(ms, AfterProc, (ClientData) afterPtr); afterPtr->nextPtr = assocPtr->firstAfterPtr; assocPtr->firstAfterPtr = afterPtr; - sprintf(interp->result, "after#%d", afterPtr->id); + sprintf(buf, "after#%d", afterPtr->id); + Tcl_AppendResult(interp, buf, (char *) NULL); return TCL_OK; } /* * If it's not a number it must be a subcommand. */ - result = Tcl_GetIndexFromObj(NULL, objv[1], subCmds, "option", - 0, (int *) &index); - if (result != TCL_OK) { - Tcl_AppendResult(interp, "bad argument \"", arg, + + if (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "argument", + 0, &index) != TCL_OK) { + Tcl_AppendResult(interp, "bad argument \"", argString, "\": must be cancel, idle, info, or a number", (char *) NULL); return TCL_ERROR; } - - switch (index) { - case 0: /* cancel */ - { - char *arg; - Tcl_Obj *objPtr = NULL; - - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "id|command"); - return TCL_ERROR; - } - if (objc == 3) { - arg = Tcl_GetStringFromObj(objv[2], &length); - } else { - objPtr = Tcl_ConcatObj(objc-2, objv+2);; - arg = Tcl_GetStringFromObj(objPtr, &length); - } - for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL; - afterPtr = afterPtr->nextPtr) { - if (strcmp(afterPtr->command, arg) == 0) { - break; - } - } - if (afterPtr == NULL) { - afterPtr = GetAfterEvent(assocPtr, arg); - } - if (objPtr != NULL) { - Tcl_DecrRefCount(objPtr); - } - if (afterPtr != NULL) { - if (afterPtr->token != NULL) { - Tcl_DeleteTimerHandler(afterPtr->token); - } else { - Tcl_CancelIdleCall(AfterProc, (ClientData) afterPtr); - } - FreeAfterPtr(afterPtr); - } - break; - } - case 1: /* idle */ + switch ((enum afterSubCmds) index) { + case AFTER_CANCEL: { + Tcl_Obj *commandPtr; + 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((void*) command, (void*) tempCommand, + (unsigned) length) == 0)) { + 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, (ClientData) afterPtr); + } + FreeAfterPtr(afterPtr); + } + break; + } + case AFTER_IDLE: if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "script script ..."); return TCL_ERROR; } afterPtr = (AfterInfo *) ckalloc((unsigned) (sizeof(AfterInfo))); afterPtr->assocPtr = assocPtr; if (objc == 3) { - arg = Tcl_GetStringFromObj(objv[2], &length); - afterPtr->command = (char *) ckalloc((unsigned) length + 1); - strcpy(afterPtr->command, arg); + afterPtr->commandPtr = objv[2]; } else { - Tcl_Obj *objPtr = Tcl_ConcatObj(objc-2, objv+2);; - arg = Tcl_GetStringFromObj(objPtr, &length); - afterPtr->command = (char *) ckalloc((unsigned) (length + 1)); - strcpy(afterPtr->command, arg); - Tcl_DecrRefCount(objPtr); - } - afterPtr->id = nextId; - nextId += 1; + 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, (ClientData) afterPtr); - sprintf(interp->result, "after#%d", afterPtr->id); + sprintf(buf, "after#%d", afterPtr->id); + Tcl_AppendResult(interp, buf, (char *) NULL); break; - case 2: /* info */ + case AFTER_INFO: { + Tcl_Obj *resultListPtr; + if (objc == 2) { - char buffer[30]; - for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL; afterPtr = afterPtr->nextPtr) { if (assocPtr->interp == interp) { - sprintf(buffer, "after#%d", afterPtr->id); - Tcl_AppendElement(interp, buffer); + sprintf(buf, "after#%d", afterPtr->id); + Tcl_AppendElement(interp, buf); } } return TCL_OK; } if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "?id?"); return TCL_ERROR; } - arg = Tcl_GetStringFromObj(objv[2], &length); - afterPtr = GetAfterEvent(assocPtr, arg); + afterPtr = GetAfterEvent(assocPtr, objv[2]); if (afterPtr == NULL) { - Tcl_AppendResult(interp, "event \"", arg, + Tcl_AppendResult(interp, "event \"", Tcl_GetString(objv[2]), "\" doesn't exist", (char *) NULL); return TCL_ERROR; } - Tcl_AppendElement(interp, afterPtr->command); - Tcl_AppendElement(interp, - (afterPtr->token == NULL) ? "idle" : "timer"); + resultListPtr = Tcl_GetObjResult(interp); + Tcl_ListObjAppendElement(interp, resultListPtr, afterPtr->commandPtr); + Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj( + (afterPtr->token == NULL) ? "idle" : "timer", -1)); + Tcl_SetObjResult(interp, resultListPtr); break; + } + default: { + panic("Tcl_AfterObjCmd: bad subcommand index to afterSubCmds"); + } } return TCL_OK; } /* @@ -921,36 +936,38 @@ * This procedure 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 "string" and is for interp, + * 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(assocPtr, string) +GetAfterEvent(assocPtr, commandPtr) AfterAssocData *assocPtr; /* Points to "after"-related information for * this interpreter. */ - char *string; /* Textual identifier for after event, such - * as "after#6". */ + Tcl_Obj *commandPtr; { + char *cmdString; /* Textual identifier for after event, such + * as "after#6". */ AfterInfo *afterPtr; int id; char *end; - if (strncmp(string, "after#", 6) != 0) { + cmdString = Tcl_GetString(commandPtr); + if (strncmp(cmdString, "after#", 6) != 0) { return NULL; } - string += 6; - id = strtoul(string, &end, 10); - if ((end == string) || (*end != 0)) { + 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) { @@ -987,10 +1004,12 @@ AfterInfo *afterPtr = (AfterInfo *) clientData; AfterAssocData *assocPtr = afterPtr->assocPtr; AfterInfo *prevPtr; int result; Tcl_Interp *interp; + char *script; + int numBytes; /* * 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. @@ -1010,11 +1029,12 @@ * Execute the callback. */ interp = assocPtr->interp; Tcl_Preserve((ClientData) interp); - result = Tcl_GlobalEval(interp, afterPtr->command); + script = Tcl_GetStringFromObj(afterPtr->commandPtr, &numBytes); + result = Tcl_EvalEx(interp, script, numBytes, TCL_EVAL_GLOBAL); if (result != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (\"after\" script)"); Tcl_BackgroundError(interp); } Tcl_Release((ClientData) interp); @@ -1021,11 +1041,11 @@ /* * Free the memory for the callback. */ - ckfree(afterPtr->command); + Tcl_DecrRefCount(afterPtr->commandPtr); ckfree((char *) afterPtr); } /* *---------------------------------------------------------------------- @@ -1060,11 +1080,11 @@ prevPtr = prevPtr->nextPtr) { /* Empty loop body. */ } prevPtr->nextPtr = afterPtr->nextPtr; } - ckfree(afterPtr->command); + Tcl_DecrRefCount(afterPtr->commandPtr); ckfree((char *) afterPtr); } /* *---------------------------------------------------------------------- @@ -1099,10 +1119,10 @@ if (afterPtr->token != NULL) { Tcl_DeleteTimerHandler(afterPtr->token); } else { Tcl_CancelIdleCall(AfterProc, (ClientData) afterPtr); } - ckfree(afterPtr->command); + Tcl_DecrRefCount(afterPtr->commandPtr); ckfree((char *) afterPtr); } ckfree((char *) assocPtr); } ADDED generic/tclUniData.c Index: generic/tclUniData.c ================================================================== --- /dev/null +++ generic/tclUniData.c @@ -0,0 +1,621 @@ +/* + * tclUtfData.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. + * + * RCS: @(#) $Id: tclUniData.c,v 1.1.2.2 1998/11/11 04:54:21 stanton Exp $ + */ + +/* + * 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 6 + +/* + * 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 char pageMap[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 28, 28, 47, 48, 49, 50, 51, 52, 53, 28, 28, 28, 54, 55, 56, 57, 58, + 59, 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, 60, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 75, + 76, 77, 78, 28, 28, 79, 80, 81, 82, 83, 83, 84, 85, 86, 85, 28, 28, + 87, 88, 89, 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, 90, 91, 92, 93, 94, 56, 95, 28, 96, 97, 98, 99, 83, 100, 83, + 101, 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, 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, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 102, 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, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 103, 28, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 56, 56, 56, 56, 106, 28, 28, 28, 107, 108, 109, 110, 56, 56, 56, + 56, 111, 112, 113, 114, 115, 116, 56, 117, 118, 119, 120, 121 +}; + +/* + * 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 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, 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, 4, 4, 4, + 4, 14, 14, 11, 14, 15, 16, 7, 8, 14, 11, 14, 7, 17, 17, 11, 15, 14, + 3, 11, 17, 15, 18, 17, 17, 17, 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, 15, 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, 19, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, + 21, 22, 23, 20, 21, 20, 21, 20, 21, 15, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 20, 21, 20, 21, 15, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 24, 20, 21, 20, 21, 20, 21, 25, 15, 26, 20, 21, + 20, 21, 27, 20, 21, 28, 28, 20, 21, 15, 29, 30, 31, 20, 21, 28, 32, + 15, 33, 34, 20, 21, 15, 15, 33, 35, 15, 36, 20, 21, 20, 21, 20, 21, + 37, 20, 21, 38, 39, 15, 20, 21, 38, 20, 21, 40, 40, 20, 21, 20, 21, + 41, 20, 21, 15, 39, 20, 21, 39, 39, 39, 39, 39, 39, 42, 43, 44, 42, + 43, 44, 42, 43, 44, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 45, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 20, 21, 15, 42, 43, 44, 20, 21, 0, 0, 0, 0, 20, 21, + 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 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, 15, 15, 15, 46, 47, 15, 48, 48, 15, 49, 15, 50, 15, 15, 15, 15, + 48, 15, 15, 51, 15, 15, 15, 15, 52, 53, 15, 15, 15, 15, 15, 53, 15, + 15, 54, 15, 15, 55, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 56, 15, 15, 15, 15, 56, 15, 57, 57, 15, 15, 15, 15, 15, 15, 58, + 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, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 11, 11, 59, 59, 59, 59, 59, 59, 59, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 59, 59, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 59, 59, 59, 59, 59, 11, 11, 11, 11, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 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, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 3, 0, 0, 0, 0, 59, 0, 0, 0, 3, 0, 0, 0, 0, 0, 11, 11, 61, + 3, 62, 62, 62, 0, 63, 0, 64, 64, 15, 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, 65, 66, 66, 66, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 67, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 68, 69, 69, 0, 70, 71, 37, 37, 37, 72, 73, 0, 0, 0, 37, 0, 37, 0, 37, + 0, 37, 0, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 74, + 75, 45, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 0, 76, 76, 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, 0, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 0, 75, 75, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 20, 21, 14, 60, 60, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 39, 20, + 21, 20, 21, 0, 0, 20, 21, 0, 0, 20, 21, 0, 0, 0, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 20, 21, 0, 0, 20, 21, 20, 21, 20, 21, 20, 21, 0, 0, + 20, 21, 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, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 0, 0, 59, 3, 3, + 3, 3, 3, 3, 0, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 15, 0, 3, 0, 0, 0, 0, 0, 0, 0, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 0, 60, 60, 60, 3, 60, 3, 60, 60, 3, 60, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 0, 0, 0, 0, 0, 39, 39, 39, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 3, 0, 0, 0, 3, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, + 0, 0, 0, 0, 59, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 60, 60, 60, + 60, 60, 60, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 0, 0, 60, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, 0, 39, 39, + 39, 39, 39, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 0, 39, 39, 39, 39, 3, 39, 60, 60, 60, 60, 60, 60, 60, 79, 79, + 60, 60, 60, 60, 60, 60, 59, 59, 60, 60, 14, 60, 60, 60, 60, 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, 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, 60, 60, 80, 0, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, 0, 60, 39, + 80, 80, 80, 60, 60, 60, 60, 60, 60, 60, 60, 80, 80, 80, 80, 60, 0, + 0, 14, 60, 60, 60, 60, 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 60, 60, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 80, 80, 0, 39, 39, 39, 39, 39, 39, + 39, 39, 0, 0, 39, 39, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, 39, 39, 39, 39, + 39, 39, 39, 0, 39, 0, 0, 0, 39, 39, 39, 39, 0, 0, 60, 0, 80, 80, 80, + 60, 60, 60, 60, 0, 0, 80, 80, 0, 0, 80, 80, 60, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 80, 0, 0, 0, 0, 39, 39, 0, 39, 39, 39, 60, 60, 0, 0, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 39, 39, 4, 4, 17, 17, 17, 17, 17, 17, 14, 0, 0, + 0, 0, 0, 0, 0, 60, 0, 0, 39, 39, 39, 39, 39, 39, 0, 0, 0, 0, 39, 39, + 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 0, 39, 39, 39, 39, 39, 39, 39, 0, 39, 39, 0, + 39, 39, 0, 39, 39, 0, 0, 60, 0, 80, 80, 80, 60, 60, 0, 0, 0, 0, 60, + 60, 0, 0, 60, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, 39, + 39, 0, 39, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 60, 60, + 39, 39, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 60, 80, 0, 39, + 39, 39, 39, 39, 39, 39, 0, 39, 0, 39, 39, 39, 0, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 0, 39, 39, 39, 39, 39, 39, 39, 0, 39, 39, 0, 39, 39, 39, 39, 39, 0, + 0, 60, 39, 80, 80, 80, 60, 60, 60, 60, 60, 0, 60, 60, 80, 0, 80, 80, + 60, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, + 0, 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, 60, 80, 80, 0, 39, 39, 39, 39, 39, 39, 39, 39, + 0, 0, 39, 39, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, 39, 39, 39, 39, 39, 39, + 39, 0, 39, 39, 0, 0, 39, 39, 39, 39, 0, 0, 60, 39, 80, 60, 80, 60, + 60, 60, 0, 0, 0, 80, 80, 0, 0, 80, 80, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 60, 80, 0, 0, 0, 0, 39, 39, 0, 39, 39, 39, 0, 0, 0, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 60, 80, 0, 39, 39, 39, 39, 39, 39, 0, 0, 0, 39, 39, 39, 0, 39, + 39, 39, 39, 0, 0, 0, 39, 39, 0, 39, 0, 39, 39, 0, 0, 0, 39, 39, 0, + 0, 0, 39, 39, 39, 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 0, 39, 39, + 39, 0, 0, 0, 0, 80, 80, 60, 80, 80, 0, 0, 0, 80, 80, 80, 0, 80, 80, + 80, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 17, 17, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 80, 0, 39, 39, 39, 39, 39, 39, 39, + 39, 0, 39, 39, 39, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 0, 39, 39, 39, 39, 39, 0, 0, 0, 0, 60, 60, 60, + 80, 80, 80, 80, 0, 60, 60, 60, 0, 60, 60, 60, 60, 0, 0, 0, 0, 0, 0, + 0, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, 0, 0, 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, 80, 80, 0, 39, 39, 39, 39, 39, 39, 39, 39, 0, 39, 39, 39, 0, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 0, 39, 39, 39, 39, 39, 0, 0, 0, 0, 80, 60, 80, 80, 80, 80, 80, 0, 60, + 80, 80, 0, 80, 80, 60, 60, 0, 0, 0, 0, 0, 0, 0, 80, 80, 0, 0, 0, 0, + 0, 0, 0, 39, 0, 39, 39, 0, 0, 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, 80, 80, 0, 39, 39, + 39, 39, 39, 39, 39, 39, 0, 39, 39, 39, 0, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, + 0, 0, 0, 80, 80, 80, 60, 60, 60, 0, 0, 80, 80, 80, 0, 80, 80, 80, 60, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, 0, 0, + 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, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, + 39, 60, 39, 39, 60, 60, 60, 60, 60, 60, 60, 0, 0, 0, 0, 4, 39, 39, + 39, 39, 39, 39, 59, 60, 60, 60, 60, 60, 60, 60, 60, 14, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 3, 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, 0, 0, 0, 0, 39, + 39, 0, 39, 0, 0, 39, 39, 0, 39, 0, 0, 39, 0, 0, 0, 0, 0, 0, 39, 39, + 39, 39, 0, 39, 39, 39, 39, 39, 39, 39, 0, 39, 39, 39, 0, 39, 0, 39, + 0, 0, 39, 39, 0, 39, 39, 3, 39, 60, 39, 39, 60, 60, 60, 60, 60, 60, + 0, 60, 60, 39, 0, 0, 39, 39, 39, 39, 39, 0, 59, 0, 60, 60, 60, 60, + 60, 60, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 39, 39, 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, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 14, 14, 14, 14, 14, 60, 60, 14, 14, 14, 14, 14, 14, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 14, 60, 14, 60, 14, 60, 5, 6, 5, 6, 5, 6, 39, 39, 39, 39, 39, 39, 39, + 39, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 0, 0, 0, 0, 0, 0, 0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 80, 60, 60, 60, 60, 60, 3, 60, 60, 14, 14, 14, 14, 0, 0, + 0, 0, 60, 60, 60, 60, 60, 60, 0, 60, 0, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0, 0, 0, 60, + 60, 60, 60, 60, 60, 60, 0, 60, 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, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 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, 0, 0, 0, 0, 3, 0, 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, 0, 0, 0, 0, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 0, 0, 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 0, 0, 0, 0, 0, 0, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 20, 21, 15, 15, 15, 15, 15, 81, 0, 0, 0, 0, 20, 21, + 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, + 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, + 21, 20, 21, 0, 0, 0, 0, 0, 0, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, + 83, 83, 83, 83, 83, 83, 82, 82, 82, 82, 82, 82, 0, 0, 83, 83, 83, 83, + 83, 83, 0, 0, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, + 83, 83, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, + 83, 82, 82, 82, 82, 82, 82, 0, 0, 83, 83, 83, 83, 83, 83, 0, 0, 15, + 82, 15, 82, 15, 82, 15, 82, 0, 83, 0, 83, 0, 83, 0, 83, 82, 82, 82, + 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 84, 84, 85, 85, + 85, 85, 86, 86, 87, 87, 88, 88, 89, 89, 0, 0, 82, 82, 82, 82, 82, 82, + 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 82, 82, 82, 82, 82, 82, 82, + 82, 83, 83, 83, 83, 83, 83, 83, 83, 82, 82, 82, 82, 82, 82, 82, 82, + 83, 83, 83, 83, 83, 83, 83, 83, 82, 82, 15, 90, 15, 0, 15, 15, 83, + 83, 91, 91, 92, 11, 37, 11, 11, 11, 15, 90, 15, 0, 15, 15, 93, 93, + 93, 93, 92, 11, 11, 11, 82, 82, 15, 15, 0, 0, 15, 15, 83, 83, 94, 94, + 0, 11, 11, 11, 82, 82, 15, 15, 15, 95, 15, 15, 83, 83, 96, 96, 97, + 11, 11, 11, 0, 0, 15, 90, 15, 0, 15, 15, 98, 98, 99, 99, 92, 11, 11, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 100, 100, 100, 100, 8, 8, 8, + 8, 8, 8, 3, 3, 16, 18, 5, 16, 16, 18, 5, 16, 3, 3, 3, 3, 3, 3, 3, 3, + 101, 102, 100, 100, 100, 100, 100, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 16, + 18, 3, 3, 3, 3, 12, 12, 3, 3, 3, 7, 5, 6, 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, 100, 100, 100, 100, 100, 100, 17, 0, 0, 0, 17, 17, 17, 17, + 17, 17, 7, 7, 7, 5, 6, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 7, 7, 7, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 79, 79, 79, + 79, 60, 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, 37, 14, 14, 14, 14, 37, 14, 14, + 15, 37, 37, 37, 15, 15, 37, 37, 37, 15, 14, 37, 14, 14, 37, 37, 37, + 37, 37, 37, 14, 14, 14, 14, 14, 14, 37, 14, 37, 14, 37, 14, 37, 37, + 37, 37, 15, 15, 37, 37, 14, 37, 15, 39, 39, 39, 39, 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, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 103, 103, 103, 103, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 105, 105, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 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, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 14, 14, 14, 14, 14, 14, 7, + 7, 7, 7, 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, 14, 14, 14, 14, + 14, 14, 14, 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, 14, 14, 14, 14, 14, 14, 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, 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, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 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, 17, 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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 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, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 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, 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, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 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, 0, 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, 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, 0, 14, 0, 14, 14, 14, 14, 0, 0, 0, 14, + 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 14, 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, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 2, 3, 3, + 3, 14, 59, 3, 105, 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, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 60, 60, 60, 60, 60, 60, 8, 59, 59, 59, 59, 59, 14, 14, 0, 0, 0, + 0, 0, 0, 0, 14, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 0, 0, 0, 0, 60, 60, 59, 59, 59, 59, 0, 0, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 3, 59, 59, 59, 0, 0, 0, 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, + 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, 14, + 14, 17, 17, 17, 17, 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, 14, 14, 14, 14, 14, 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, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 14, 14, 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, 14, 14, 14, 14, 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, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 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, 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, 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, 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, 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, 0, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 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, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 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, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 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, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 60, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 7, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 0, 39, 39, 39, 39, 39, 0, 39, 0, 39, 39, 0, 39, + 39, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 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, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, 0, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 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, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 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, 60, 60, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 8, 8, + 12, 12, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 0, 0, 0, 0, + 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, 39, 39, 39, 0, 39, + 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 0, 0, 100, 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, 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, 0, 0, 3, 5, 6, 3, 3, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 59, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 59, + 59, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, 0, 0, + 39, 39, 39, 39, 39, 39, 0, 0, 39, 39, 39, 39, 39, 39, 0, 0, 39, 39, + 39, 39, 39, 39, 0, 0, 39, 39, 39, 0, 0, 0, 4, 4, 7, 11, 14, 4, 4, 0, + 7, 7, 7, 7, 7, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, + 0, 0 +}; + +/* + * 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 = sutract delta for title/upper + * 101 = sub delta for upper, sub 1 for title + * 110 = sub delta for upper, add delta for lower + * + * Bits 8-21 Reserved for future use. + * + * Bits 22-31 Case delta: delta for case conversions. This should be the + * highest field so we can easily sign extend. + */ + +static int groups[] = { + 0, 15, 12, 25, 27, 21, 22, 26, 20, 9, 134217793, 28, 19, 134217858, + 29, 2, 23, 11, 24, -507510654, 4194369, 4194434, -834666431, 973078658, + -507510719, 1258291330, 880803905, 864026689, 859832385, 331350081, + 847249473, 851443777, 868220993, 884998209, 876609601, 893386817, + 897581121, 1, 914358337, 5, 910164033, 918552641, 8388705, 4194499, + 8388770, 331350146, 880803970, 864026754, 859832450, 847249538, + 851443842, 868221058, 876609666, 884998274, 893386882, 897581186, + 914358402, 910164098, 918552706, 4, 6, 159383617, 155189313, 268435521, + 264241217, 159383682, 155189378, 130023554, 268435586, 264241282, + 260046978, 239075458, 197132418, 226492546, 360710274, 335544450, + 335544385, 201326657, 201326722, 7, 8, 247464066, -33554302, -33554367, + -310378366, -360710014, -419430270, -536870782, -469761918, -528482174, + -37748606, -310378431, -37748671, -360710079, -419430335, -29359998, + -469761983, -29360063, -536870847, -528482239, 16, 13, 14, 67108938, + 67109002, 10, 109051997, 109052061, 18, 17 +}; + +/* + * The following constants are used to determine the category of a + * Unicode character. + */ + +#define UNICODE_CATEGORY_MASK 0X1F + +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(info) ((info) & 0x1F) +#define GetDelta(infO) (((info) > 0) ? ((info) >> 22) : (~(~((info)) >> 22))) + +/* + * This macro extracts the information about a character from the + * Unicode character tables. + */ + +#define GetUniCharInfo(ch) (groups[(int)groupMap[(int)((pageMap[(((int)(ch)) & 0xffff) >> OFFSET_BITS] << OFFSET_BITS) | ((ch) & ((1 << OFFSET_BITS)-1)))]]) + ADDED generic/tclUtf.c Index: generic/tclUtf.c ================================================================== --- /dev/null +++ generic/tclUtf.c @@ -0,0 +1,1287 @@ +/* + * 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. + * + * RCS: @(#) $Id: tclUtf.c,v 1.1.2.6 1999/04/02 23:44:58 stanton Exp $ + */ + +#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 << OTHER_LETTER)) + +#define DIGIT_BITS (1 << DECIMAL_DIGIT_NUMBER) + +#define SPACE_BITS ((1 << SPACE_SEPARATOR) | (1 << LINE_SEPARATOR) \ + | (1 << PARAGRAPH_SEPARATOR)) + +#define CONNECTOR_BITS (1 << CONNECTOR_PUNCTUATION) + +/* + * Unicode characters less than this value are represented by themselves + * in UTF-8 strings. + */ + +#define UNICODE_SELF 0x80 + +/* + * The following structures are used when mapping between Unicode (UCS-2) + * and UTF-8. + */ + +CONST unsigned char totalBytes[256] = { + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 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, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +#if TCL_UTF_MAX > 3 + 4,4,4,4,4,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 +}; + + +/* + *--------------------------------------------------------------------------- + * + * 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(ch, str) + int ch; /* The Tcl_UniChar to be stored in the + * buffer. */ + char *str; /* 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)) { + str[0] = (char) ch; + return 1; + } + if (ch <= 0x7FF) { + str[1] = (char) ((ch | 0x80) & 0xBF); + str[0] = (char) ((ch >> 6) | 0xC0); + return 2; + } + if (ch <= 0xFFFF) { + three: + str[2] = (char) ((ch | 0x80) & 0xBF); + str[1] = (char) (((ch >> 6) | 0x80) & 0xBF); + str[0] = (char) ((ch >> 12) | 0xE0); + return 3; + } + +#if TCL_UTF_MAX > 3 + if (ch <= 0x1FFFFF) { + str[3] = (char) ((ch | 0x80) & 0xBF); + str[2] = (char) (((ch >> 6) | 0x80) & 0xBF); + str[1] = (char) (((ch >> 12) | 0x80) & 0xBF); + str[0] = (char) ((ch >> 18) | 0xF0); + return 4; + } + if (ch <= 0x3FFFFFF) { + str[4] = (char) ((ch | 0x80) & 0xBF); + str[3] = (char) (((ch >> 6) | 0x80) & 0xBF); + str[2] = (char) (((ch >> 12) | 0x80) & 0xBF); + str[1] = (char) (((ch >> 18) | 0x80) & 0xBF); + str[0] = (char) ((ch >> 24) | 0xF8); + return 5; + } + if (ch <= 0x7FFFFFFF) { + str[5] = (char) ((ch | 0x80) & 0xBF); + str[4] = (char) (((ch >> 6) | 0x80) & 0xBF); + str[3] = (char) (((ch >> 12) | 0x80) & 0xBF); + str[2] = (char) (((ch >> 18) | 0x80) & 0xBF); + str[1] = (char) (((ch >> 24) | 0x80) & 0xBF); + str[0] = (char) ((ch >> 30) | 0xFC); + return 6; + } +#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(wString, numChars, dsPtr) + CONST Tcl_UniChar *wString; /* Unicode string to convert to UTF-8. */ + int numChars; /* 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 + numChars + 1) * TCL_UTF_MAX); + string = Tcl_DStringValue(dsPtr) + oldLength; + + p = string; + wEnd = wString + numChars; + for (w = wString; 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(str, chPtr) + register CONST char *str; /* 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 *) str); + 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 ((str[1] & 0xC0) == 0x80) { + /* + * Two-byte-character lead-byte followed by a trail-byte. + */ + + *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (str[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 (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) { + /* + * Three-byte-character lead byte followed by two trail bytes. + */ + + *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) + | ((str[1] & 0x3F) << 6) | (str[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 + else { + int ch, total, trail; + + total = totalBytes[byte]; + trail = total - 1; + if (trail > 0) { + ch = byte & (0x3F >> trail); + do { + str++; + if ((*str & 0xC0) != 0x80) { + *chPtr = byte; + return 1; + } + ch <<= 6; + ch |= (*str & 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(string, length, dsPtr) + CONST char *string; /* 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(string); + } + + /* + * Unicode string length in Tcl_UniChars will be <= UTF-8 string length + * in bytes. + */ + + oldLength = Tcl_DStringLength(dsPtr); + Tcl_DStringSetLength(dsPtr, + (int) ((oldLength + length + 1) * sizeof(Tcl_UniChar))); + wString = (Tcl_UniChar *) (Tcl_DStringValue(dsPtr) + oldLength); + + w = wString; + end = string + length; + for (p = string; p < end; ) { + p += Tcl_UtfToUniChar(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(str, len) + CONST char *str; /* String to check if first few bytes + * contain a complete UTF-8 character. */ + int len; /* Length of above string in bytes. */ +{ + int ch; + + ch = *((unsigned char *) str); + return len >= 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(str, len) + register CONST char *str; /* The UTF-8 string to measure. */ + int len; /* The length of the string in bytes, or -1 + * for strlen(string). */ +{ + Tcl_UniChar ch; + register Tcl_UniChar *chPtr = &ch; + register int n; + int i; + + /* + * The separate implementations are faster. + */ + + i = 0; + if (len < 0) { + while (1) { + str += Tcl_UtfToUniChar(str, chPtr); + if (ch == '\0') { + break; + } + i++; + } + } else { + while (len > 0) { + n = Tcl_UtfToUniChar(str, chPtr); + len -= n; + str += 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. + * + *--------------------------------------------------------------------------- + */ +char * +Tcl_UtfFindFirst(string, ch) + CONST char *string; /* The UTF-8 string to be searched. */ + int ch; /* The Tcl_UniChar to search for. */ +{ + int len; + Tcl_UniChar find; + + while (1) { + len = Tcl_UtfToUniChar(string, &find); + if (find == ch) { + return (char *) string; + } + if (*string == '\0') { + return NULL; + } + string += 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. + * + *--------------------------------------------------------------------------- + */ + +char * +Tcl_UtfFindLast(string, ch) + CONST char *string; /* 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 = Tcl_UtfToUniChar(string, &find); + if (find == ch) { + last = string; + } + if (*string == '\0') { + break; + } + string += len; + } + return (char *) 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. + * + *--------------------------------------------------------------------------- + */ + +char * +Tcl_UtfNext(str) + CONST char *str; /* The current location in the string. */ +{ + Tcl_UniChar ch; + + return (char *) str + Tcl_UtfToUniChar(str, &ch); +} + +/* + *--------------------------------------------------------------------------- + * + * Tcl_UtfPrev -- + * + * Given a pointer to some current location in a UTF-8 string, + * move backwards one 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. + * + *--------------------------------------------------------------------------- + */ + +char * +Tcl_UtfPrev(str, start) + CONST char *str; /* 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; + + str--; + look = str; + for (i = 0; i < TCL_UTF_MAX; i++) { + if (look < start) { + if (str < start) { + str = start; + } + break; + } + byte = *((unsigned char *) look); + if (byte < 0x80) { + break; + } + if (byte >= 0xC0) { + if (totalBytes[byte] != i + 1) { + break; + } + return (char *) look; + } + look--; + } + return (char *) str; +} + +/* + *--------------------------------------------------------------------------- + * + * 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(src, index) + register CONST char *src; /* The UTF-8 string to dereference. */ + register int index; /* The position of the desired character. */ +{ + Tcl_UniChar ch; + + while (index >= 0) { + index--; + src += Tcl_UtfToUniChar(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. + * + *--------------------------------------------------------------------------- + */ + +char * +Tcl_UtfAtIndex(src, index) + 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 += Tcl_UtfToUniChar(src, &ch); + } + return (char *) 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(src, readPtr, dst) + 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. */ +{ + register CONST char *p = src+1; + int result, count, n; + char buf[TCL_UTF_MAX]; + + if (dst == NULL) { + dst = buf; + } + + 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': + if (isxdigit(UCHAR(p[1]))) { /* INTL: digit */ + char *end; + + result = (unsigned char) strtoul(p+1, &end, 16); + count = end - src; + } else { + count = 2; + result = 'x'; + } + break; + case 'u': + result = 0; + for (count = 0; count < 4; count++) { + p++; + if (!isxdigit(UCHAR(*p))) { /* INTL: digit */ + break; + } + n = *p - '0'; + if (n > 9) { + n = n + '0' + 10 - 'A'; + } + if (n > 16) { + n = n + 'A' - 'a'; + } + result = (result << 4) + n; + } + if (count == 0) { + result = 'u'; + } + count += 2; + break; + + case '\n': + do { + p++; + } while ((*p == ' ') || (*p == '\t')); + result = ' '; + count = p - src; + break; + case 0: + result = '\\'; + count = 1; + break; + default: + if (isdigit(UCHAR(*p))) { /* INTL: digit */ + result = (unsigned char)(*p - '0'); + p++; + if (!isdigit(UCHAR(*p))) { /* INTL: digit */ + break; + } + count = 3; + result = (unsigned char)((result << 3) + (*p - '0')); + p++; + if (!isdigit(UCHAR(*p))) { /* INTL: digit */ + break; + } + count = 4; + result = (unsigned char)((result << 3) + (*p - '0')); + break; + } + result = *p; + count = 2; + break; + } + + if (readPtr != NULL) { + *readPtr = count; + } + return Tcl_UniCharToUtf(result, dst); +} + +/* + *---------------------------------------------------------------------- + * + * 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(str) + char *str; /* String to convert in place. */ +{ + Tcl_UniChar ch; + char *src, *dst; + + /* + * Iterate over the string until we hit the terminating null. + */ + + src = dst = str; + while (*src) { + src += Tcl_UtfToUniChar(src, &ch); + dst += Tcl_UniCharToUtf(Tcl_UniCharToUpper(ch), dst); + } + *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(str) + char *str; /* String to convert in place. */ +{ + Tcl_UniChar ch; + char *src, *dst; + + /* + * Iterate over the string until we hit the terminating null. + */ + + src = dst = str; + while (*src) { + src += Tcl_UtfToUniChar(src, &ch); + dst += Tcl_UniCharToUtf(Tcl_UniCharToLower(ch), dst); + } + *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(str) + char *str; /* String to convert in place. */ +{ + Tcl_UniChar ch; + char *src, *dst; + + /* + * Capitalize the first character and then lowercase the rest of the + * characters until we get to a null. + */ + + src = dst = str; + + if (*src) { + src += Tcl_UtfToUniChar(src, &ch); + dst += Tcl_UniCharToUtf(Tcl_UniCharToTitle(ch), dst); + } + while (*src) { + src += Tcl_UtfToUniChar(src, &ch); + dst += Tcl_UniCharToUtf(Tcl_UniCharToLower(ch), dst); + } + *dst = '\0'; + return (dst - str); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_UniCharToUpper -- + * + * Compute the uppercase equivalent of the given Unicode character. + * + * Results: + * Returns the uppercase Unicode character. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tcl_UniChar +Tcl_UniCharToUpper(ch) + int ch; /* Unicode character to convert. */ +{ + int info = GetUniCharInfo(ch); + + if (GetCaseType(info) & 0x04) { + return (Tcl_UniChar) (ch - GetDelta(info)); + } else { + return 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(ch) + int ch; /* Unicode character to convert. */ +{ + int info = GetUniCharInfo(ch); + + if (GetCaseType(info) & 0x02) { + return (Tcl_UniChar) (ch + GetDelta(info)); + } else { + return 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(ch) + 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. + */ + + return (Tcl_UniChar) (ch + ((mode & 0x4) ? -1 : 1)); + } else if (mode == 0x4) { + return (Tcl_UniChar) (ch - GetDelta(info)); + } else { + return 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(str) + Tcl_UniChar *str; /* Unicode string to find length of. */ +{ + int len = 0; + + while (*str != '\0') { + len++; + str++; + } + return len; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_UniCharNcmp -- + * + * Compare at most n unichars of string cs to string ct. Both cs + * and ct are assumed to be at least n unichars long. + * + * Results: + * Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_UniCharNcmp(cs, ct, n) + CONST Tcl_UniChar *cs; /* Unicode string to compare to ct. */ + CONST Tcl_UniChar *ct; /* Unicode string cs is compared to. */ + size_t n; /* Number of unichars to compare. */ +{ + for ( ; n != 0; n--, cs++, ct++) { + if (*cs != *ct) { + return *cs - *ct; + } + if (*cs == '\0') { + break; + } + } + 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(ch) + int ch; /* Unicode character to test. */ +{ + register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK); + + return (((ALPHA_BITS | DIGIT_BITS) >> category) & 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(ch) + int ch; /* Unicode character to test. */ +{ + register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK); + return ((ALPHA_BITS >> category) & 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(ch) + int ch; /* Unicode character to test. */ +{ + return ((GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK) + == DECIMAL_DIGIT_NUMBER); +} + +/* + *---------------------------------------------------------------------- + * + * 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(ch) + int ch; /* Unicode character to test. */ +{ + return ((GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK) == LOWERCASE_LETTER); +} + +/* + *---------------------------------------------------------------------- + * + * 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(ch) + int ch; /* Unicode character to test. */ +{ + register int category; + + /* + * If the character is within the first 127 characters, just use the + * standard C function, otherwise consult the Unicode table. + */ + + if (ch < 0x80) { + return isspace(UCHAR(ch)); /* INTL: ISO space */ + } else { + category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK); + return ((SPACE_BITS >> category) & 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(ch) + int ch; /* Unicode character to test. */ +{ + return ((GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK) == 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(ch) + int ch; /* Unicode character to test. */ +{ + register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK); + + return (((ALPHA_BITS | DIGIT_BITS | CONNECTOR_BITS) >> category) & 1); +} Index: generic/tclUtil.c ================================================================== --- generic/tclUtil.c +++ generic/tclUtil.c @@ -3,21 +3,31 @@ * * This file contains utility procedures that are used by many Tcl * commands. * * Copyright (c) 1987-1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclUtil.c 1.161 97/08/12 17:07:18 + * RCS: @(#) $Id: tclUtil.c,v 1.1.2.10 1999/04/06 04:27:02 rjohnson Exp $ */ #include "tclInt.h" #include "tclPort.h" +/* + * The following variable holds the full path name of the binary + * from which this application was executed, or NULL if it isn't + * know. The value of the variable is set by the procedure + * Tcl_FindExecutable. The storage space is dynamically allocated. + */ + +char *tclExecutableName = NULL; +char *tclNativeExecutableName = NULL; + /* * The following values are used in the flags returned by Tcl_ScanElement * and used by Tcl_ConvertElement. The value TCL_DONT_USE_BRACES is also * defined in tcl.h; make sure its value doesn't overlap with any of the * values below. @@ -40,28 +50,20 @@ /* * The following values determine the precision used when converting * floating-point values to strings. This information is linked to all * of the tcl_precision variables in all interpreters via the procedure * TclPrecTraceProc. - * - * NOTE: these variables are not thread-safe. */ static char precisionString[10] = "12"; /* The string value of all the tcl_precision * variables. */ static char precisionFormat[10] = "%.12g"; /* The format string actually used in calls * to sprintf. */ - - -/* - * Function prototypes for local procedures in this file: - */ - -static void SetupAppendBuffer _ANSI_ARGS_((Interp *iPtr, - int newSpace)); +TCL_DECLARE_MUTEX(precisionMutex) + /* *---------------------------------------------------------------------- * * TclFindElement -- @@ -71,11 +73,11 @@ * * 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; - * interp->result contains a more detailed error message. + * 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 @@ -99,45 +101,42 @@ TclFindElement(interp, list, listLength, elementPtr, nextPtr, sizePtr, bracePtr) Tcl_Interp *interp; /* Interpreter to use for error reporting. * If NULL, then no error message is left * after errors. */ - char *list; /* Points to the first byte of a string + 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. */ - char **elementPtr; /* Where to put address of first significant + CONST char **elementPtr; /* Where to put address of first significant * character in first element of list. */ - char **nextPtr; /* Fill in with location of character just + 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 *bracePtr; /* If non-zero, fill in with non-zero/zero * to indicate that arg was/wasn't * in braces. */ { - char *p = list; - char *elemStart; /* Points to first byte of first element. */ - char *limit; /* Points just after list's last byte. */ + CONST char *p = list; + CONST char *elemStart; /* Points to first byte of first element. */ + CONST char *limit; /* Points just after list's last byte. */ int openBraces = 0; /* Brace nesting level during parse. */ int inQuotes = 0; - int size = 0; /* Init. avoids compiler warning. */ + int size = 0; /* lint. */ int numChars; - char *p2; + CONST char *p2; /* * Skim off leading white space and check for an opening brace or * quote. We treat embedded NULLs in the list as bytes belonging to - * a list element. Note: use of "isascii" below and elsewhere in this - * procedure is a temporary hack (7/27/90) because Mx uses characters - * with the high-order bit set for some things. This should probably - * be changed back eventually, or all of Tcl should call isascii. + * a list element. */ limit = (list + listLength); - while ((p < limit) && (isspace(UCHAR(*p)))) { + while ((p < limit) && (isspace(UCHAR(*p)))) { /* INTL: ISO space. */ p++; } if (p == limit) { /* no element found */ elemStart = limit; goto done; @@ -182,11 +181,12 @@ if (openBraces > 1) { openBraces--; } else if (openBraces == 1) { size = (p - elemStart); p++; - if ((p >= limit) || isspace(UCHAR(*p))) { + if ((p >= limit) + || isspace(UCHAR(*p))) { /* INTL: ISO space. */ goto done; } /* * Garbage after the closing brace; return an error. @@ -194,11 +194,12 @@ if (interp != NULL) { char buf[100]; p2 = p; - while ((p2 < limit) && (!isspace(UCHAR(*p2))) + while ((p2 < limit) + && (!isspace(UCHAR(*p2))) /* INTL: ISO space. */ && (p2 < p+20)) { p2++; } sprintf(buf, "list element in braces followed by \"%.*s\" instead of space", @@ -213,11 +214,11 @@ * Backslash: skip over everything up to the end of the * backslash sequence. */ case '\\': { - (void) Tcl_Backslash(p, &numChars); + Tcl_UtfBackslash(p, &numChars, NULL); p += (numChars - 1); break; } /* @@ -243,11 +244,12 @@ case '"': if (inQuotes) { size = (p - elemStart); p++; - if ((p >= limit) || isspace(UCHAR(*p))) { + if ((p >= limit) + || isspace(UCHAR(*p))) { /* INTL: ISO space */ goto done; } /* * Garbage after the closing quote; return an error. @@ -255,11 +257,12 @@ if (interp != NULL) { char buf[100]; p2 = p; - while ((p2 < limit) && (!isspace(UCHAR(*p2))) + while ((p2 < limit) + && (!isspace(UCHAR(*p2))) /* INTL: ISO space */ && (p2 < p+20)) { p2++; } sprintf(buf, "list element in quotes followed by \"%.*s\" %s", @@ -294,11 +297,11 @@ } size = (p - elemStart); } done: - while ((p < limit) && (isspace(UCHAR(*p)))) { + while ((p < limit) && (isspace(UCHAR(*p)))) { /* INTL: ISO space. */ p++; } *elementPtr = elemStart; *nextPtr = p; if (sizePtr != 0) { @@ -328,24 +331,25 @@ */ int TclCopyAndCollapse(count, src, dst) int count; /* Number of characters to copy from src. */ - char *src; /* Copy from here... */ + CONST char *src; /* Copy from here... */ char *dst; /* ... to here. */ { - char c; + register char c; int numRead; int newCount = 0; + int backslashCount; for (c = *src; count > 0; src++, c = *src, count--) { if (c == '\\') { - *dst = Tcl_Backslash(src, &numRead); - dst++; + backslashCount = Tcl_UtfBackslash(src, &numRead, dst); + dst += backslashCount; + newCount += backslashCount; src += numRead-1; count -= numRead-1; - newCount++; } else { *dst = c; dst++; newCount++; } @@ -363,11 +367,11 @@ * * 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; interp->result will contain a more detailed + * 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 @@ -386,40 +390,41 @@ int Tcl_SplitList(interp, list, argcPtr, argvPtr) Tcl_Interp *interp; /* Interpreter to use for error reporting. * If NULL, no error message is left. */ - char *list; /* Pointer to string with list structure. */ + 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. */ char ***argvPtr; /* Pointer to place to store pointer to * array of pointers to list elements. */ { char **argv; + CONST char *l; char *p; int length, size, i, result, elSize, brace; - char *element; + CONST char *element; /* * Figure out how much space to allocate. There must be enough * space for both the array of pointers and also for a copy of * the list. To estimate the number of pointers needed, count * the number of space characters in the list. */ - for (size = 1, p = list; *p != 0; p++) { - if (isspace(UCHAR(*p))) { + for (size = 1, l = list; *l != 0; l++) { + if (isspace(UCHAR(*l))) { /* INTL: ISO space. */ size++; } } size++; /* Leave space for final NULL pointer. */ argv = (char **) ckalloc((unsigned) - ((size * sizeof(char *)) + (p - list) + 1)); + ((size * sizeof(char *)) + (l - list) + 1)); length = strlen(list); for (i = 0, p = ((char *) argv) + size*sizeof(char *); *list != 0; i++) { - char *prevList = list; + CONST char *prevList = list; result = TclFindElement(interp, list, length, &element, &list, &elSize, &brace); length -= (list - prevList); if (result != TCL_OK) { @@ -478,13 +483,13 @@ *---------------------------------------------------------------------- */ int Tcl_ScanElement(string, flagPtr) - CONST char *string; /* String to convert to Tcl list element. */ - int *flagPtr; /* Where to store information to guide - * Tcl_ConvertCountedElement. */ + register CONST char *string; /* String to convert to list element. */ + register int *flagPtr; /* Where to store information to guide + * Tcl_ConvertCountedElement. */ { return Tcl_ScanCountedElement(string, -1, flagPtr); } /* @@ -518,11 +523,11 @@ int length; /* Number of bytes in string, or -1. */ int *flagPtr; /* Where to store information to guide * Tcl_ConvertElement. */ { int flags, nestingLevel; - CONST char *p, *lastChar; + register CONST char *p, *lastChar; /* * This procedure and Tcl_ConvertElement together do two things: * * 1. They produce a proper list, one that will yield back the @@ -602,11 +607,11 @@ if ((p+1 == lastChar) || (p[1] == '\n')) { flags = TCL_DONT_USE_BRACES | BRACES_UNMATCHED; } else { int size; - (void) Tcl_Backslash(p, &size); + Tcl_UtfBackslash(p, &size, NULL); p += size-1; flags |= USE_BRACES; } break; } @@ -646,13 +651,13 @@ *---------------------------------------------------------------------- */ int Tcl_ConvertElement(src, dst, flags) - CONST char *src; /* Source information for list element. */ - char *dst; /* Place to put list-ified element. */ - int flags; /* Flags produced by Tcl_ScanElement. */ + 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); } /* @@ -678,17 +683,17 @@ *---------------------------------------------------------------------- */ int Tcl_ConvertCountedElement(src, length, dst, flags) - CONST char *src; /* Source information for list element. */ + 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. */ { - char *p = dst; - CONST char *lastChar; + register char *p = dst; + register CONST char *lastChar; /* * See the comment block at the beginning of the Tcl_ScanElement * code for details of how this works. */ @@ -865,10 +870,44 @@ } /* *---------------------------------------------------------------------- * + * 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(src, readPtr) + 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); + Tcl_UtfToUniChar(buf, &ch); + return (char) ch; +} + +/* + *---------------------------------------------------------------------- + * * Tcl_Concat -- * * Concatenate a set of strings into a single large string. * * Results: @@ -909,17 +948,18 @@ * to generate a neater result, and ignore any empty * elements. */ element = argv[i]; - while (isspace(UCHAR(*element))) { + while (isspace(UCHAR(*element))) { /* INTL: ISO space. */ element++; } for (length = strlen(element); - (length > 0) && (isspace(UCHAR(element[length-1]))) + (length > 0) + && (isspace(UCHAR(element[length-1]))) /* INTL: ISO space. */ && ((length < 2) || (element[length-2] != '\\')); - length--) { + length--) { /* Null loop body. */ } if (length == 0) { continue; } @@ -966,11 +1006,11 @@ Tcl_Obj *objPtr; allocSize = 0; for (i = 0; i < objc; i++) { objPtr = objv[i]; - element = TclGetStringFromObj(objPtr, &length); + element = Tcl_GetStringFromObj(objPtr, &length); if ((element != NULL) && (length > 0)) { allocSize += (length + 1); } } if (allocSize == 0) { @@ -996,12 +1036,13 @@ *concatStr = '\0'; } else { p = concatStr; for (i = 0; i < objc; i++) { objPtr = objv[i]; - element = TclGetStringFromObj(objPtr, &elemLength); - while ((elemLength > 0) && (isspace(UCHAR(*element)))) { + element = Tcl_GetStringFromObj(objPtr, &elemLength); + while ((elemLength > 0) + && (isspace(UCHAR(*element)))) { /* INTL: ISO space. */ element++; elemLength--; } /* @@ -1009,11 +1050,11 @@ * a space character if it is preceded by a backslash: in * this case it could be significant. */ while ((elemLength > 0) - && isspace(UCHAR(element[elemLength-1])) + && isspace(UCHAR(element[elemLength-1])) /* INTL: ISO space. */ && ((elemLength < 2) || (element[elemLength-2] != '\\'))) { elemLength--; } if (elemLength == 0) { continue; /* nothing left of this element */ @@ -1057,963 +1098,139 @@ *---------------------------------------------------------------------- */ int Tcl_StringMatch(string, pattern) - char *string; /* String. */ - char *pattern; /* Pattern, which may contain special + CONST char *string; /* String. */ + CONST char *pattern; /* Pattern, which may contain special * characters. */ { - char c2; - + int p, s; + CONST char *pstart = pattern; + 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. + p = *pattern; + s = *string; + + /* + * 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 == 0) { - if (*string == 0) { + if (p == '\0') { + if (s == '\0') { return 1; } else { return 0; } } - if ((*string == 0) && (*pattern != '*')) { + if ((s == '\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 (*pattern == '*') { - pattern += 1; - if (*pattern == 0) { + if (p == '*') { + pattern++; + if (*pattern == '\0') { return 1; } while (1) { if (Tcl_StringMatch(string, pattern)) { return 1; } - if (*string == 0) { + if (*string == '\0') { return 0; } - string += 1; + string++; } } - + /* Check for a "?" as the next pattern character. It matches * any single character. */ - if (*pattern == '?') { - goto thisCharOK; + if (p == '?') { + Tcl_UniChar ch; + + pattern++; + string += Tcl_UtfToUniChar(string, &ch); + 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 (*pattern == '[') { - pattern += 1; - while (1) { - if ((*pattern == ']') || (*pattern == 0)) { - return 0; - } - if (*pattern == *string) { - break; - } - if (pattern[1] == '-') { - c2 = pattern[2]; - if (c2 == 0) { - return 0; - } - if ((*pattern <= *string) && (c2 >= *string)) { - break; - } - if ((*pattern >= *string) && (c2 <= *string)) { - break; - } - pattern += 2; - } - pattern += 1; - } - while (*pattern != ']') { - if (*pattern == 0) { - pattern--; - break; - } - pattern += 1; - } - goto thisCharOK; - } - - /* If the next pattern character is '/', just strip off the '/' + if (p == '[') { + Tcl_UniChar ch, startChar, endChar; + + pattern++; + string += Tcl_UtfToUniChar(string, &ch); + + while (1) { + if ((*pattern == ']') || (*pattern == '\0')) { + return 0; + } + pattern += Tcl_UtfToUniChar(pattern, &startChar); + if (*pattern == '-') { + pattern++; + if (*pattern == '\0') { + return 0; + } + pattern += Tcl_UtfToUniChar(pattern, &endChar); + if (((startChar <= ch) && (ch <= endChar)) + || ((endChar <= ch) && (ch <= startChar))) { + /* + * Matches ranges of form [a-z] or [z-a]. + */ + + break; + } + } else if (startChar == ch) { + 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 (*pattern == '\\') { - pattern += 1; - if (*pattern == 0) { + if (p == '\\') { + pattern++; + p = *pattern; + if (p == '\0') { return 0; } } /* There's no special character. Just make sure that the next - * characters of each string match. + * bytes of each string match. */ - if (*pattern != *string) { + if (s != p) { return 0; } - - thisCharOK: pattern += 1; - string += 1; - } -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_SetResult -- - * - * Arrange for "string" to be the Tcl return value. - * - * Results: - * None. - * - * Side effects: - * interp->result is left pointing either to "string" (if "copy" is 0) - * or to a copy of string. Also, the object result is reset. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_SetResult(interp, string, freeProc) - Tcl_Interp *interp; /* Interpreter with which to associate the - * return value. */ - char *string; /* 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; - int length; - Tcl_FreeProc *oldFreeProc = iPtr->freeProc; - char *oldResult = iPtr->result; - - if (string == NULL) { - iPtr->resultSpace[0] = 0; - iPtr->result = iPtr->resultSpace; - iPtr->freeProc = 0; - } else if (freeProc == TCL_VOLATILE) { - length = strlen(string); - if (length > TCL_RESULT_SIZE) { - iPtr->result = (char *) ckalloc((unsigned) length+1); - iPtr->freeProc = TCL_DYNAMIC; - } else { - iPtr->result = iPtr->resultSpace; - iPtr->freeProc = 0; - } - strcpy(iPtr->result, string); - } else { - iPtr->result = string; - 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) - || (oldFreeProc == (Tcl_FreeProc *) free)) { - ckfree(oldResult); - } else { - (*oldFreeProc)(oldResult); - } - } - - /* - * Reset the object result since we just set the string result. - */ - - TclResetObjResult(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. - * - *---------------------------------------------------------------------- - */ - -char * -Tcl_GetStringResult(interp) - 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. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS. - */ - - if (*(interp->result) == 0) { - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL), - TCL_VOLATILE); - } - return interp->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(interp, objPtr) - Tcl_Interp *interp; /* Interpreter with which to associate the - * return object value. */ - Tcl_Obj *objPtr; /* Tcl object to be returned. If NULL, the - * obj result is made an empty string - * object. */ -{ - Interp *iPtr = (Interp *) interp; - 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) - || (iPtr->freeProc == (Tcl_FreeProc *) free)) { - 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 procedure 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(interp) - Tcl_Interp *interp; /* Interpreter whose result to return. */ -{ - 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) { - TclResetObjResult(iPtr); - - objResultPtr = iPtr->objResultPtr; - length = strlen(iPtr->result); - TclInitStringRep(objResultPtr, iPtr->result, length); - - if (iPtr->freeProc != NULL) { - if ((iPtr->freeProc == TCL_DYNAMIC) - || (iPtr->freeProc == (Tcl_FreeProc *) free)) { - ckfree(iPtr->result); - } else { - (*iPtr->freeProc)(iPtr->result); - } - iPtr->freeProc = 0; - } - iPtr->result = iPtr->resultSpace; - iPtr->resultSpace[0] = 0; - } - return iPtr->objResultPtr; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_AppendResult -- - * - * Append a variable number of strings onto the interpreter's string - * 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 empty, the object result is moved to the - * string result, then the object result is reset. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_AppendResult TCL_VARARGS_DEF(Tcl_Interp *,arg1) -{ - va_list argList; - Interp *iPtr; - char *string; - int newSpace; - - /* - * If the string result is empty, move the object result to the - * string result, then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS. - */ - - iPtr = (Interp *) TCL_VARARGS_START(Tcl_Interp *,arg1,argList); - if (*(iPtr->result) == 0) { - Tcl_SetResult((Tcl_Interp *) iPtr, - TclGetStringFromObj(Tcl_GetObjResult((Tcl_Interp *) iPtr), - (int *) NULL), - TCL_VOLATILE); - } - - /* - * Scan through all the arguments to see how much space is needed. - */ - - newSpace = 0; - while (1) { - string = va_arg(argList, char *); - if (string == NULL) { - break; - } - newSpace += strlen(string); - } - va_end(argList); - - /* - * If the append buffer isn't already setup and large enough to hold - * the new data, set it up. - */ - - if ((iPtr->result != iPtr->appendResult) - || (iPtr->appendResult[iPtr->appendUsed] != 0) - || ((newSpace + iPtr->appendUsed) >= iPtr->appendAvl)) { - SetupAppendBuffer(iPtr, newSpace); - } - - /* - * Now go through all the argument strings again, copying them into the - * buffer. - */ - - TCL_VARARGS_START(Tcl_Interp *,arg1,argList); - while (1) { - string = va_arg(argList, char *); - if (string == NULL) { - break; - } - strcpy(iPtr->appendResult + iPtr->appendUsed, string); - iPtr->appendUsed += strlen(string); - } - 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(interp, string) - Tcl_Interp *interp; /* Interpreter whose result is to be - * extended. */ - char *string; /* 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. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS. - */ - - if (*(iPtr->result) == 0) { - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL), - TCL_VOLATILE); - } - - /* - * See how much space is needed, and grow the append buffer if - * needed to accommodate the list element. - */ - - size = Tcl_ScanElement(string, &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++; - } - iPtr->appendUsed += Tcl_ConvertElement(string, dst, flags); -} - -/* - *---------------------------------------------------------------------- - * - * SetupAppendBuffer -- - * - * This procedure 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(iPtr, newSpace) - 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 = (char *) ckalloc((unsigned) 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 procedure 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 procedure 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(interp) - Tcl_Interp *interp; /* Interpreter for which to free result. */ -{ - Interp *iPtr = (Interp *) interp; - - if (iPtr->freeProc != NULL) { - if ((iPtr->freeProc == TCL_DYNAMIC) - || (iPtr->freeProc == (Tcl_FreeProc *) free)) { - ckfree(iPtr->result); - } else { - (*iPtr->freeProc)(iPtr->result); - } - iPtr->freeProc = 0; - } - - TclResetObjResult(iPtr); -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_ResetResult -- - * - * This procedure 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(interp) - Tcl_Interp *interp; /* Interpreter for which to clear result. */ -{ - Interp *iPtr = (Interp *) interp; - - TclResetObjResult(iPtr); - - Tcl_FreeResult(interp); - iPtr->result = iPtr->resultSpace; - iPtr->resultSpace[0] = 0; - - iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS | ERROR_CODE_SET); -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_SetErrorCode -- - * - * This procedure is called to record machine-readable information - * about an error that is about to be returned. - * - * Results: - * None. - * - * Side effects: - * The errorCode global variable is modified to hold all of the - * arguments to this procedure, in a list form with each argument - * becoming one element of the list. A flag is set internally - * to remember that errorCode has been set, so the variable doesn't - * get set automatically when the error is returned. - * - *---------------------------------------------------------------------- - */ - /* VARARGS2 */ -void -Tcl_SetErrorCode TCL_VARARGS_DEF(Tcl_Interp *,arg1) -{ - va_list argList; - char *string; - int flags; - Interp *iPtr; - - /* - * Scan through the arguments one at a time, appending them to - * $errorCode as list elements. - */ - - iPtr = (Interp *) TCL_VARARGS_START(Tcl_Interp *,arg1,argList); - flags = TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT; - while (1) { - string = va_arg(argList, char *); - if (string == NULL) { - break; - } - (void) Tcl_SetVar2((Tcl_Interp *) iPtr, "errorCode", - (char *) NULL, string, flags); - flags |= TCL_APPEND_VALUE; - } - va_end(argList); - iPtr->flags |= ERROR_CODE_SET; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_SetObjErrorCode -- - * - * This procedure 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 global variable is modified to be the new value. - * A flag is set internally to remember that errorCode has been - * set, so the variable doesn't get set automatically when the - * error is returned. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_SetObjErrorCode(interp, errorObjPtr) - Tcl_Interp *interp; - Tcl_Obj *errorObjPtr; -{ - Tcl_Obj *namePtr; - Interp *iPtr; - - namePtr = Tcl_NewStringObj("errorCode", -1); - iPtr = (Interp *) interp; - Tcl_ObjSetVar2(interp, namePtr, (Tcl_Obj *) NULL, errorObjPtr, - TCL_GLOBAL_ONLY); - iPtr->flags |= ERROR_CODE_SET; - Tcl_DecrRefCount(namePtr); -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_RegExpCompile -- - * - * Compile a regular expression into a form suitable for fast - * matching. This procedure retains a small cache of pre-compiled - * regular expressions in the interpreter, in order to avoid - * compilation costs as much as possible. - * - * 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 procedure, 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 interp->result. - * - * Side effects: - * The cache of compiled regexp's in interp will be modified to - * hold information for string, if such information isn't already - * present in the cache. - * - *---------------------------------------------------------------------- - */ - -Tcl_RegExp -Tcl_RegExpCompile(interp, string) - Tcl_Interp *interp; /* For use in error reporting. */ - char *string; /* String for which to produce - * compiled regular expression. */ -{ - Interp *iPtr = (Interp *) interp; - int i, length; - regexp *result; - - length = strlen(string); - for (i = 0; i < NUM_REGEXPS; i++) { - if ((length == iPtr->patLengths[i]) - && (strcmp(string, iPtr->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 = iPtr->patterns[i]; - result = iPtr->regexps[i]; - for (j = i-1; j >= 0; j--) { - iPtr->patterns[j+1] = iPtr->patterns[j]; - iPtr->patLengths[j+1] = iPtr->patLengths[j]; - iPtr->regexps[j+1] = iPtr->regexps[j]; - } - iPtr->patterns[0] = cachedString; - iPtr->patLengths[0] = length; - iPtr->regexps[0] = result; - } - return (Tcl_RegExp) iPtr->regexps[0]; - } - } - - /* - * No match in the cache. Compile the string and add it to the - * cache. - */ - - TclRegError((char *) NULL); - result = TclRegComp(string); - if (TclGetRegError() != NULL) { - Tcl_AppendResult(interp, - "couldn't compile regular expression pattern: ", - TclGetRegError(), (char *) NULL); - return NULL; - } - if (iPtr->patterns[NUM_REGEXPS-1] != NULL) { - ckfree(iPtr->patterns[NUM_REGEXPS-1]); - ckfree((char *) iPtr->regexps[NUM_REGEXPS-1]); - } - for (i = NUM_REGEXPS - 2; i >= 0; i--) { - iPtr->patterns[i+1] = iPtr->patterns[i]; - iPtr->patLengths[i+1] = iPtr->patLengths[i]; - iPtr->regexps[i+1] = iPtr->regexps[i]; - } - iPtr->patterns[0] = (char *) ckalloc((unsigned) (length+1)); - strcpy(iPtr->patterns[0], string); - iPtr->patLengths[0] = length; - iPtr->regexps[0] = result; - return (Tcl_RegExp) result; -} - -/* - *---------------------------------------------------------------------- - * - * 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 interp->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(interp, re, string, start) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - Tcl_RegExp re; /* Compiled regular expression; must have - * been returned by previous call to - * Tcl_RegExpCompile. */ - char *string; /* String against which to match re. */ - char *start; /* If string is part of a larger string, - * this identifies beginning of larger - * string, so that "^" won't match. */ -{ - int match; - - regexp *regexpPtr = (regexp *) re; - TclRegError((char *) NULL); - match = TclRegExec(regexpPtr, string, start); - if (TclGetRegError() != NULL) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "error while matching regular expression: ", - TclGetRegError(), (char *) NULL); - return -1; - } - return match; -} - -/* - *---------------------------------------------------------------------- - * - * 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(re, index, startPtr, endPtr) - 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. Must be no greater - * than NSUBEXP. */ - char **startPtr; /* Store address of first character in - * (sub-) range here. */ - char **endPtr; /* Store address of character just after last - * in (sub-) range here. */ -{ - regexp *regexpPtr = (regexp *) re; - - if (index >= NSUBEXP) { - *startPtr = *endPtr = NULL; - } else { - *startPtr = regexpPtr->startp[index]; - *endPtr = regexpPtr->endp[index]; - } -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_RegExpMatch -- - * - * See if a string matches a regular expression. - * - * Results: - * If an error occurs during the matching operation then -1 - * is returned and interp->result contains an error message. - * Otherwise the return value is 1 if "string" matches "pattern" - * and 0 otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -Tcl_RegExpMatch(interp, string, pattern) - Tcl_Interp *interp; /* Used for error reporting. */ - char *string; /* String. */ - char *pattern; /* Regular expression to match against - * string. */ -{ - Tcl_RegExp re; - - re = Tcl_RegExpCompile(interp, pattern); - if (re == NULL) { - return -1; - } - return Tcl_RegExpExec(interp, re, string, string); + pattern++; + string++; + } } /* *---------------------------------------------------------------------- * @@ -2037,11 +1254,11 @@ 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; + dsPtr->staticSpace[0] = '\0'; } /* *---------------------------------------------------------------------- * @@ -2068,11 +1285,11 @@ int length; /* Number of characters from string to * append. If < 0, then append all of string, * up to null at end. */ { int newSize; - char *newString, *dst; + char *dst; CONST char *end; if (length < 0) { length = strlen(string); } @@ -2083,18 +1300,22 @@ * 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; - newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl); - memcpy((VOID *) newString, (VOID *) dsPtr->string, - (size_t) dsPtr->length); - if (dsPtr->string != dsPtr->staticSpace) { - ckfree(dsPtr->string); - } - dsPtr->string = newString; + dsPtr->spaceAvl = newSize * 2; + if (dsPtr->string == dsPtr->staticSpace) { + char *newString; + + newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl); + memcpy((VOID *) newString, (VOID *) dsPtr->string, + (size_t) dsPtr->length); + dsPtr->string = newString; + } else { + dsPtr->string = (char *) ckrealloc((VOID *) dsPtr->string, + (size_t) dsPtr->spaceAvl); + } } /* * Copy the new string into the buffer at the end of the old * one. @@ -2132,11 +1353,11 @@ Tcl_DString *dsPtr; /* Structure describing dynamic string. */ CONST char *string; /* String to append. Must be * null-terminated. */ { int newSize, flags; - char *dst, *newString; + char *dst; newSize = Tcl_ScanElement(string, &flags) + dsPtr->length + 1; /* * Allocate a larger buffer for the string if the current one isn't @@ -2146,18 +1367,22 @@ * to a larger buffer, since there may be embedded NULLs in the * string in some cases. */ if (newSize >= dsPtr->spaceAvl) { - dsPtr->spaceAvl = newSize*2; - newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl); - memcpy((VOID *) newString, (VOID *) dsPtr->string, - (size_t) dsPtr->length); - if (dsPtr->string != dsPtr->staticSpace) { - ckfree(dsPtr->string); - } - dsPtr->string = newString; + dsPtr->spaceAvl = newSize * 2; + if (dsPtr->string == dsPtr->staticSpace) { + char *newString; + + newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl); + memcpy((VOID *) newString, (VOID *) dsPtr->string, + (size_t) dsPtr->length); + dsPtr->string = newString; + } else { + dsPtr->string = (char *) ckrealloc((VOID *) dsPtr->string, + (size_t) dsPtr->spaceAvl); + } } /* * Convert the new string to a list element and copy it into the * buffer at the end, with a space, if needed. @@ -2196,31 +1421,45 @@ void Tcl_DStringSetLength(dsPtr, length) 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) { - char *newString; - - dsPtr->spaceAvl = length+1; - newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl); - /* - * 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. + * 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. */ - memcpy((VOID *) newString, (VOID *) dsPtr->string, - (size_t) dsPtr->length); - if (dsPtr->string != dsPtr->staticSpace) { - ckfree(dsPtr->string); + newsize = dsPtr->spaceAvl * 2; + if (length < newsize) { + dsPtr->spaceAvl = newsize; + } else { + dsPtr->spaceAvl = length + 1; } - dsPtr->string = newString; + if (dsPtr->string == dsPtr->staticSpace) { + char *newString; + + newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl); + memcpy((VOID *) newString, (VOID *) dsPtr->string, + (size_t) dsPtr->length); + dsPtr->string = newString; + } else { + dsPtr->string = (char *) ckrealloc((VOID *) dsPtr->string, + (size_t) dsPtr->spaceAvl); + } } dsPtr->length = length; dsPtr->string[length] = 0; } @@ -2237,12 +1476,11 @@ * * Side effects: * The previous contents of the dynamic string are lost, and * the new value is an empty string. * - *---------------------------------------------------------------------- - */ + *---------------------------------------------------------------------- */ void Tcl_DStringFree(dsPtr) Tcl_DString *dsPtr; /* Structure describing dynamic string. */ { @@ -2250,11 +1488,11 @@ ckfree(dsPtr->string); } dsPtr->string = dsPtr->staticSpace; dsPtr->length = 0; dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; - dsPtr->staticSpace[0] = 0; + dsPtr->staticSpace[0] = '\0'; } /* *---------------------------------------------------------------------- * @@ -2294,11 +1532,11 @@ } dsPtr->string = dsPtr->staticSpace; dsPtr->length = 0; dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; - dsPtr->staticSpace[0] = 0; + dsPtr->staticSpace[0] = '\0'; } /* *---------------------------------------------------------------------- * @@ -2332,16 +1570,14 @@ } /* * If the string result is empty, move the object result to the * string result, then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS. */ if (*(iPtr->result) == 0) { - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL), + Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), TCL_VOLATILE); } dsPtr->length = strlen(iPtr->result); if (iPtr->freeProc != NULL) { @@ -2454,22 +1690,27 @@ double value; /* Value to print as string. */ char *dst; /* Where to store converted value; * must have at least TCL_DOUBLE_SPACE * characters. */ { - char *p; + char *p, c; + Tcl_UniChar ch; + Tcl_MutexLock(&precisionMutex); sprintf(dst, precisionFormat, value); + Tcl_MutexUnlock(&precisionMutex); /* * If the ASCII result looks like an integer, add ".0" so that it * doesn't look like an integer anymore. This prevents floating-point * values from being converted to integers unintentionally. */ - for (p = dst; *p != 0; p++) { - if ((*p == '.') || (isalpha(UCHAR(*p)))) { + for (p = dst; *p != 0; ) { + p += Tcl_UtfToUniChar(p, &ch); + c = UCHAR(ch); + if ((c == '.') || isalpha(UCHAR(c))) { /* INTL: ISO only. */ return; } } p[0] = '.'; p[1] = '0'; @@ -2526,13 +1767,16 @@ * value. This is needed in case the variable was modified in * some other interpreter so that this interpreter's value is * out of date. */ + Tcl_MutexLock(&precisionMutex); + if (flags & TCL_TRACE_READS) { Tcl_SetVar2(interp, name1, name2, precisionString, flags & TCL_GLOBAL_ONLY); + Tcl_MutexUnlock(&precisionMutex); return (char *) NULL; } /* * The variable is being written. Check the new value and disallow @@ -2542,10 +1786,11 @@ */ if (Tcl_IsSafe(interp)) { Tcl_SetVar2(interp, name1, name2, precisionString, flags & TCL_GLOBAL_ONLY); + Tcl_MutexUnlock(&precisionMutex); return "can't modify precision from a safe interpreter"; } value = Tcl_GetVar2(interp, name1, name2, flags & TCL_GLOBAL_ONLY); if (value == NULL) { value = ""; @@ -2553,14 +1798,16 @@ prec = strtoul(value, &end, 10); if ((prec <= 0) || (prec > TCL_MAX_PREC) || (prec > 100) || (end == value) || (*end != 0)) { Tcl_SetVar2(interp, name1, name2, precisionString, flags & TCL_GLOBAL_ONLY); + Tcl_MutexUnlock(&precisionMutex); return "improper value for precision"; } TclFormatInt(precisionString, prec); sprintf(precisionFormat, "%%.%dg", prec); + Tcl_MutexUnlock(&precisionMutex); return (char *) NULL; } /* *---------------------------------------------------------------------- @@ -2599,11 +1846,12 @@ if (end == start) { return 0; } end--; if (*end != '{') { - if (isspace(UCHAR(*end)) && ((end == start) || (end[-1] != '\\'))) { + if (isspace(UCHAR(*end)) /* INTL: ISO space. */ + && ((end == start) || (end[-1] != '\\'))) { return 0; } return 1; } do { @@ -2610,11 +1858,11 @@ if (end == start) { return 0; } end--; } while (*end == '{'); - if (isspace(UCHAR(*end))) { + if (isspace(UCHAR(*end))) { /* INTL: ISO space. */ return 0; } return 1; } @@ -2651,11 +1899,21 @@ int i; int numFormatted, j; char *digits = "0123456789"; /* - * Check first whether "n" is the maximum negative value. This is + * 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. */ if (n == -n) { @@ -2713,25 +1971,44 @@ * *---------------------------------------------------------------------- */ int -TclLooksLikeInt(p) - char *p; /* Pointer to string. */ +TclLooksLikeInt(bytes, length) + register char *bytes; /* Points to first byte of the string. */ + int length; /* Number of bytes in the string. If < 0 + * bytes up to the first null byte are + * considered (if they may appear in an + * integer). */ { - while (isspace(UCHAR(*p))) { + register char *p, *end; + + if (length < 0) { + length = (bytes? strlen(bytes) : 0); + } + end = (bytes + length); + + p = bytes; + while ((p < end) && isspace(UCHAR(*p))) { /* INTL: ISO space. */ p++; } + if (p == end) { + return 0; + } + if ((*p == '+') || (*p == '-')) { p++; } - if (!isdigit(UCHAR(*p))) { + if ((p == end) || !isdigit(UCHAR(*p))) { /* INTL: digit */ return 0; } p++; - while (isdigit(UCHAR(*p))) { + while ((p < end) && isdigit(UCHAR(*p))) { /* INTL: digit */ p++; + } + if (p == end) { + return 1; } if ((*p != '.') && (*p != 'e') && (*p != 'E')) { return 1; } return 0; @@ -2762,34 +2039,30 @@ *---------------------------------------------------------------------- */ int TclGetIntForIndex(interp, objPtr, endValue, indexPtr) - Tcl_Interp *interp; /* Interpreter to use for error reporting. + 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 + Tcl_Obj *objPtr; /* Points to an object containing either * "end" or an integer. */ - int endValue; /* The value to be stored at "indexPtr" if + int endValue; /* The value to be stored at "indexPtr" if * "objPtr" holds "end". */ - int *indexPtr; /* Location filled in with an integer + int *indexPtr; /* Location filled in with an integer * representing an index. */ { Interp *iPtr = (Interp *) interp; char *bytes; int index, length, result; - /* - * THIS FAILS IF THE INDEX OBJECT'S STRING REP CONTAINS NULLS. - */ - if (objPtr->typePtr == &tclIntType) { *indexPtr = (int)objPtr->internalRep.longValue; return TCL_OK; } - bytes = TclGetStringFromObj(objPtr, &length); + bytes = Tcl_GetStringFromObj(objPtr, &length); if ((*bytes == 'e') && (strncmp(bytes, "end", (unsigned) length) == 0)) { index = endValue; } else { result = Tcl_GetIntFromObj((Tcl_Interp *) NULL, objPtr, &index); @@ -2803,5 +2076,85 @@ } } *indexPtr = index; return TCL_OK; } + +/* + *---------------------------------------------------------------------- + * + * Tcl_GetNameOfExecutable -- + * + * This procedure simply returns a pointer to the internal full + * path name of the executable file as computed by + * Tcl_FindExecutable. This procedure call is the C API + * equivalent to the "info nameofexecutable" command. + * + * Results: + * A pointer to the internal string or NULL if the internal full + * path name has not been computed or unknown. + * + * Side effects: + * The object referenced by "objPtr" might be converted to an + * integer object. + * + *---------------------------------------------------------------------- + */ + +CONST char * +Tcl_GetNameOfExecutable() +{ + return (tclExecutableName); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_GetCwd -- + * + * This function replaces the library version of getcwd(). + * + * 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. + * + *---------------------------------------------------------------------- + */ + +char * +Tcl_GetCwd(interp, cwdPtr) + Tcl_Interp *interp; + Tcl_DString *cwdPtr; +{ + return TclpGetCwd(interp, cwdPtr); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_Chdir -- + * + * This function replaces the library version of chdir(). + * + * Results: + * See chdir() documentation. + * + * Side effects: + * See chdir() documentation. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_Chdir(dirName) + CONST char *dirName; +{ + return TclpChdir(dirName); +} + Index: generic/tclVar.c ================================================================== --- generic/tclVar.c +++ generic/tclVar.c @@ -7,15 +7,16 @@ * 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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclVar.c 1.130 97/10/29 18:26:16 + * RCS: @(#) $Id: tclVar.c,v 1.1.2.5 1999/04/06 19:06:54 surles Exp $ */ #include "tclInt.h" #include "tclPort.h" @@ -26,11 +27,12 @@ static char *noSuchVar = "no such variable"; static char *isArray = "variable is array"; static char *needArray = "variable isn't array"; static char *noSuchElement = "no such element in array"; -static char *danglingUpvar = "upvar refers to element in deleted array"; +static char *danglingElement = "upvar refers to element in deleted array"; +static char *danglingVar = "upvar refers to variable in deleted namespace"; static char *badNamespace = "parent namespace doesn't exist"; static char *missingName = "missing variable name"; /* * Forward references to procedures defined later in this file: @@ -73,13 +75,11 @@ * (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 - * interp->result if TCL_LEAVE_ERR_MSG is set in flags. (The result - * isn't put in interp->objResultPtr because this procedure is used - * by so many string-based routines.) + * 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 @@ -95,21 +95,17 @@ Var * TclLookupVar(interp, part1, part2, flags, msg, createPart1, createPart2, arrayPtrPtr) Tcl_Interp *interp; /* Interpreter to use for lookup. */ - char *part1; /* If part2 isn't NULL, this is the name of - * an array. Otherwise, if the - * TCL_PARSE_PART1 flag bit is set this + register 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 elemnt. If - * TCL_PARSE_PART1 isn't present, then - * this is the name of a scalar variable. */ + * include a parenthesized array element. */ char *part2; /* Name of element within array, or NULL. */ int flags; /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, - * TCL_LEAVE_ERR_MSG, and - * TCL_PARSE_PART1 bits matter. */ + * and TCL_LEAVE_ERR_MSG bits matter. */ 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 @@ -139,11 +135,12 @@ /* If this procedure parses a name into * array and index, these point to the * parens around the index. Otherwise they * are NULL. These are needed to restore * the parens after parsing the name. */ - Namespace *varNsPtr, *dummy1Ptr, *dummy2Ptr; + Namespace *varNsPtr, *cxtNsPtr, *dummy1Ptr, *dummy2Ptr; + ResolverScheme *resPtr; Tcl_HashEntry *hPtr; register char *p; int new, i, result; varPtr = NULL; @@ -150,39 +147,82 @@ *arrayPtrPtr = NULL; openParen = closeParen = NULL; varNsPtr = NULL; /* set non-NULL if a nonlocal variable */ /* - * If the name hasn't been parsed into array name and index yet, - * do it now. + * Parse part1 into array name and index. + * Always check if part1 is an array element name and allow it only if + * part2 is not given. + * (if one does not care about creating array elements that can't be used + * from tcl, and prefer slightly better performance, one can put + * the following in an if (part2 == NULL) { ... } block and remove + * the part2's test and error reporting or move that code in array set) */ elName = part2; - if (flags & TCL_PARSE_PART1) { - for (p = part1; ; p++) { - if (*p == 0) { - elName = NULL; - break; - } - if (*p == '(') { - openParen = p; - do { - p++; - } while (*p != '\0'); - p--; - if (*p == ')') { - closeParen = p; - *openParen = 0; - elName = openParen+1; - } else { + for (p = part1; *p ; p++) { + if (*p == '(') { + openParen = p; + do { + p++; + } while (*p != '\0'); + p--; + if (*p == ')') { + if (part2 != NULL) { openParen = NULL; - elName = NULL; + if (flags & TCL_LEAVE_ERR_MSG) { + VarErrMsg(interp, part1, part2, msg, needArray); + } + goto done; } - break; + closeParen = p; + *openParen = 0; + elName = openParen+1; + } else { + openParen = NULL; } + break; } } + + /* + * 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 || iPtr->varFramePtr == NULL) { + cxtNsPtr = iPtr->globalNsPtr; + } else { + cxtNsPtr = iPtr->varFramePtr->nsPtr; + } + + if (cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL) { + resPtr = iPtr->resolverPtr; + + if (cxtNsPtr->varResProc) { + result = (*cxtNsPtr->varResProc)(interp, part1, + (Tcl_Namespace *) cxtNsPtr, flags, &var); + } else { + result = TCL_CONTINUE; + } + + while (result == TCL_CONTINUE && resPtr) { + if (resPtr->varResProc) { + result = (*resPtr->varResProc)(interp, part1, + (Tcl_Namespace *) cxtNsPtr, flags, &var); + } + resPtr = resPtr->nextPtr; + } + + if (result == TCL_OK) { + varPtr = (Var *) var; + goto lookupVarPart2; + } else if (result != TCL_CONTINUE) { + return (Var *) NULL; + } + } /* * Look up part1. Look it up as either a namespace variable or as a * local variable in a procedure call frame (varFramePtr). * Interpret part1 as a namespace variable if: @@ -198,43 +238,29 @@ * If createPart1 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) - || (varFramePtr == NULL) - || !varFramePtr->isProcCallFrame - || (strstr(part1, "::") != NULL)) { + || (varFramePtr == NULL) + || !varFramePtr->isProcCallFrame + || (strstr(part1, "::") != NULL)) { char *tail; + /* + * Don't pass TCL_LEAVE_ERR_MSG, we may yet create the variable, + * or otherwise generate our own error! + */ var = Tcl_FindNamespaceVar(interp, part1, (Tcl_Namespace *) NULL, - flags); + flags & ~TCL_LEAVE_ERR_MSG); if (var != (Tcl_Var) NULL) { varPtr = (Var *) var; } if (varPtr == NULL) { - if (flags & TCL_LEAVE_ERR_MSG) { - Tcl_ResetResult(interp); - } if (createPart1) { /* var wasn't found so create it */ - result = TclGetNamespaceForQualName(interp, part1, - (Namespace *) NULL, flags, &varNsPtr, &dummy1Ptr, - &dummy2Ptr, &tail); - if (result != TCL_OK) { - if (flags & TCL_LEAVE_ERR_MSG) { - /* - * Move the interpreter's object result to the - * string result, then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REP HAS NULLS. - */ - - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), - (int *) NULL), - TCL_VOLATILE); - } - goto done; - } + TclGetNamespaceForQualName(interp, part1, (Namespace *) NULL, + flags, &varNsPtr, &dummy1Ptr, &dummy2Ptr, &tail); + if (varNsPtr == NULL) { if (flags & TCL_LEAVE_ERR_MSG) { VarErrMsg(interp, part1, part2, msg, badNamespace); } goto done; @@ -263,12 +289,12 @@ CompiledLocal *localPtr = procPtr->firstLocalPtr; Var *localVarPtr = varFramePtr->compiledLocals; int part1Len = strlen(part1); for (i = 0; i < localCt; i++) { - if (!localPtr->isTemp) { - char *localName = localVarPtr->name; + if (!TclIsVarTemporary(localPtr)) { + register char *localName = localVarPtr->name; if ((part1[0] == localName[0]) && (part1Len == localPtr->nameLength) && (strcmp(part1, localName) == 0)) { varPtr = localVarPtr; break; @@ -280,11 +306,11 @@ if (varPtr == NULL) { /* look in the frame's var hash table */ tablePtr = varFramePtr->varTablePtr; if (createPart1) { if (tablePtr == NULL) { tablePtr = (Tcl_HashTable *) - ckalloc(sizeof(Tcl_HashTable)); + ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS); varFramePtr->varTablePtr = tablePtr; } hPtr = Tcl_CreateHashEntry(tablePtr, part1, &new); if (new) { @@ -308,10 +334,12 @@ } varPtr = (Var *) Tcl_GetHashValue(hPtr); } } } + + lookupVarPart2: if (openParen != NULL) { *openParen = '('; openParen = NULL; } @@ -344,14 +372,27 @@ VarErrMsg(interp, part1, part2, msg, noSuchVar); } varPtr = NULL; goto done; } + + /* + * Make sure we are not resurrecting a namespace variable from a + * deleted namespace! + */ + if ((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->hPtr == NULL)) { + if (flags & TCL_LEAVE_ERR_MSG) { + VarErrMsg(interp, part1, part2, msg, danglingVar); + } + varPtr = NULL; + goto done; + } + TclSetVarArray(varPtr); TclClearVarUndefined(varPtr); varPtr->value.tablePtr = - (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(varPtr->value.tablePtr, TCL_STRING_KEYS); } else if (!TclIsVarArray(varPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { VarErrMsg(interp, part1, part2, msg, needArray); } @@ -408,11 +449,11 @@ * * 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 interp->result if the TCL_LEAVE_ERR_MSG flag is set. + * 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: @@ -428,12 +469,11 @@ 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. */ { - return Tcl_GetVar2(interp, varName, (char *) NULL, - (flags | TCL_PARSE_PART1)); + return Tcl_GetVar2(interp, varName, (char *) NULL, flags); } /* *---------------------------------------------------------------------- * @@ -444,11 +484,11 @@ * * 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 interp->result if the + * 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: @@ -464,57 +504,21 @@ char *part1; /* Name of an array (if part2 is non-NULL) * or the name of a variable. */ 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, TCL_LEAVE_ERR_MSG, - * and TCL_PARSE_PART1 bits. */ + * TCL_NAMESPACE_ONLY and TCL_LEAVE_ERR_MSG + * bits. */ { - register Tcl_Obj *part1Ptr; - register Tcl_Obj *part2Ptr = NULL; Tcl_Obj *objPtr; - int length; - - length = strlen(part1); - TclNewObj(part1Ptr); - TclInitStringRep(part1Ptr, part1, length); - Tcl_IncrRefCount(part1Ptr); - - if (part2 != NULL) { - length = strlen(part2); - TclNewObj(part2Ptr); - TclInitStringRep(part2Ptr, part2, length); - Tcl_IncrRefCount(part2Ptr); - } - - objPtr = Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags); - - TclDecrRefCount(part1Ptr); /* done with the part1 name object */ - if (part2Ptr != NULL) { - TclDecrRefCount(part2Ptr); /* and the part2 name object */ - } - + + objPtr = Tcl_GetVar2Ex(interp, part1, part2, flags); if (objPtr == NULL) { - /* - * Move the interpreter's object result to the string result, - * then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS. - */ - - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL), - TCL_VOLATILE); return NULL; } - - /* - * THIS FAILS IF Tcl_ObjGetVar2's RESULT'S STRING REP HAS A NULL BYTE. - */ - - return TclGetStringFromObj(objPtr, (int *) NULL); -} - + return TclGetString(objPtr); +} /* *---------------------------------------------------------------------- * * Tcl_ObjGetVar2 -- * @@ -548,24 +552,61 @@ * part1Ptr. */ int flags; /* OR-ed combination of TCL_GLOBAL_ONLY, * TCL_LEAVE_ERR_MSG, and * TCL_PARSE_PART1 bits. */ { + char *part1, *part2; + + part1 = Tcl_GetString(part1Ptr); + if (part2Ptr != NULL) { + part2 = Tcl_GetString(part2Ptr); + } else { + part2 = NULL; + } + + return Tcl_GetVar2Ex(interp, part1, part2, flags); +} + +/* + *---------------------------------------------------------------------- + * + * 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(interp, part1, part2, flags) + Tcl_Interp *interp; /* Command interpreter in which variable is + * to be looked up. */ + char *part1; /* Name of an array (if part2 is non-NULL) + * or the name of a variable. */ + 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. */ +{ Interp *iPtr = (Interp *) interp; register Var *varPtr; Var *arrayPtr; - char *part1, *msg; - char *part2 = NULL; - - /* - * THIS FAILS IF A NAME OBJECT'S STRING REP HAS A NULL BYTE. - */ - - part1 = TclGetStringFromObj(part1Ptr, (int *) NULL); - if (part2Ptr != NULL) { - part2 = TclGetStringFromObj(part2Ptr, (int *) NULL); - } + char *msg; + varPtr = TclLookupVar(interp, part1, part2, flags, "read", /*createPart1*/ 0, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { return NULL; } @@ -575,11 +616,11 @@ */ if ((varPtr->tracePtr != NULL) || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) { msg = CallTraces(iPtr, arrayPtr, varPtr, part1, part2, - (flags & (TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY|TCL_PARSE_PART1)) | TCL_TRACE_READS); + (flags & (TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY)) | TCL_TRACE_READS); if (msg != NULL) { if (flags & TCL_LEAVE_ERR_MSG) { VarErrMsg(interp, part1, part2, "read", msg); } goto errorReturn; @@ -644,11 +685,11 @@ Tcl_Obj * TclGetIndexedScalar(interp, localIndex, leaveErrorMsg) Tcl_Interp *interp; /* Command interpreter in which variable is * to be looked up. */ - int localIndex; /* Index of variable in procedure's array + register int localIndex; /* Index of variable in procedure's array * of local variables. */ int leaveErrorMsg; /* 1 if to leave an error message in * interpreter's result on an error. * Otherwise no error message is left. */ { @@ -657,30 +698,29 @@ /* 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. */ Var *compiledLocals = varFramePtr->compiledLocals; - Var *varPtr; /* Points to the variable's in-frame Var + register Var *varPtr; /* Points to the variable's in-frame Var * structure. */ char *varName; /* Name of the local variable. */ char *msg; #ifdef TCL_COMPILE_DEBUG - Proc *procPtr = varFramePtr->procPtr; - int localCt = procPtr->numCompiledLocals; + int localCt = varFramePtr->procPtr->numCompiledLocals; if (compiledLocals == NULL) { fprintf(stderr, "\nTclGetIndexedScalar: can't get local %i in frame 0x%x, no compiled locals\n", - localIndex, (unsigned int) varFramePtr); + localIndex, (unsigned int) varFramePtr); panic("TclGetIndexedScalar: no compiled locals in frame 0x%x", - (unsigned int) varFramePtr); + (unsigned int) varFramePtr); } if ((localIndex < 0) || (localIndex >= localCt)) { fprintf(stderr, "\nTclGetIndexedScalar: can't get local %i in frame 0x%x with %i locals\n", - localIndex, (unsigned int) varFramePtr, localCt); + localIndex, (unsigned int) varFramePtr, localCt); panic("TclGetIndexedScalar: bad local index %i in frame 0x%x", - localIndex, (unsigned int) varFramePtr); + localIndex, (unsigned int) varFramePtr); } #endif /* TCL_COMPILE_DEBUG */ varPtr = &(compiledLocals[localIndex]); varName = varPtr->name; @@ -700,11 +740,11 @@ * Invoke any traces that have been set for the variable. */ if (varPtr->tracePtr != NULL) { msg = CallTraces(iPtr, /*arrayPtr*/ NULL, varPtr, varName, NULL, - TCL_TRACE_READS); + TCL_TRACE_READS); if (msg != NULL) { if (leaveErrorMsg) { VarErrMsg(interp, varName, NULL, "read", msg); } return NULL; @@ -722,10 +762,11 @@ msg = isArray; } else { msg = noSuchVar; } VarErrMsg(interp, varName, NULL, "read", msg); + } return NULL; } return varPtr->value.objPtr; } @@ -788,27 +829,23 @@ Proc *procPtr = varFramePtr->procPtr; int localCt = procPtr->numCompiledLocals; if (compiledLocals == NULL) { fprintf(stderr, "\nTclGetElementOfIndexedArray: can't get element of local %i in frame 0x%x, no compiled locals\n", - localIndex, (unsigned int) varFramePtr); + localIndex, (unsigned int) varFramePtr); panic("TclGetIndexedScalar: no compiled locals in frame 0x%x", - (unsigned int) varFramePtr); + (unsigned int) varFramePtr); } if ((localIndex < 0) || (localIndex >= localCt)) { fprintf(stderr, "\nTclGetIndexedScalar: can't get element of local %i in frame 0x%x with %i locals\n", - localIndex, (unsigned int) varFramePtr, localCt); + localIndex, (unsigned int) varFramePtr, localCt); panic("TclGetElementOfIndexedArray: bad local index %i in frame 0x%x", - localIndex, (unsigned int) varFramePtr); + localIndex, (unsigned int) varFramePtr); } #endif /* TCL_COMPILE_DEBUG */ - /* - * THIS FAILS IF THE ELEMENT NAME OBJECT'S STRING REP HAS A NULL BYTE. - */ - - elem = Tcl_GetStringFromObj(elemPtr, (int *) NULL); + elem = TclGetString(elemPtr); arrayPtr = &(compiledLocals[localIndex]); arrayName = arrayPtr->name; /* * If arrayPtr is a link variable, we have a reference to some variable @@ -902,11 +939,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_SetCmd -- + * Tcl_SetObjCmd -- * * This procedure is invoked to process the "set" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -918,39 +955,36 @@ *---------------------------------------------------------------------- */ /* ARGSUSED */ int -Tcl_SetCmd(dummy, interp, argc, argv) +Tcl_SetObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ register Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ -{ - if (argc == 2) { - char *value; - - value = Tcl_GetVar2(interp, argv[1], (char *) NULL, - TCL_LEAVE_ERR_MSG|TCL_PARSE_PART1); - if (value == NULL) { + 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_SetResult(interp, value, TCL_VOLATILE); + Tcl_SetObjResult(interp, varValueObj); return TCL_OK; - } else if (argc == 3) { - char *result; + } else if (objc == 3) { - result = Tcl_SetVar2(interp, argv[1], (char *) NULL, argv[2], - TCL_LEAVE_ERR_MSG|TCL_PARSE_PART1); - if (result == NULL) { + varValueObj = Tcl_ObjSetVar2(interp, objv[1], NULL, objv[2], + TCL_LEAVE_ERR_MSG); + if (varValueObj == NULL) { return TCL_ERROR; } - Tcl_SetResult(interp, result, TCL_VOLATILE); + Tcl_SetObjResult(interp, varValueObj); return TCL_OK; } else { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " varName ?newValue?\"", (char *) NULL); + Tcl_WrongNumArgs(interp, 1, objv, "varName ?newValue?"); return TCL_ERROR; } } /* @@ -963,11 +997,11 @@ * 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 interp->result. Note that the + * 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, @@ -986,12 +1020,11 @@ 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. */ { - return Tcl_SetVar2(interp, varName, (char *) NULL, newValue, - (flags | TCL_PARSE_PART1)); + return Tcl_SetVar2(interp, varName, (char *) NULL, newValue, flags); } /* *---------------------------------------------------------------------- * @@ -1006,11 +1039,11 @@ * 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 interp->result. Note that the returned + * 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 @@ -1030,74 +1063,90 @@ * NULL. */ 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, TCL_LEAVE_ERR_MSG, or - * TCL_PARSE_PART1. */ + * TCL_LIST_ELEMENT, or TCL_LEAVE_ERR_MSG */ { register Tcl_Obj *valuePtr; - register Tcl_Obj *part1Ptr; - register Tcl_Obj *part2Ptr = NULL; Tcl_Obj *varValuePtr; - int length; /* * Create an object holding the variable's new value and use - * Tcl_ObjSetVar2 to actually set the variable. + * Tcl_SetVar2Ex to actually set the variable. */ - length = newValue ? strlen(newValue) : 0; - TclNewObj(valuePtr); - TclInitStringRep(valuePtr, newValue, length); + valuePtr = Tcl_NewStringObj(newValue, -1); Tcl_IncrRefCount(valuePtr); - length = strlen(part1) ; - TclNewObj(part1Ptr); - TclInitStringRep(part1Ptr, part1, length); - Tcl_IncrRefCount(part1Ptr); - - if (part2 != NULL) { - length = strlen(part2); - TclNewObj(part2Ptr); - TclInitStringRep(part2Ptr, part2, length); - Tcl_IncrRefCount(part2Ptr); - } - - varValuePtr = Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, valuePtr, - flags); - - TclDecrRefCount(part1Ptr); /* done with the part1 name object */ - if (part2Ptr != NULL) { - TclDecrRefCount(part2Ptr); /* and the part2 name object */ - } + varValuePtr = Tcl_SetVar2Ex(interp, part1, part2, valuePtr, flags); Tcl_DecrRefCount(valuePtr); /* done with the object */ if (varValuePtr == NULL) { - /* - * Move the interpreter's object result to the string result, - * then reset the object result. - * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS. - */ - - Tcl_SetResult(interp, - TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL), - TCL_VOLATILE); return NULL; } - - /* - * THIS FAILS IF Tcl_ObjSetVar2's RESULT'S STRING REP HAS A NULL BYTE. - */ - - return TclGetStringFromObj(varValuePtr, (int *) NULL); + return TclGetString(varValuePtr); } /* *---------------------------------------------------------------------- * * Tcl_ObjSetVar2 -- + * + * This function is the same as Tcl_SetVar2Ex below, 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. + + * + *---------------------------------------------------------------------- + */ + +Tcl_Obj * +Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, newValuePtr, flags) + 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, TCL_LEAVE_ERR_MSG, or + * TCL_PARSE_PART1. */ +{ + char *part1, *part2; + + part1 = Tcl_GetString(part1Ptr); + if (part2Ptr != NULL) { + part2 = Tcl_GetString(part2Ptr); + } else { + part2 = NULL; + } + + return Tcl_SetVar2Ex(interp, part1, part2, newValuePtr, flags); +} + +/* + *---------------------------------------------------------------------- + * + * 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. @@ -1117,11 +1166,11 @@ * * 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_ObjSetVar2. newValuePtr's ref count is also left unchanged if + * 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 @@ -1129,61 +1178,52 @@ * *---------------------------------------------------------------------- */ Tcl_Obj * -Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, newValuePtr, flags) +Tcl_SetVar2Ex(interp, part1, part2, newValuePtr, flags) 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. */ + char *part1; /* Name of an array (if part2 is non-NULL) + * or the name of a variable. */ + 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, TCL_LEAVE_ERR_MSG, or - * TCL_PARSE_PART1. */ + * TCL_LIST_ELEMENT or TCL_LEAVE_ERR_MSG. */ { Interp *iPtr = (Interp *) interp; register Var *varPtr; Var *arrayPtr; Tcl_Obj *oldValuePtr; Tcl_Obj *resultPtr = NULL; - char *part1, *bytes; - char *part2 = NULL; + char *bytes; int length, result; - /* - * THIS FAILS IF A NAME OBJECT'S STRING REP HAS A NULL BYTE. - */ - - part1 = TclGetStringFromObj(part1Ptr, (int *) NULL); - if (part2Ptr != NULL) { - part2 = TclGetStringFromObj(part2Ptr, (int *) NULL); - } - varPtr = TclLookupVar(interp, part1, part2, flags, "set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { return NULL; } /* * If the variable is in a hashtable and its hPtr field is NULL, then we - * have an upvar to an array element where the array was deleted, - * leaving the element dangling at the end of the upvar. Generate an - * error (allowing the variable to be reset would screw up our storage - * allocation and is meaningless anyway). + * 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 ((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->hPtr == NULL)) { if (flags & TCL_LEAVE_ERR_MSG) { - VarErrMsg(interp, part1, part2, "set", danglingUpvar); + if (TclIsVarArrayElement(varPtr)) { + VarErrMsg(interp, part1, part2, "set", danglingElement); + } else { + VarErrMsg(interp, part1, part2, "set", danglingVar); + } } return NULL; } /* @@ -1269,11 +1309,11 @@ } bytes = Tcl_GetStringFromObj(newValuePtr, &length); neededBytes = Tcl_ScanElement(bytes, &listFlags); oldValuePtr = Tcl_NewObj(); oldValuePtr->bytes = (char *) - ckalloc((unsigned) (neededBytes + 1)); + ckalloc((unsigned) (neededBytes + 1)); oldValuePtr->length = Tcl_ConvertElement(bytes, oldValuePtr->bytes, listFlags); varPtr->value.objPtr = oldValuePtr; Tcl_IncrRefCount(varPtr->value.objPtr); } else if (newValuePtr != oldValuePtr) { @@ -1295,11 +1335,11 @@ */ if ((varPtr->tracePtr != NULL) || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) { char *msg = CallTraces(iPtr, arrayPtr, varPtr, part1, part2, - (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_PARSE_PART1)) | TCL_TRACE_WRITES); + (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) | TCL_TRACE_WRITES); if (msg != NULL) { if (flags & TCL_LEAVE_ERR_MSG) { VarErrMsg(interp, part1, part2, "set", msg); } goto cleanup; @@ -1396,19 +1436,19 @@ Proc *procPtr = varFramePtr->procPtr; int localCt = procPtr->numCompiledLocals; if (compiledLocals == NULL) { fprintf(stderr, "\nTclSetIndexedScalar: can't set local %i in frame 0x%x, no compiled locals\n", - localIndex, (unsigned int) varFramePtr); + localIndex, (unsigned int) varFramePtr); panic("TclSetIndexedScalar: no compiled locals in frame 0x%x", - (unsigned int) varFramePtr); + (unsigned int) varFramePtr); } if ((localIndex < 0) || (localIndex >= localCt)) { fprintf(stderr, "\nTclSetIndexedScalar: can't set local %i in frame 0x%x with %i locals\n", - localIndex, (unsigned int) varFramePtr, localCt); + localIndex, (unsigned int) varFramePtr, localCt); panic("TclSetIndexedScalar: bad local index %i in frame 0x%x", - localIndex, (unsigned int) varFramePtr); + localIndex, (unsigned int) varFramePtr); } #endif /* TCL_COMPILE_DEBUG */ varPtr = &(compiledLocals[localIndex]); varName = varPtr->name; @@ -1424,19 +1464,23 @@ varPtr = varPtr->value.linkPtr; } /* * If the variable is in a hashtable and its hPtr field is NULL, then we - * have an upvar to an array element where the array was deleted, - * leaving the element dangling at the end of the upvar. Generate an - * error (allowing the variable to be reset would screw up our storage - * allocation and is meaningless anyway). + * 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 ((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->hPtr == NULL)) { if (leaveErrorMsg) { - VarErrMsg(interp, varName, NULL, "set", danglingUpvar); + if (TclIsVarArrayElement(varPtr)) { + VarErrMsg(interp, varName, NULL, "set", danglingElement); + } else { + VarErrMsg(interp, varName, NULL, "set", danglingVar); + } } return NULL; } /* @@ -1577,27 +1621,23 @@ Proc *procPtr = varFramePtr->procPtr; int localCt = procPtr->numCompiledLocals; if (compiledLocals == NULL) { fprintf(stderr, "\nTclSetElementOfIndexedArray: can't set element of local %i in frame 0x%x, no compiled locals\n", - localIndex, (unsigned int) varFramePtr); + localIndex, (unsigned int) varFramePtr); panic("TclSetIndexedScalar: no compiled locals in frame 0x%x", - (unsigned int) varFramePtr); + (unsigned int) varFramePtr); } if ((localIndex < 0) || (localIndex >= localCt)) { fprintf(stderr, "\nTclSetIndexedScalar: can't set elememt of local %i in frame 0x%x with %i locals\n", - localIndex, (unsigned int) varFramePtr, localCt); + localIndex, (unsigned int) varFramePtr, localCt); panic("TclSetElementOfIndexedArray: bad local index %i in frame 0x%x", - localIndex, (unsigned int) varFramePtr); + localIndex, (unsigned int) varFramePtr); } #endif /* TCL_COMPILE_DEBUG */ - /* - * THIS FAILS IF THE ELEMENT NAME OBJECT'S STRING REP HAS A NULL BYTE. - */ - - elem = Tcl_GetStringFromObj(elemPtr, (int *) NULL); + elem = TclGetString(elemPtr); arrayPtr = &(compiledLocals[localIndex]); arrayName = arrayPtr->name; /* * If arrayPtr is a link variable, we have a reference to some variable @@ -1607,19 +1647,38 @@ */ while (TclIsVarLink(arrayPtr)) { arrayPtr = arrayPtr->value.linkPtr; } + + /* + * 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 ((arrayPtr->flags & VAR_IN_HASHTABLE) && (arrayPtr->hPtr == NULL)) { + if (leaveErrorMsg) { + if (TclIsVarArrayElement(arrayPtr)) { + VarErrMsg(interp, arrayName, elem, "set", danglingElement); + } else { + VarErrMsg(interp, arrayName, elem, "set", danglingVar); + } + } + goto errorReturn; + } /* * Make sure we're dealing with an array. */ if (TclIsVarUndefined(arrayPtr) && !TclIsVarArrayElement(arrayPtr)) { TclSetVarArray(arrayPtr); arrayPtr->value.tablePtr = - (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(arrayPtr->value.tablePtr, TCL_STRING_KEYS); TclClearVarUndefined(arrayPtr); } else if (!TclIsVarArray(arrayPtr)) { if (leaveErrorMsg) { VarErrMsg(interp, arrayName, elem, "set", needArray); @@ -1738,36 +1797,33 @@ * *---------------------------------------------------------------------- */ Tcl_Obj * -TclIncrVar2(interp, part1Ptr, part2Ptr, incrAmount, part1NotParsed) +TclIncrVar2(interp, part1Ptr, part2Ptr, incrAmount, flags) 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. */ long incrAmount; /* Amount to be added to variable. */ - int part1NotParsed; /* 1 if part1 hasn't yet been parsed into - * an array name and index (if any). */ + 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. */ { register Tcl_Obj *varValuePtr; Tcl_Obj *resultPtr; int createdNewObj; /* Set 1 if var's value object is shared * so we must increment a copy (i.e. copy * on write). */ long i; - int flags, result; + int result; - flags = TCL_LEAVE_ERR_MSG; - if (part1NotParsed) { - flags |= TCL_PARSE_PART1; - } - varValuePtr = Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags); if (varValuePtr == NULL) { Tcl_AddObjErrorInfo(interp, "\n (reading value of variable to increment)", -1); return NULL; @@ -1796,12 +1852,11 @@ /* * Store the variable's new value and run any write traces. */ - resultPtr = Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, varValuePtr, - flags); + resultPtr = Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, varValuePtr, flags); if (resultPtr == NULL) { return NULL; } return resultPtr; } @@ -1846,11 +1901,11 @@ * on write). */ long i; int result; varValuePtr = TclGetIndexedScalar(interp, localIndex, - /*leaveErrorMsg*/ 1); + /*leaveErrorMsg*/ 1); if (varValuePtr == NULL) { Tcl_AddObjErrorInfo(interp, "\n (reading value of variable to increment)", -1); return NULL; } @@ -1880,11 +1935,11 @@ /* * Store the variable's new value and run any write traces. */ resultPtr = TclSetIndexedScalar(interp, localIndex, varValuePtr, - /*leaveErrorMsg*/ 1); + /*leaveErrorMsg*/ 1); if (resultPtr == NULL) { return NULL; } return resultPtr; } @@ -1933,11 +1988,11 @@ * on write). */ long i; int result; varValuePtr = TclGetElementOfIndexedArray(interp, localIndex, elemPtr, - /*leaveErrorMsg*/ 1); + /*leaveErrorMsg*/ 1); if (varValuePtr == NULL) { Tcl_AddObjErrorInfo(interp, "\n (reading value of variable to increment)", -1); return NULL; } @@ -1967,12 +2022,12 @@ /* * Store the variable's new value and run any write traces. */ resultPtr = TclSetElementOfIndexedArray(interp, localIndex, elemPtr, - varValuePtr, - /*leaveErrorMsg*/ 1); + varValuePtr, + /*leaveErrorMsg*/ 1); if (resultPtr == NULL) { return NULL; } return resultPtr; } @@ -1986,11 +2041,11 @@ * * 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 interp->result. + * is left in the interp's result. * * Side effects: * If varName is defined as a local or global variable in interp, * it is deleted. * @@ -2006,12 +2061,11 @@ * 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. */ { - return Tcl_UnsetVar2(interp, varName, (char *) NULL, - (flags | TCL_PARSE_PART1)); + return Tcl_UnsetVar2(interp, varName, (char *) NULL, flags); } /* *---------------------------------------------------------------------- * @@ -2021,11 +2075,11 @@ * * 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 interp->result. + * 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. @@ -2039,12 +2093,11 @@ * to be looked up. */ char *part1; /* Name of variable or array. */ 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, or - * TCL_PARSE_PART1. */ + * TCL_LEAVE_ERR_MSG. */ { Var dummyVar; Var *varPtr, *dummyVarPtr; Interp *iPtr = (Interp *) interp; Var *arrayPtr; @@ -2096,18 +2149,18 @@ if ((dummyVar.tracePtr != NULL) || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) { varPtr->refCount++; dummyVar.flags &= ~VAR_TRACE_ACTIVE; (void) CallTraces(iPtr, arrayPtr, &dummyVar, part1, part2, - (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_PARSE_PART1)) | TCL_TRACE_UNSETS); + (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) | TCL_TRACE_UNSETS); while (dummyVar.tracePtr != NULL) { VarTrace *tracePtr = dummyVar.tracePtr; dummyVar.tracePtr = tracePtr->nextPtr; ckfree((char *) tracePtr); } for (activePtr = iPtr->activeTracePtr; activePtr != NULL; - activePtr = activePtr->nextPtr) { + activePtr = activePtr->nextPtr) { if (activePtr->varPtr == varPtr) { activePtr->nextTracePtr = NULL; } } varPtr->refCount--; @@ -2121,23 +2174,21 @@ */ dummyVarPtr = &dummyVar; if (TclIsVarArray(dummyVarPtr) && !TclIsVarUndefined(dummyVarPtr)) { DeleteArray(iPtr, part1, dummyVarPtr, - (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) | TCL_TRACE_UNSETS); + (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) | TCL_TRACE_UNSETS); } if (TclIsVarScalar(dummyVarPtr) && (dummyVarPtr->value.objPtr != NULL)) { objPtr = dummyVarPtr->value.objPtr; TclDecrRefCount(objPtr); dummyVarPtr->value.objPtr = NULL; } /* - * If the variable was a namespace variable, decrement its reference - * count. We are in the process of destroying its namespace so that - * namespace will no longer "refer" to the variable. + * If the variable was a namespace variable, decrement its reference count. */ if (varPtr->flags & VAR_NAMESPACE_VAR) { varPtr->flags &= ~VAR_NAMESPACE_VAR; varPtr->refCount--; @@ -2197,12 +2248,12 @@ * TCL_NAMESPACE_ONLY. */ Tcl_VarTraceProc *proc; /* Procedure to call when specified ops are * invoked upon varName. */ ClientData clientData; /* Arbitrary argument to pass to proc. */ { - return Tcl_TraceVar2(interp, varName, (char *) NULL, - (flags | TCL_PARSE_PART1), proc, clientData); + return Tcl_TraceVar2(interp, varName, (char *) NULL, + flags, proc, clientData); } /* *---------------------------------------------------------------------- * @@ -2233,12 +2284,11 @@ * 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, - * TCL_NAMESPACE_ONLY and - * TCL_PARSE_PART1. */ + * and TCL_NAMESPACE_ONLY. */ Tcl_VarTraceProc *proc; /* Procedure to call when specified ops are * invoked upon varName. */ ClientData clientData; /* Arbitrary argument to pass to proc. */ { Var *varPtr, *arrayPtr; @@ -2256,11 +2306,12 @@ tracePtr = (VarTrace *) ckalloc(sizeof(VarTrace)); tracePtr->traceProc = proc; tracePtr->clientData = clientData; tracePtr->flags = - flags & (TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS); + flags & (TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS | + TCL_TRACE_ARRAY); tracePtr->nextPtr = varPtr->tracePtr; varPtr->tracePtr = tracePtr; return TCL_OK; } @@ -2293,12 +2344,11 @@ * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY * and TCL_NAMESPACE_ONLY. */ Tcl_VarTraceProc *proc; /* Procedure assocated with trace. */ ClientData clientData; /* Arbitrary argument to pass to proc. */ { - Tcl_UntraceVar2(interp, varName, (char *) NULL, - (flags | TCL_PARSE_PART1), proc, clientData); + Tcl_UntraceVar2(interp, varName, (char *) NULL, flags, proc, clientData); } /* *---------------------------------------------------------------------- * @@ -2326,12 +2376,11 @@ * 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, - * TCL_NAMESPACE_ONLY and - * TCL_PARSE_PART1. */ + * and TCL_NAMESPACE_ONLY. */ Tcl_VarTraceProc *proc; /* Procedure assocated with trace. */ ClientData clientData; /* Arbitrary argument to pass to proc. */ { register VarTrace *tracePtr; VarTrace *prevPtr; @@ -2338,20 +2387,21 @@ Var *varPtr, *arrayPtr; Interp *iPtr = (Interp *) interp; ActiveVarTrace *activePtr; varPtr = TclLookupVar(interp, part1, part2, - flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_PARSE_PART1), + flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY), /*msg*/ (char *) NULL, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); if (varPtr == NULL) { return; } - flags &= (TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS); + flags &= (TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS | + TCL_TRACE_ARRAY); for (tracePtr = varPtr->tracePtr, prevPtr = NULL; ; - prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) { + prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) { if (tracePtr == NULL) { return; } if ((tracePtr->traceProc == proc) && (tracePtr->flags == flags) && (tracePtr->clientData == clientData)) { @@ -2364,11 +2414,11 @@ * are active: it makes sure that the deleted trace won't be * processed by CallTraces. */ for (activePtr = iPtr->activeTracePtr; activePtr != NULL; - activePtr = activePtr->nextPtr) { + activePtr = activePtr->nextPtr) { if (activePtr->nextTracePtr == tracePtr) { activePtr->nextTracePtr = tracePtr->nextPtr; } } if (prevPtr == NULL) { @@ -2427,11 +2477,11 @@ * return the next trace after that one. * If NULL, this call will return the * first trace. */ { return Tcl_VarTraceInfo2(interp, varName, (char *) NULL, - (flags | TCL_PARSE_PART1), proc, prevClientData); + flags, proc, prevClientData); } /* *---------------------------------------------------------------------- * @@ -2455,12 +2505,11 @@ char *part1; /* Name of variable or array. */ 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, and - * TCL_PARSE_PART1. */ + * TCL_NAMESPACE_ONLY. */ Tcl_VarTraceProc *proc; /* Procedure assocated with trace. */ ClientData prevClientData; /* If non-NULL, gives last value returned * by this procedure, so this call will * return the next trace after that one. * If NULL, this call will return the @@ -2468,11 +2517,11 @@ { register VarTrace *tracePtr; Var *varPtr, *arrayPtr; varPtr = TclLookupVar(interp, part1, part2, - flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_PARSE_PART1), + flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY), /*msg*/ (char *) NULL, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); if (varPtr == NULL) { return NULL; } @@ -2531,17 +2580,13 @@ Tcl_WrongNumArgs(interp, 1, objv, "varName ?varName ...?"); return TCL_ERROR; } for (i = 1; i < objc; i++) { - /* - * THIS FAILS IF A NAME OBJECT'S STRING REP HAS A NULL BYTE. - */ - - name = Tcl_GetStringFromObj(objv[i], (int *) NULL); + name = TclGetString(objv[i]); if (Tcl_UnsetVar2(interp, name, (char *) NULL, - (TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1)) != TCL_OK) { + TCL_LEAVE_ERR_MSG) != TCL_OK) { return TCL_ERROR; } } return TCL_OK; } @@ -2578,28 +2623,24 @@ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "varName ?value value ...?"); return TCL_ERROR; } - if (objc == 2) { - varValuePtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL, - (TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1)); + varValuePtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG); if (varValuePtr == NULL) { return TCL_ERROR; } } else { for (i = 2; i < objc; i++) { varValuePtr = Tcl_ObjSetVar2(interp, objv[1], (Tcl_Obj *) NULL, - objv[i], - (TCL_APPEND_VALUE | TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1)); + objv[i], (TCL_APPEND_VALUE | TCL_LEAVE_ERR_MSG)); if (varValuePtr == NULL) { return TCL_ERROR; } } } - Tcl_SetObjResult(interp, varValuePtr); return TCL_OK; } /* @@ -2634,31 +2675,30 @@ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "varName ?value value ...?"); return TCL_ERROR; } - if (objc == 2) { newValuePtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL, - (TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1)); + (TCL_LEAVE_ERR_MSG)); if (newValuePtr == NULL) { /* * The variable doesn't exist yet. Just create it with an empty * initial value. */ Tcl_Obj *nullObjPtr = Tcl_NewObj(); newValuePtr = Tcl_ObjSetVar2(interp, objv[1], NULL, - nullObjPtr, (TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1)); + nullObjPtr, TCL_LEAVE_ERR_MSG); if (newValuePtr == NULL) { Tcl_DecrRefCount(nullObjPtr); /* free unneeded object */ return TCL_ERROR; } } } else { /* - * We have arguments to append. We used to call Tcl_ObjSetVar2 to + * 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 @@ -2665,26 +2705,25 @@ * we create a new copy to modify: this is "copy on write". */ createdNewObj = 0; createVar = 1; - varValuePtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL, - TCL_PARSE_PART1); + varValuePtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); 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. */ - char *name, *p; + char *p, *varName; int nameBytes, i; - name = TclGetStringFromObj(objv[1], &nameBytes); - for (i = 0, p = name; i < nameBytes; i++, p++) { + varName = Tcl_GetStringFromObj(objv[1], &nameBytes); + for (i = 0, p = varName; i < nameBytes; i++, p++) { if (*p == '(') { - p = (name + nameBytes-1); + p = (varName + nameBytes-1); if (*p == ')') { /* last char is ')' => array ref */ createVar = 0; } break; } @@ -2720,11 +2759,11 @@ numRequired = numElems + (objc-2); if (numRequired > listRepPtr->maxElemCount) { int newMax = (2 * numRequired); Tcl_Obj **newElemPtrs = (Tcl_Obj **) - ckalloc((unsigned) (newMax * sizeof(Tcl_Obj *))); + ckalloc((unsigned) (newMax * sizeof(Tcl_Obj *))); memcpy((VOID *) newElemPtrs, (VOID *) elemPtrs, (size_t) (numElems * sizeof(Tcl_Obj *))); listRepPtr->maxElemCount = newMax; listRepPtr->elements = newElemPtrs; @@ -2753,12 +2792,12 @@ * 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 = Tcl_ObjSetVar2(interp, objv[1], (Tcl_Obj *) NULL, - varValuePtr, (TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1)); + newValuePtr = Tcl_ObjSetVar2(interp, objv[1], NULL, varValuePtr, + TCL_LEAVE_ERR_MSG); if (newValuePtr == NULL) { if (createdNewObj && !createVar) { Tcl_DecrRefCount(varValuePtr); /* free unneeded obj */ } return TCL_ERROR; @@ -2797,48 +2836,72 @@ ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { + /* + * The list of constants below should match the arrayOptions string array + * below. + */ + + enum {ARRAY_ANYMORE, ARRAY_DONESEARCH, ARRAY_EXISTS, ARRAY_GET, + ARRAY_NAMES, ARRAY_NEXTELEMENT, ARRAY_SET, ARRAY_SIZE, + ARRAY_STARTSEARCH}; static char *arrayOptions[] = {"anymore", "donesearch", "exists", - "get", "names", "nextelement", "set", "size", "startsearch", - (char *) NULL}; + "get", "names", "nextelement", "set", + "size", "startsearch", (char *) NULL}; + + Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_HashEntry *hPtr; Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); int notArray; - char *varName; + char *varName, *msg; int index, result; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option arrayName ?arg ...?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], arrayOptions, "option", 0, &index) - != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[1], arrayOptions, "option", + 0, &index) != TCL_OK) { return TCL_ERROR; } /* * Locate the array variable (and it better be an array). - * THIS FAILS IF A NAME OBJECT'S STRING REP HAS A NULL BYTE. */ - varName = TclGetStringFromObj(objv[2], (int *) NULL); + varName = TclGetString(objv[2]); varPtr = TclLookupVar(interp, varName, (char *) NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); notArray = 0; if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) { notArray = 1; } - + + /* + * Special array trace used to keep the env array in sync for + * array names, array get, etc. + */ + + if (varPtr != NULL && varPtr->tracePtr != NULL) { + msg = CallTraces(iPtr, arrayPtr, varPtr, varName, NULL, + (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| + TCL_TRACE_ARRAY)); + if (msg != NULL) { + VarErrMsg(interp, varName, NULL, "trace array", msg); + return TCL_ERROR; + } + } + switch (index) { - case 0: { /* anymore */ + case ARRAY_ANYMORE: { ArraySearch *searchPtr; char *searchId; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, @@ -2846,11 +2909,11 @@ return TCL_ERROR; } if (notArray) { goto error; } - searchId = Tcl_GetStringFromObj(objv[3], (int *) NULL); + searchId = Tcl_GetString(objv[3]); searchPtr = ParseSearchId(interp, varPtr, varName, searchId); if (searchPtr == NULL) { return TCL_ERROR; } while (1) { @@ -2869,11 +2932,11 @@ } } Tcl_SetIntObj(resultPtr, 1); break; } - case 1: { /* donesearch */ + case ARRAY_DONESEARCH: { ArraySearch *searchPtr, *prevPtr; char *searchId; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, @@ -2881,38 +2944,38 @@ return TCL_ERROR; } if (notArray) { goto error; } - searchId = Tcl_GetStringFromObj(objv[3], (int *) NULL); + searchId = Tcl_GetString(objv[3]); searchPtr = ParseSearchId(interp, varPtr, varName, searchId); if (searchPtr == NULL) { return TCL_ERROR; } if (varPtr->searchPtr == searchPtr) { varPtr->searchPtr = searchPtr->nextPtr; } else { for (prevPtr = varPtr->searchPtr; ; - prevPtr = prevPtr->nextPtr) { + prevPtr = prevPtr->nextPtr) { if (prevPtr->nextPtr == searchPtr) { prevPtr->nextPtr = searchPtr->nextPtr; break; } } } ckfree((char *) searchPtr); break; } - case 2: { /* exists */ + case ARRAY_EXISTS: { if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "arrayName"); return TCL_ERROR; } Tcl_SetIntObj(resultPtr, !notArray); break; } - case 3: { /*get*/ + case ARRAY_GET: { Tcl_HashSearch search; Var *varPtr2; char *pattern = NULL; char *name; Tcl_Obj *namePtr, *valuePtr; @@ -2923,14 +2986,14 @@ } if (notArray) { return TCL_OK; } if (objc == 4) { - pattern = Tcl_GetStringFromObj(objv[3], (int *) NULL); + pattern = TclGetString(objv[3]); } for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { varPtr2 = (Var *) Tcl_GetHashValue(hPtr); if (TclIsVarUndefined(varPtr2)) { continue; } name = Tcl_GetHashKey(varPtr->value.tablePtr, hPtr); @@ -2959,11 +3022,11 @@ return result; } } break; } - case 4: { /* names */ + case ARRAY_NAMES: { Tcl_HashSearch search; Var *varPtr2; char *pattern = NULL; char *name; Tcl_Obj *namePtr; @@ -2974,14 +3037,14 @@ } if (notArray) { return TCL_OK; } if (objc == 4) { - pattern = Tcl_GetStringFromObj(objv[3], (int *) NULL); + pattern = Tcl_GetString(objv[3]); } for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { varPtr2 = (Var *) Tcl_GetHashValue(hPtr); if (TclIsVarUndefined(varPtr2)) { continue; } name = Tcl_GetHashKey(varPtr->value.tablePtr, hPtr); @@ -2990,17 +3053,17 @@ } namePtr = Tcl_NewStringObj(name, -1); result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr); if (result != TCL_OK) { - Tcl_DecrRefCount(namePtr); /* free unneeded name object */ + Tcl_DecrRefCount(namePtr); /* free unneeded name obj */ return result; } } break; } - case 5: { /*nextelement*/ + case ARRAY_NEXTELEMENT: { ArraySearch *searchPtr; char *searchId; Tcl_HashEntry *hPtr; if (objc != 4) { @@ -3009,11 +3072,11 @@ return TCL_ERROR; } if (notArray) { goto error; } - searchId = Tcl_GetStringFromObj(objv[3], (int *) NULL); + searchId = Tcl_GetString(objv[3]); searchPtr = ParseSearchId(interp, varPtr, varName, searchId); if (searchPtr == NULL) { return TCL_ERROR; } while (1) { @@ -3035,65 +3098,18 @@ } Tcl_SetStringObj(resultPtr, Tcl_GetHashKey(varPtr->value.tablePtr, hPtr), -1); break; } - case 6: { /*set*/ - Tcl_Obj **elemPtrs; - int listLen, i, result; - + case ARRAY_SET: { if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "arrayName list"); return TCL_ERROR; } - result = Tcl_ListObjGetElements(interp, objv[3], &listLen, - &elemPtrs); - if (result != TCL_OK) { - return result; - } - if (listLen & 1) { - Tcl_ResetResult(interp); - Tcl_AppendToObj(Tcl_GetObjResult(interp), - "list must have an even number of elements", -1); - return TCL_ERROR; - } - if (listLen > 0) { - for (i = 0; i < listLen; i += 2) { - if (Tcl_ObjSetVar2(interp, objv[2], elemPtrs[i], - elemPtrs[i+1], TCL_LEAVE_ERR_MSG) == NULL) { - result = TCL_ERROR; - break; - } - } - } else if (varPtr == NULL) { - /* - * The list is empty and the array variable doesn't - * exist yet: create the variable with an empty array - * as the value. - */ - - Tcl_Obj *namePtr, *valuePtr; - - namePtr = Tcl_NewStringObj("tempElem", -1); - valuePtr = Tcl_NewObj(); - if (Tcl_ObjSetVar2(interp, objv[2], namePtr, valuePtr, - /* flags*/ 0) == NULL) { - Tcl_DecrRefCount(namePtr); - Tcl_DecrRefCount(valuePtr); - return TCL_ERROR; - } - result = Tcl_UnsetVar2(interp, varName, "tempElem", - TCL_LEAVE_ERR_MSG); - if (result != TCL_OK) { - Tcl_DecrRefCount(namePtr); - Tcl_DecrRefCount(valuePtr); - return result; - } - } - return result; - } - case 7: { /*size*/ + return(TclArraySet(interp, objv[2], objv[3])); + } + case ARRAY_SIZE: { Tcl_HashSearch search; Var *varPtr2; int size; if (objc != 3) { @@ -3102,11 +3118,11 @@ } size = 0; if (!notArray) { for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { varPtr2 = (Var *) Tcl_GetHashValue(hPtr); if (TclIsVarUndefined(varPtr2)) { continue; } size++; @@ -3113,11 +3129,11 @@ } } Tcl_SetIntObj(resultPtr, size); break; } - case 8: { /*startsearch*/ + case ARRAY_STARTSEARCH: { ArraySearch *searchPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "arrayName"); return TCL_ERROR; @@ -3129,16 +3145,16 @@ if (varPtr->searchPtr == NULL) { searchPtr->id = 1; Tcl_AppendStringsToObj(resultPtr, "s-1-", varName, (char *) NULL); } else { - char string[20]; + char string[TCL_INTEGER_SPACE]; searchPtr->id = varPtr->searchPtr->id + 1; TclFormatInt(string, searchPtr->id); Tcl_AppendStringsToObj(resultPtr, "s-", string, "-", varName, - (char *) NULL); + (char *) NULL); } searchPtr->varPtr = varPtr; searchPtr->nextEntry = Tcl_FirstHashEntry(varPtr->value.tablePtr, &searchPtr->search); searchPtr->nextPtr = varPtr->searchPtr; @@ -3151,10 +3167,106 @@ error: Tcl_AppendStringsToObj(resultPtr, "\"", varName, "\" isn't an array", (char *) NULL); return TCL_ERROR; } + +/* + *---------------------------------------------------------------------- + * + * 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. + * + *---------------------------------------------------------------------- + */ + +int +TclArraySet(interp, arrayNameObj, arrayElemObj) + Tcl_Interp *interp; /* Current interpreter. */ + Tcl_Obj *arrayNameObj; /* The array name. */ + Tcl_Obj *arrayElemObj; /* The array elements list. If this is + * NULL, create an empty array. */ +{ + Var *varPtr, *arrayPtr; + Tcl_Obj **elemPtrs; + int result, elemLen, i; + char *varName; + + varName = TclGetString(arrayNameObj); + varPtr = TclLookupVar(interp, varName, (char *) NULL, /*flags*/ 0, + /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); + + if (arrayElemObj != NULL) { + result = Tcl_ListObjGetElements(interp, arrayElemObj, + &elemLen, &elemPtrs); + if (result != TCL_OK) { + return result; + } + if (elemLen & 1) { + Tcl_ResetResult(interp); + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "list must have an even number of elements", -1); + return TCL_ERROR; + } + if (elemLen > 0) { + for (i = 0; i < elemLen; i += 2) { + if (Tcl_ObjSetVar2(interp, arrayNameObj, elemPtrs[i], + elemPtrs[i+1], TCL_LEAVE_ERR_MSG) == NULL) { + result = TCL_ERROR; + break; + } + } + return result; + } + } + + /* + * The list is empty make sure we have an array, or create + * one if necessary. + */ + + if (varPtr != NULL) { + if (!TclIsVarUndefined(varPtr) && TclIsVarArray(varPtr)) { + /* + * Already an array, done. + */ + + return TCL_OK; + } + if (TclIsVarArrayElement(varPtr) || + !TclIsVarUndefined(varPtr)) { + /* + * Either an array element, or a scalar: lose! + */ + + VarErrMsg(interp, varName, (char *)NULL, "array set", needArray); + return TCL_ERROR; + } + } else { + /* + * Create variable for new array. + */ + + varPtr = TclLookupVar(interp, varName, (char *) NULL, 0, 0, + /*createPart1*/ 1, /*createPart2*/ 0, &arrayPtr); + } + TclSetVarArray(varPtr); + TclClearVarUndefined(varPtr); + varPtr->value.tablePtr = + (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(varPtr->value.tablePtr, TCL_STRING_KEYS); + return TCL_OK; +} /* *---------------------------------------------------------------------- * * MakeUpvar -- @@ -3193,11 +3305,11 @@ CallFrame *varFramePtr; CallFrame *savedFramePtr = NULL; /* Init. to avoid compiler warning. */ Tcl_HashTable *tablePtr; Namespace *nsPtr, *altNsPtr, *dummyNsPtr; char *tail; - int new, result; + int new; /* * 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 TclLookupVar. @@ -3232,25 +3344,22 @@ * procedure's local variable hashtable if necessary. */ varFramePtr = iPtr->varFramePtr; if ((myFlags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY)) - || (varFramePtr == NULL) - || !varFramePtr->isProcCallFrame - || (strstr(myName, "::") != NULL)) { - result = TclGetNamespaceForQualName((Tcl_Interp *) iPtr, myName, - (Namespace *) NULL, (myFlags | TCL_LEAVE_ERR_MSG), - &nsPtr, &altNsPtr, &dummyNsPtr, &tail); - if (result != TCL_OK) { - return result; - } + || (varFramePtr == NULL) + || !varFramePtr->isProcCallFrame + || (strstr(myName, "::") != NULL)) { + TclGetNamespaceForQualName((Tcl_Interp *) iPtr, myName, + (Namespace *) NULL, myFlags, &nsPtr, &altNsPtr, &dummyNsPtr, &tail); + if (nsPtr == NULL) { nsPtr = altNsPtr; } if (nsPtr == NULL) { Tcl_AppendResult((Tcl_Interp *) iPtr, "bad variable name \"", - myName, "\": unknown namespace", (char *) NULL); + myName, "\": unknown namespace", (char *) NULL); return TCL_ERROR; } /* * Check that we are not trying to create a namespace var linked to @@ -3257,11 +3366,11 @@ * 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 (otherPtr->nsPtr == NULL) { + if ((otherP2 ? arrayPtr->nsPtr : otherPtr->nsPtr) == NULL) { Tcl_AppendResult((Tcl_Interp *) iPtr, "bad variable name \"", myName, "\": upvar won't create namespace variable that refers to procedure variable", (char *) NULL); return TCL_ERROR; } @@ -3283,11 +3392,11 @@ int nameLen = strlen(myName); int i; varPtr = NULL; for (i = 0; i < localCt; i++) { - if (!localPtr->isTemp) { + if (!TclIsVarTemporary(localPtr)) { char *localName = localVarPtr->name; if ((myName[0] == localName[0]) && (nameLen == localPtr->nameLength) && (strcmp(myName, localName) == 0)) { varPtr = localVarPtr; @@ -3339,15 +3448,15 @@ if (TclIsVarUndefined(linkPtr)) { CleanupVar(linkPtr, (Var *) NULL); } } else if (!TclIsVarUndefined(varPtr)) { Tcl_AppendResult((Tcl_Interp *) iPtr, "variable \"", myName, - "\" already exists", (char *) NULL); + "\" already exists", (char *) NULL); return TCL_ERROR; } else if (varPtr->tracePtr != NULL) { Tcl_AppendResult((Tcl_Interp *) iPtr, "variable \"", myName, - "\" has traces: can't use for upvar", (char *) NULL); + "\" has traces: can't use for upvar", (char *) NULL); return TCL_ERROR; } } TclSetVarLink(varPtr); TclClearVarUndefined(varPtr); @@ -3364,11 +3473,11 @@ * This procedure 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 interp->result. + * 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 localName, so that references to * localName are redirected to the other variable like a symbolic @@ -3437,11 +3546,11 @@ * This procedure 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 interp->result. + * 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 localName, so that * references to localName are redirected to the other variable @@ -3576,11 +3685,11 @@ * Make a local variable linked to its counterpart in the global :: * namespace. */ objPtr = objv[i]; - varName = Tcl_GetStringFromObj(objPtr, (int *) NULL); + varName = TclGetString(objPtr); /* * The variable name might have a scope qualifier, but the name for * the local "link" variable must be the simple name at the tail. */ @@ -3650,11 +3759,11 @@ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { Interp *iPtr = (Interp *) interp; - char *varName, *tail; + char *varName, *tail, *cp; Var *varPtr, *arrayPtr; Tcl_Obj *varValuePtr; int i, result; for (i = 1; i < objc; i = i+2) { @@ -3661,11 +3770,11 @@ /* * Look up each variable in the current namespace context, creating * it if necessary. */ - varName = Tcl_GetStringFromObj(objv[i], (int *) NULL); + varName = TclGetString(objv[i]); varPtr = TclLookupVar(interp, varName, (char *) NULL, (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "define", /*createPart1*/ 1, /*createPart2*/ 0, &arrayPtr); if (varPtr == NULL) { return TCL_ERROR; @@ -3689,12 +3798,12 @@ * leave its value unchanged; just create the local link if * we're in a Tcl procedure). */ if (i+1 < objc) { /* a value was specified */ - varValuePtr = Tcl_ObjSetVar2(interp, objv[i], (Tcl_Obj *) NULL, - objv[i+1], (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG)); + varValuePtr = Tcl_ObjSetVar2(interp, objv[i], NULL, objv[i+1], + (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG)); if (varValuePtr == NULL) { return TCL_ERROR; } } @@ -3706,21 +3815,21 @@ if ((iPtr->varFramePtr != NULL) && iPtr->varFramePtr->isProcCallFrame) { /* * 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 = varName; *tail != '\0'; tail++) { - /* empty body */ - } - while ((tail > varName) - && ((*tail != ':') || (*(tail-1) != ':'))) { - tail--; - } - if (*tail == ':') { - tail++; + 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. @@ -3776,14 +3885,14 @@ return TCL_ERROR; } /* * Find the call frame containing each of the "other variables" to be - * linked to. FAILS IF objv[1]'s STRING REP CONTAINS NULLS. + * linked to. */ - frameSpec = Tcl_GetStringFromObj(objv[1], (int *) NULL); + frameSpec = TclGetString(objv[1]); result = TclGetFrame(interp, frameSpec, &framePtr); if (result == -1) { return TCL_ERROR; } objc -= result+1; @@ -3797,12 +3906,12 @@ * 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) { - myVarName = Tcl_GetStringFromObj(objv[1], (int *) NULL); - otherVarName = Tcl_GetStringFromObj(objv[0], (int *) NULL); + myVarName = TclGetString(objv[1]); + otherVarName = TclGetString(objv[0]); for (p = otherVarName; *p != 0; p++) { if (*p == '(') { char *openParen = p; do { @@ -3870,13 +3979,11 @@ char *part1, *part2; /* Variable's two-part name. */ int flags; /* Flags passed to trace procedures: * indicates what's happening to variable, * plus other stuff like TCL_GLOBAL_ONLY, * TCL_NAMESPACE_ONLY, and - * TCL_INTERP_DESTROYED. May also contain - * TCL_PARSE_PART1, which should not be - * passed through to callbacks. */ + * TCL_INTERP_DESTROYED. */ { register VarTrace *tracePtr; ActiveVarTrace active; char *result, *openParen, *p; Tcl_DString nameCopy; @@ -3901,15 +4008,12 @@ * string in place, because the string might get used by the * callbacks we invoke). */ copiedName = 0; - if (flags & TCL_PARSE_PART1) { - for (p = part1; ; p++) { - if (*p == 0) { - break; - } + if (part2 == NULL) { + for (p = part1; *p ; p++) { if (*p == '(') { openParen = p; do { p++; } while (*p != '\0'); @@ -3916,20 +4020,19 @@ p--; if (*p == ')') { Tcl_DStringInit(&nameCopy); Tcl_DStringAppend(&nameCopy, part1, (p-part1)); part2 = Tcl_DStringValue(&nameCopy) - + (openParen + 1 - part1); + + (openParen + 1 - part1); part2[-1] = 0; part1 = Tcl_DStringValue(&nameCopy); copiedName = 1; } break; } } } - flags &= ~TCL_PARSE_PART1; /* * Invoke traces on the array containing the variable, if relevant. */ @@ -3938,11 +4041,11 @@ iPtr->activeTracePtr = &active; if (arrayPtr != NULL) { arrayPtr->refCount++; active.varPtr = arrayPtr; for (tracePtr = arrayPtr->tracePtr; tracePtr != NULL; - tracePtr = active.nextTracePtr) { + tracePtr = active.nextTracePtr) { active.nextTracePtr = tracePtr->nextPtr; if (!(tracePtr->flags & flags)) { continue; } result = (*tracePtr->traceProc)(tracePtr->clientData, @@ -3964,11 +4067,11 @@ if (flags & TCL_TRACE_UNSETS) { flags |= TCL_TRACE_DESTROYED; } active.varPtr = varPtr; for (tracePtr = varPtr->tracePtr; tracePtr != NULL; - tracePtr = active.nextTracePtr) { + tracePtr = active.nextTracePtr) { active.nextTracePtr = tracePtr->nextPtr; if (!(tracePtr->flags & flags)) { continue; } result = (*tracePtr->traceProc)(tracePtr->clientData, @@ -4047,11 +4150,11 @@ * 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, - * interp->result contains an error message. + * the interp's result contains an error message. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -4096,11 +4199,11 @@ * Search through the list of active searches on the interpreter * to see if the desired one exists. */ for (searchPtr = varPtr->searchPtr; searchPtr != NULL; - searchPtr = searchPtr->nextPtr) { + searchPtr = searchPtr->nextPtr) { if (searchPtr->id == id) { return searchPtr; } } Tcl_AppendResult(interp, "couldn't find search \"", string, "\"", @@ -4186,11 +4289,11 @@ } else if (tablePtr == &currNsPtr->varTable) { flags |= TCL_NAMESPACE_ONLY; } for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL; - hPtr = Tcl_NextHashEntry(&search)) { + hPtr = Tcl_NextHashEntry(&search)) { varPtr = (Var *) Tcl_GetHashValue(hPtr); /* * For global/upvar variables referenced in procedures, decrement * the reference count on the variable referred to, and free @@ -4227,30 +4330,30 @@ if (varPtr->tracePtr != NULL) { objPtr = Tcl_NewObj(); Tcl_IncrRefCount(objPtr); /* until done with traces */ Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, objPtr); (void) CallTraces(iPtr, (Var *) NULL, varPtr, - Tcl_GetStringFromObj(objPtr, (int *) NULL), - (char *) NULL, flags); + Tcl_GetString(objPtr), (char *) NULL, flags); Tcl_DecrRefCount(objPtr); /* free no longer needed obj */ while (varPtr->tracePtr != NULL) { VarTrace *tracePtr = varPtr->tracePtr; varPtr->tracePtr = tracePtr->nextPtr; ckfree((char *) tracePtr); } for (activePtr = iPtr->activeTracePtr; activePtr != NULL; - activePtr = activePtr->nextPtr) { + activePtr = activePtr->nextPtr) { if (activePtr->varPtr == varPtr) { activePtr->nextTracePtr = NULL; } } } if (TclIsVarArray(varPtr)) { DeleteArray(iPtr, Tcl_GetHashKey(tablePtr, hPtr), varPtr, flags); + varPtr->value.tablePtr = NULL; } if (TclIsVarScalar(varPtr) && (varPtr->value.objPtr != NULL)) { objPtr = varPtr->value.objPtr; TclDecrRefCount(objPtr); varPtr->value.objPtr = NULL; @@ -4360,11 +4463,11 @@ VarTrace *tracePtr = varPtr->tracePtr; varPtr->tracePtr = tracePtr->nextPtr; ckfree((char *) tracePtr); } for (activePtr = iPtr->activeTracePtr; activePtr != NULL; - activePtr = activePtr->nextPtr) { + activePtr = activePtr->nextPtr) { if (activePtr->varPtr == varPtr) { activePtr->nextTracePtr = NULL; } } } @@ -4430,11 +4533,11 @@ ActiveVarTrace *activePtr; Tcl_Obj *objPtr; DeleteSearches(varPtr); for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { elPtr = (Var *) Tcl_GetHashValue(hPtr); if (TclIsVarScalar(elPtr) && (elPtr->value.objPtr != NULL)) { objPtr = elPtr->value.objPtr; TclDecrRefCount(objPtr); elPtr->value.objPtr = NULL; @@ -4448,11 +4551,11 @@ VarTrace *tracePtr = elPtr->tracePtr; elPtr->tracePtr = tracePtr->nextPtr; ckfree((char *) tracePtr); } for (activePtr = iPtr->activeTracePtr; activePtr != NULL; - activePtr = activePtr->nextPtr) { + activePtr = activePtr->nextPtr) { if (activePtr->varPtr == elPtr) { activePtr->nextTracePtr = NULL; } } } @@ -4525,11 +4628,11 @@ * * Results: * None. * * Side effects: - * Interp->result is reset to hold a message identifying the + * 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. * *---------------------------------------------------------------------- */ @@ -4542,11 +4645,11 @@ * e.g. "read", "set", or "unset". */ char *reason; /* String describing why operation failed. */ { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "can't ", operation, " \"", part1, - (char *) NULL); + (char *) NULL); if (part2 != NULL) { Tcl_AppendResult(interp, "(", part2, ")", (char *) NULL); } Tcl_AppendResult(interp, "\": ", reason, (char *) NULL); } ADDED library/auto.tcl Index: library/auto.tcl ================================================================== --- /dev/null +++ library/auto.tcl @@ -0,0 +1,553 @@ +# auto.tcl -- +# +# utility procs formerly in init.tcl dealing with auto execution +# of commands and can be auto loaded themselves. +# +# RCS: @(#) $Id: auto.tcl,v 1.1.2.8 1999/03/31 19:54:15 welch Exp $ +# +# Copyright (c) 1991-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. +# + +# auto_reset -- +# +# Destroy all cached information for auto-loading and auto-execution, +# so that the information gets recomputed the next time it's needed. +# Also delete any procedures that are listed in the auto-load index +# except those defined in this file. +# +# Arguments: +# None. + +proc auto_reset {} { + global auto_execs auto_index auto_oldpath + foreach p [info procs] { + if {[info exists auto_index($p)] && ![string match auto_* $p] + && ([lsearch -exact {unknown pkg_mkIndex tclPkgSetup + tcl_findLibrary pkg_compareExtension + tclMacPkgSearch tclPkgUnknown} $p] < 0)} { + rename $p {} + } + } + catch {unset auto_execs} + catch {unset auto_index} + catch {unset auto_oldpath} +} + +# tcl_findLibrary -- +# +# This is a utility for extensions that searches for a library directory +# using a canonical searching algorithm. A side effect is to source +# the initialization script and set a global library variable. +# +# Arguments: +# basename Prefix of the directory name, (e.g., "tk") +# version Version number of the package, (e.g., "8.0") +# patch Patchlevel of the package, (e.g., "8.0.3") +# initScript Initialization script to source (e.g., tk.tcl) +# enVarName environment variable to honor (e.g., TK_LIBRARY) +# varName Global variable to set when done (e.g., tk_library) + +proc tcl_findLibrary {basename version patch initScript enVarName varName} { + upvar #0 $varName the_library + global env errorInfo + + set dirs {} + set errors {} + + # The C application may have hardwired a path, which we honor + + if {[info exist the_library] && [string compare $the_library {}]} { + lappend dirs $the_library + } else { + + # Do the canonical search + + # 1. From an environment variable, if it exists + + if {[info exists env($enVarName)]} { + lappend dirs $env($enVarName) + } + + # 2. Relative to the Tcl library + + lappend dirs [file join [file dirname [info library]] \ + $basename$version] + + # 3. Various locations relative to the executable + # ../lib/foo1.0 (From bin directory in install hierarchy) + # ../../lib/foo1.0 (From bin/arch directory in install hierarchy) + # ../library (From unix directory in build hierarchy) + # ../../library (From unix/arch directory in build hierarchy) + # ../../foo1.0b1/library (From unix directory in parallel build hierarchy) + # ../../../foo1.0b1/library (From unix/arch directory in parallel build hierarchy) + + set parentDir [file dirname [file dirname [info nameofexecutable]]] + set grandParentDir [file dirname $parentDir] + lappend dirs [file join $parentDir lib $basename$version] + lappend dirs [file join $grandParentDir lib $basename$version] + lappend dirs [file join $parentDir library] + lappend dirs [file join $grandParentDir library] + if {![regexp {.*[ab][0-9]*} $patch ver]} { + set ver $version + } + lappend dirs [file join $grandParentDir $basename$ver library] + lappend dirs [file join [file dirname $grandParentDir] $basename$ver library] + } + foreach i $dirs { + set the_library $i + set file [file join $i $initScript] + + # source everything when in a safe interpreter because + # we have a source command, but no file exists command + + if {[interp issafe] || [file exists $file]} { + if {![catch {uplevel #0 [list source $file]} msg]} { + return + } else { + append errors "$file: $msg\n$errorInfo\n" + } + } + } + set msg "Can't find a usable $initScript in the following directories: \n" + append msg " $dirs\n\n" + append msg "$errors\n\n" + append msg "This probably means that $basename wasn't installed properly.\n" + error $msg +} + + +# ---------------------------------------------------------------------- +# auto_mkindex +# ---------------------------------------------------------------------- +# The following procedures are used to generate the tclIndex file +# from Tcl source files. They use a special safe interpreter to +# parse Tcl source files, writing out index entries as "proc" +# commands are encountered. This implementation won't work in a +# safe interpreter, since a safe interpreter can't create the +# special parser and mess with its commands. + +if {[interp issafe]} { + return ;# Stop sourcing the file here +} + +# auto_mkindex -- +# Regenerate a tclIndex file from Tcl source files. Takes as argument +# the name of the directory in which the tclIndex file is to be placed, +# followed by any number of glob patterns to use in that directory to +# locate all of the relevant files. +# +# Arguments: +# dir - Name of the directory in which to create an index. +# args - Any number of additional arguments giving the +# names of files within dir. If no additional +# are given auto_mkindex will look for *.tcl. + +proc auto_mkindex {dir args} { + global errorCode errorInfo + + if {[interp issafe]} { + error "can't generate index within safe interpreter" + } + + set oldDir [pwd] + cd $dir + set dir [pwd] + + append index "# Tcl autoload index file, version 2.0\n" + append index "# This file is generated by the \"auto_mkindex\" command\n" + append index "# and sourced to set up indexing information for one or\n" + append index "# more commands. Typically each line is a command that\n" + append index "# sets an element in the auto_index array, where the\n" + append index "# element name is the name of a command and the value is\n" + append index "# a script that loads the command.\n\n" + if {$args == ""} { + set args *.tcl + } + + auto_mkindex_parser::init + foreach file [eval glob $args] { + if {[catch {auto_mkindex_parser::mkindex $file} msg] == 0} { + append index $msg + } else { + set code $errorCode + set info $errorInfo + cd $oldDir + error $msg $info $code + } + } + auto_mkindex_parser::cleanup + + set fid [open "tclIndex" w] + puts $fid $index nonewline + close $fid + cd $oldDir +} + +# Original version of auto_mkindex that just searches the source +# code for "proc" at the beginning of the line. + +proc auto_mkindex_old {dir args} { + global errorCode errorInfo + set oldDir [pwd] + cd $dir + set dir [pwd] + append index "# Tcl autoload index file, version 2.0\n" + append index "# This file is generated by the \"auto_mkindex\" command\n" + append index "# and sourced to set up indexing information for one or\n" + append index "# more commands. Typically each line is a command that\n" + append index "# sets an element in the auto_index array, where the\n" + append index "# element name is the name of a command and the value is\n" + append index "# a script that loads the command.\n\n" + if {$args == ""} { + set args *.tcl + } + foreach file [eval glob $args] { + set f "" + set error [catch { + set f [open $file] + while {[gets $f line] >= 0} { + if {[regexp {^proc[ ]+([^ ]*)} $line match procName]} { + set procName [lindex [auto_qualify $procName "::"] 0] + append index "set [list auto_index($procName)]" + append index " \[list source \[file join \$dir [list $file]\]\]\n" + } + } + close $f + } msg] + if {$error} { + set code $errorCode + set info $errorInfo + catch {close $f} + cd $oldDir + error $msg $info $code + } + } + set f "" + set error [catch { + set f [open tclIndex w] + puts $f $index nonewline + close $f + cd $oldDir + } msg] + if {$error} { + set code $errorCode + set info $errorInfo + catch {close $f} + cd $oldDir + error $msg $info $code + } +} + +# Create a safe interpreter that can be used to parse Tcl source files +# generate a tclIndex file for autoloading. This interp contains +# commands for things that need index entries. Each time a command +# is executed, it writes an entry out to the index file. + +namespace eval auto_mkindex_parser { + variable parser "" ;# parser used to build index + variable index "" ;# maintains index as it is built + variable scriptFile "" ;# name of file being processed + variable contextStack "" ;# stack of namespace scopes + variable imports "" ;# keeps track of all imported cmds + variable initCommands "" ;# list of commands that create aliases + + proc init {} { + variable parser + variable initCommands + + if {![interp issafe]} { + set parser [interp create -safe] + $parser hide info + $parser hide rename + $parser hide proc + $parser hide namespace + $parser hide eval + $parser hide puts + $parser invokehidden namespace delete :: + $parser invokehidden proc unknown {args} {} + + # We'll need access to the "namespace" command within the + # interp. Put it back, but move it out of the way. + + $parser expose namespace + $parser invokehidden rename namespace _%@namespace + $parser expose eval + $parser invokehidden rename eval _%@eval + + # Install all the registered psuedo-command implementations + + foreach cmd $initCommands { + eval $cmd + } + } + } + proc cleanup {} { + variable parser + interp delete $parser + unset parser + } +} + +# auto_mkindex_parser::mkindex -- +# +# Used by the "auto_mkindex" command to create a "tclIndex" file for +# the given Tcl source file. Executes the commands in the file, and +# handles things like the "proc" command by adding an entry for the +# index file. Returns a string that represents the index file. +# +# Arguments: +# file Name of Tcl source file to be indexed. + +proc auto_mkindex_parser::mkindex {file} { + variable parser + variable index + variable scriptFile + variable contextStack + variable imports + + set scriptFile $file + + set fid [open $file] + set contents [read $fid] + close $fid + + # There is one problem with sourcing files into the safe + # interpreter: references like "$x" will fail since code is not + # really being executed and variables do not really exist. + # Be careful to escape all naked "$" before evaluating. + + regsub -all {([^\$])\$([^\$])} $contents {\1\\$\2} contents + + set index "" + set contextStack "" + set imports "" + + $parser eval $contents + + foreach name $imports { + catch {$parser eval [list _%@namespace forget $name]} + } + return $index +} + +# auto_mkindex_parser::hook command +# +# Registers a Tcl command to evaluate when initializing the +# slave interpreter used by the mkindex parser. +# The command is evaluated in the master interpreter, and can +# use the variable auto_mkindex_parser::parser to get to the slave + +proc auto_mkindex_parser::hook {cmd} { + variable initCommands + + lappend initCommands $cmd +} + +# auto_mkindex_parser::slavehook command +# +# Registers a Tcl command to evaluate when initializing the +# slave interpreter used by the mkindex parser. +# The command is evaluated in the slave interpreter. + +proc auto_mkindex_parser::slavehook {cmd} { + variable initCommands + + # The $parser variable is defined to be the name of the + # slave interpreter when this command is used later. + + lappend initCommands "\$parser eval [list $cmd]" +} + +# auto_mkindex_parser::command -- +# +# Registers a new command with the "auto_mkindex_parser" interpreter +# that parses Tcl files. These commands are fake versions of things +# like the "proc" command. When you execute them, they simply write +# out an entry to a "tclIndex" file for auto-loading. +# +# This procedure allows extensions to register their own commands +# with the auto_mkindex facility. For example, a package like +# [incr Tcl] might register a "class" command so that class definitions +# could be added to a "tclIndex" file for auto-loading. +# +# Arguments: +# name Name of command recognized in Tcl files. +# arglist Argument list for command. +# body Implementation of command to handle indexing. + +proc auto_mkindex_parser::command {name arglist body} { + hook [list auto_mkindex_parser::commandInit $name $arglist $body] +} + +# auto_mkindex_parser::commandInit -- +# +# This does the actual work set up by auto_mkindex_parser::command +# This is called when the interpreter used by the parser is created. +# +# Arguments: +# name Name of command recognized in Tcl files. +# arglist Argument list for command. +# body Implementation of command to handle indexing. + +proc auto_mkindex_parser::commandInit {name arglist body} { + variable parser + + set ns [namespace qualifiers $name] + set tail [namespace tail $name] + if {$ns == ""} { + set fakeName "[namespace current]::_%@fake_$tail" + } else { + set fakeName "_%@fake_$name" + regsub -all {::} $fakeName "_" fakeName + set fakeName "[namespace current]::$fakeName" + } + proc $fakeName $arglist $body + + # YUK! Tcl won't let us alias fully qualified command names, + # so we can't handle names like "::itcl::class". Instead, + # we have to build procs with the fully qualified names, and + # have the procs point to the aliases. + + if {[regexp {::} $name]} { + set exportCmd [list _%@namespace export [namespace tail $name]] + $parser eval [list _%@namespace eval $ns $exportCmd] + + # The following proc definition does not work if you + # want to tolerate space or something else diabolical + # in the procedure name, (i.e., space in $alias) + # The following does not work: + # "_%@eval {$alias} \$args" + # because $alias gets concat'ed to $args. + # The following does not work because $cmd is somehow undefined + # "set cmd {$alias} \; _%@eval {\$cmd} \$args" + # A gold star to someone that can make test + # autoMkindex-3.3 work properly + + set alias [namespace tail $fakeName] + $parser invokehidden proc $name {args} "_%@eval {$alias} \$args" + $parser alias $alias $fakeName + } else { + $parser alias $name $fakeName + } + return +} + +# auto_mkindex_parser::fullname -- +# Used by commands like "proc" within the auto_mkindex parser. +# Returns the qualified namespace name for the "name" argument. +# If the "name" does not start with "::", elements are added from +# the current namespace stack to produce a qualified name. Then, +# the name is examined to see whether or not it should really be +# qualified. If the name has more than the leading "::", it is +# returned as a fully qualified name. Otherwise, it is returned +# as a simple name. That way, the Tcl autoloader will recognize +# it properly. +# +# Arguments: +# name - Name that is being added to index. + +proc auto_mkindex_parser::fullname {name} { + variable contextStack + + if {![string match ::* $name]} { + foreach ns $contextStack { + set name "${ns}::$name" + if {[string match ::* $name]} { + break + } + } + } + + if {[namespace qualifiers $name] == ""} { + return [namespace tail $name] + } elseif {![string match ::* $name]} { + return "::$name" + } + return $name +} + +# Register all of the procedures for the auto_mkindex parser that +# will build the "tclIndex" file. + +# AUTO MKINDEX: proc name arglist body +# Adds an entry to the auto index list for the given procedure name. + +auto_mkindex_parser::command proc {name args} { + variable index + variable scriptFile + append index [list set auto_index([fullname $name])] \ + " \[list source \[file join \$dir [list $scriptFile]\]\]\n" +} + +# Conditionally add support for Tcl byte code files. There are some +# tricky details here. First, we need to get the tbcload library +# initialized in the current interpreter. We cannot load tbcload into the +# slave until we have done so because it needs access to the tcl_patchLevel +# variable. Second, because the package index file may defer loading the +# library until we invoke a command, we need to explicitly invoke auto_load +# to force it to be loaded. This should be a noop if the package has +# already been loaded + +auto_mkindex_parser::hook { + if {![catch {package require tbcload}]} { + if {[info commands tbcload::bcproc] == ""} { + auto_load tbcload::bcproc + } + load {} tbcload $auto_mkindex_parser::parser + + # AUTO MKINDEX: tbcload::bcproc name arglist body + # Adds an entry to the auto index list for the given pre-compiled + # procedure name. + + auto_mkindex_parser::commandInit tbcload::bcproc {name args} { + variable index + variable scriptFile + append index [list set auto_index([fullname $name])] \ + " \[list source \[file join \$dir [list $scriptFile]\]\]\n" + } + } +} + +# AUTO MKINDEX: namespace eval name command ?arg arg...? +# Adds the namespace name onto the context stack and evaluates the +# associated body of commands. +# +# AUTO MKINDEX: namespace import ?-force? pattern ?pattern...? +# Performs the "import" action in the parser interpreter. This is +# important for any commands contained in a namespace that affect +# the index. For example, a script may say "itcl::class ...", +# or it may import "itcl::*" and then say "class ...". This +# procedure does the import operation, but keeps track of imported +# patterns so we can remove the imports later. + +auto_mkindex_parser::command namespace {op args} { + switch -- $op { + eval { + variable parser + variable contextStack + + set name [lindex $args 0] + set args [lrange $args 1 end] + + set contextStack [linsert $contextStack 0 $name] + $parser eval [list _%@namespace eval $name] $args + set contextStack [lrange $contextStack 1 end] + } + import { + variable parser + variable imports + foreach pattern $args { + if {$pattern != "-force"} { + lappend imports $pattern + } + } + catch {$parser eval "_%@namespace import $args"} + } + } +} + +return ADDED library/encoding/ascii.enc Index: library/encoding/ascii.enc ================================================================== --- /dev/null +++ library/encoding/ascii.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/big5.enc Index: library/encoding/big5.enc ================================================================== --- /dev/null +++ library/encoding/big5.enc @@ -0,0 +1,1516 @@ +# 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 ADDED library/encoding/cp1250.enc Index: library/encoding/cp1250.enc ================================================================== --- /dev/null +++ library/encoding/cp1250.enc @@ -0,0 +1,20 @@ +# Encoding file: cp1250, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00800081201A0083201E2026202020210088203001602039015A0164017D0179 +009020182019201C201D202220132014009821220161203A015B0165017E017A +00A002C702D8014100A4010400A600A700A800A9015E00AB000000AD00AE017B +00B000B102DB014200B400B500B600B700B80105015F00BB013D02DD013E017C +015400C100C2010200C40139010600C7010C00C9011800CB011A00CD00CE010E +01100143014700D300D4015000D600D70158016E00DA017000DC00DD016200DF +015500E100E2010300E4013A010700E7010D00E9011900EB011B00ED00EE010F +01110144014800F300F4015100F600F70159016F00FA017100FC00FD016302D9 ADDED library/encoding/cp1251.enc Index: library/encoding/cp1251.enc ================================================================== --- /dev/null +++ library/encoding/cp1251.enc @@ -0,0 +1,20 @@ +# Encoding file: cp1251, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +04020403201A0453201E2026202020210088203004092039040A040C040B040F +045220182019201C201D202220132014009821220459203A045A045C045B045F +00A0040E045E040800A4049000A600A7040100A9040400AB00AC00AD00AE0407 +00B000B104060456049100B500B600B704512116045400BB0458040504550457 +0410041104120413041404150416041704180419041A041B041C041D041E041F +0420042104220423042404250426042704280429042A042B042C042D042E042F +0430043104320433043404350436043704380439043A043B043C043D043E043F +0440044104420443044404450446044704480449044A044B044C044D044E044F ADDED library/encoding/cp1252.enc Index: library/encoding/cp1252.enc ================================================================== --- /dev/null +++ library/encoding/cp1252.enc @@ -0,0 +1,20 @@ +# Encoding file: cp1252, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00800081201A0192201E20262020202102C62030016020390152008D008E008F +009020182019201C201D20222013201402DC21220161203A0153009D009E0178 +00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF +00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF +00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF +00D000D100D200D300D400D500D600D700D800D900DA00DB00DC00DD00DE00DF +00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF +00F000F100F200F300F400F500F600F700F800F900FA00FB00FC00FD00FE00FF ADDED library/encoding/cp1253.enc Index: library/encoding/cp1253.enc ================================================================== --- /dev/null +++ library/encoding/cp1253.enc @@ -0,0 +1,20 @@ +# Encoding file: cp1253, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00800081201A0192201E20262020202100882030008A2039008C008D008E008F +009020182019201C201D20222013201400982122009A203A009C009D009E009F +00A00385038600A300A400A500A600A700A800A9000000AB00AC00AD00AE2015 +00B000B100B200B3038400B500B600B703880389038A00BB038C00BD038E038F +0390039103920393039403950396039703980399039A039B039C039D039E039F +03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF +03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF +03C003C103C203C303C403C503C603C703C803C903CA03CB03CC03CD03CE0000 ADDED library/encoding/cp1254.enc Index: library/encoding/cp1254.enc ================================================================== --- /dev/null +++ library/encoding/cp1254.enc @@ -0,0 +1,20 @@ +# Encoding file: cp1254, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00800081201A0192201E20262020202102C62030016020390152008D008E008F +009020182019201C201D20222013201402DC21220161203A0153009D009E0178 +00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF +00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF +00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF +011E00D100D200D300D400D500D600D700D800D900DA00DB00DC0130015E00DF +00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF +011F00F100F200F300F400F500F600F700F800F900FA00FB00FC0131015F00FF ADDED library/encoding/cp1255.enc Index: library/encoding/cp1255.enc ================================================================== --- /dev/null +++ library/encoding/cp1255.enc @@ -0,0 +1,20 @@ +# Encoding file: cp1255, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00800081201A0192201E20262020202102C62030008A2039008C008D008E008F +009020182019201C201D20222013201402DC2122009A203A009C009D009E009F +00A0000000A200A320AA00A500A600A700A800A9000000AB00AC00AD00AE00AF +00B000B100B200B300B400B500B600B7000000B9000000BB00BC00BD00BE0000 +05B005B105B205B305B405B505B605B705B805B905BA05BB05BC05BD05BE05BF +05C005C105C205C305F005F105F2000000000000000000000000000000000000 +05D005D105D205D305D405D505D605D705D805D905DA05DB05DC05DD05DE05DF +05E005E105E205E305E405E505E605E705E805E905EA00000000200E200F0000 ADDED library/encoding/cp1256.enc Index: library/encoding/cp1256.enc ================================================================== --- /dev/null +++ library/encoding/cp1256.enc @@ -0,0 +1,20 @@ +# Encoding file: cp1256, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +0080067E201A0192201E20262020202102C62030008A2039015206860698008F +06AF20182019201C201D20222013201400982122009A203A0153200C200D009F +00A0060C00A200A300A400A500A600A700A800A9000000AB00AC00AD00AE00AF +00B000B100B200B300B400B500B600B700B800B9061B00BB00BC00BD00BE061F +0000062106220623062406250626062706280629062A062B062C062D062E062F +063006310632063306340635063600D7063706380639063A0640064106420643 +00E0064400E2064506460647064800E700E800E900EA00EB0649064A00EE00EF +064B064C064D064E00F4064F065000F7065100F9065200FB00FC200E200F0000 ADDED library/encoding/cp1257.enc Index: library/encoding/cp1257.enc ================================================================== --- /dev/null +++ library/encoding/cp1257.enc @@ -0,0 +1,20 @@ +# Encoding file: cp1257, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00800081201A0083201E20262020202100882030008A2039008C00A802C700B8 +009020182019201C201D20222013201400982122009A203A009C00AF02DB009F +00A0000000A200A300A4000000A600A700D800A9015600AB00AC00AD00AE00C6 +00B000B100B200B300B400B500B600B700F800B9015700BB00BC00BD00BE00E6 +0104012E0100010600C400C501180112010C00C90179011601220136012A013B +01600143014500D3014C00D500D600D701720141015A016A00DC017B017D00DF +0105012F0101010700E400E501190113010D00E9017A011701230137012B013C +01610144014600F3014D00F500F600F701730142015B016B00FC017C017E02D9 ADDED library/encoding/cp1258.enc Index: library/encoding/cp1258.enc ================================================================== --- /dev/null +++ library/encoding/cp1258.enc @@ -0,0 +1,20 @@ +# Encoding file: cp1258, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00800081201A0192201E20262020202102C62030008A20390152008D008E008F +009020182019201C201D20222013201402DC2122009A203A0153009D009E0178 +00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF +00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF +00C000C100C2010200C400C500C600C700C800C900CA00CB034000CD00CE00CF +011000D1030900D300D401A000D600D700D800D900DA00DB00DC01AF030300DF +00E000E100E2010300E400E500E600E700E800E900EA00EB034100ED00EE00EF +011100F1032300F300F401A100F600F700F800F900FA00FB00FC01B020AB00FF ADDED library/encoding/cp437.enc Index: library/encoding/cp437.enc ================================================================== --- /dev/null +++ library/encoding/cp437.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp737.enc Index: library/encoding/cp737.enc ================================================================== --- /dev/null +++ library/encoding/cp737.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp775.enc Index: library/encoding/cp775.enc ================================================================== --- /dev/null +++ library/encoding/cp775.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp850.enc Index: library/encoding/cp850.enc ================================================================== --- /dev/null +++ library/encoding/cp850.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp852.enc Index: library/encoding/cp852.enc ================================================================== --- /dev/null +++ library/encoding/cp852.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp855.enc Index: library/encoding/cp855.enc ================================================================== --- /dev/null +++ library/encoding/cp855.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp857.enc Index: library/encoding/cp857.enc ================================================================== --- /dev/null +++ library/encoding/cp857.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp860.enc Index: library/encoding/cp860.enc ================================================================== --- /dev/null +++ library/encoding/cp860.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp861.enc Index: library/encoding/cp861.enc ================================================================== --- /dev/null +++ library/encoding/cp861.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp862.enc Index: library/encoding/cp862.enc ================================================================== --- /dev/null +++ library/encoding/cp862.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp863.enc Index: library/encoding/cp863.enc ================================================================== --- /dev/null +++ library/encoding/cp863.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp864.enc Index: library/encoding/cp864.enc ================================================================== --- /dev/null +++ library/encoding/cp864.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp865.enc Index: library/encoding/cp865.enc ================================================================== --- /dev/null +++ library/encoding/cp865.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp866.enc Index: library/encoding/cp866.enc ================================================================== --- /dev/null +++ library/encoding/cp866.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp869.enc Index: library/encoding/cp869.enc ================================================================== --- /dev/null +++ library/encoding/cp869.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/cp874.enc Index: library/encoding/cp874.enc ================================================================== --- /dev/null +++ library/encoding/cp874.enc @@ -0,0 +1,20 @@ +# Encoding file: cp874, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +0080008100820083008420260086008700880089008A008B008C008D008E008F +009020182019201C201D20222013201400980099009A009B009C009D009E009F +00A00E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F +0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F +0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F +0E300E310E320E330E340E350E360E370E380E390E3A00000000000000000E3F +0E400E410E420E430E440E450E460E470E480E490E4A0E4B0E4C0E4D0E4E0E4F +0E500E510E520E530E540E550E560E570E580E590E5A0E5B0000000000000000 ADDED library/encoding/cp932.enc Index: library/encoding/cp932.enc ================================================================== --- /dev/null +++ library/encoding/cp932.enc @@ -0,0 +1,785 @@ +# 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 ADDED library/encoding/cp936.enc Index: library/encoding/cp936.enc ================================================================== --- /dev/null +++ library/encoding/cp936.enc @@ -0,0 +1,2162 @@ +# Encoding file: cp936, multi-byte +M +003F 0 127 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +0080000000000000000000000000000000000000000000000000000000000000 +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 ADDED library/encoding/cp949.enc Index: library/encoding/cp949.enc ================================================================== --- /dev/null +++ library/encoding/cp949.enc @@ -0,0 +1,2128 @@ +# 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 +211633C7212233C233D821210000000000000000000000000000000000000000 +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 ADDED library/encoding/cp950.enc Index: library/encoding/cp950.enc ================================================================== --- /dev/null +++ library/encoding/cp950.enc @@ -0,0 +1,1499 @@ +# 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 +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 +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 ADDED library/encoding/dingbats.enc Index: library/encoding/dingbats.enc ================================================================== --- /dev/null +++ library/encoding/dingbats.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/euc-cn.enc Index: library/encoding/euc-cn.enc ================================================================== --- /dev/null +++ library/encoding/euc-cn.enc @@ -0,0 +1,1397 @@ +# 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 ADDED library/encoding/euc-jp.enc Index: library/encoding/euc-jp.enc ================================================================== --- /dev/null +++ library/encoding/euc-jp.enc @@ -0,0 +1,1346 @@ +# 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 ADDED library/encoding/euc-kr.enc Index: library/encoding/euc-kr.enc ================================================================== --- /dev/null +++ library/encoding/euc-kr.enc @@ -0,0 +1,1533 @@ +# 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 ADDED library/encoding/gb12345.enc Index: library/encoding/gb12345.enc ================================================================== --- /dev/null +++ library/encoding/gb12345.enc @@ -0,0 +1,1414 @@ +# 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 ADDED library/encoding/gb1988.enc Index: library/encoding/gb1988.enc ================================================================== --- /dev/null +++ library/encoding/gb1988.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/gb2312.enc Index: library/encoding/gb2312.enc ================================================================== --- /dev/null +++ library/encoding/gb2312.enc @@ -0,0 +1,1380 @@ +# 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 ADDED library/encoding/iso2022-jp.enc Index: library/encoding/iso2022-jp.enc ================================================================== --- /dev/null +++ library/encoding/iso2022-jp.enc @@ -0,0 +1,12 @@ +# Encoding file: iso2022-jp, escape-driven +E +name iso2022-jp +init {} +final {} +iso8859-1 \x1b(B +jis0201 \x1b(J +jis0208 \x1b$@ +jis0208 \x1b$B +jis0212 \x1b$(D +gb2312 \x1b$A +ksc5601 \x1b$(C ADDED library/encoding/iso2022-kr.enc Index: library/encoding/iso2022-kr.enc ================================================================== --- /dev/null +++ library/encoding/iso2022-kr.enc @@ -0,0 +1,7 @@ +# Encoding file: iso2022-kr, escape-driven +E +name iso2022-kr +init \x1b$)C +final {} +iso8859-1 \x0f +ksc5601 \x0e ADDED library/encoding/iso2022.enc Index: library/encoding/iso2022.enc ================================================================== --- /dev/null +++ library/encoding/iso2022.enc @@ -0,0 +1,16 @@ +# Encoding file: iso2022, escape-driven +E +name iso2022 +init {} +final {} +iso8859-1 \x1b(B +jis0201 \x1b(J +gb1988 \x1b(T +jis0208 \x1b$@ +jis0208 \x1b$B +jis0212 \x1b$(D +gb2312 \x1b$A +ksc5601 \x1b$(C +jis0208 \x1b&@\x1b$B + + ADDED library/encoding/iso8859-1.enc Index: library/encoding/iso8859-1.enc ================================================================== --- /dev/null +++ library/encoding/iso8859-1.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/iso8859-2.enc Index: library/encoding/iso8859-2.enc ================================================================== --- /dev/null +++ library/encoding/iso8859-2.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/iso8859-3.enc Index: library/encoding/iso8859-3.enc ================================================================== --- /dev/null +++ library/encoding/iso8859-3.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/iso8859-4.enc Index: library/encoding/iso8859-4.enc ================================================================== --- /dev/null +++ library/encoding/iso8859-4.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/iso8859-5.enc Index: library/encoding/iso8859-5.enc ================================================================== --- /dev/null +++ library/encoding/iso8859-5.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/iso8859-6.enc Index: library/encoding/iso8859-6.enc ================================================================== --- /dev/null +++ library/encoding/iso8859-6.enc @@ -0,0 +1,20 @@ +# Encoding file: iso8859-6, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0660066106620663066406650666066706680669003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +0080008100820083008400850086008700880089008A008B008C008D008E008F +0090009100920093009400950096009700980099009A009B009C009D009E009F +00A000000000000000A40000000000000000000000000000060C00AD00000000 +00000000000000000000000000000000000000000000061B000000000000061F +0000062106220623062406250626062706280629062A062B062C062D062E062F +0630063106320633063406350636063706380639063A00000000000000000000 +0640064106420643064406450646064706480649064A064B064C064D064E064F +0650065106520000000000000000000000000000000000000000000000000000 ADDED library/encoding/iso8859-7.enc Index: library/encoding/iso8859-7.enc ================================================================== --- /dev/null +++ library/encoding/iso8859-7.enc @@ -0,0 +1,20 @@ +# Encoding file: iso8859-7, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +0080008100820083008400850086008700880089008A008B008C008D008E008F +0090009100920093009400950096009700980099009A009B009C009D009E009F +00A002BD02BC00A30000000000A600A700A800A9000000AB00AC00AD00002015 +00B000B100B200B303840385038600B703880389038A00BB038C00BD038E038F +0390039103920393039403950396039703980399039A039B039C039D039E039F +03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF +03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF +03C003C103C203C303C403C503C603C703C803C903CA03CB03CC03CD03CE0000 ADDED library/encoding/iso8859-8.enc Index: library/encoding/iso8859-8.enc ================================================================== --- /dev/null +++ library/encoding/iso8859-8.enc @@ -0,0 +1,20 @@ +# Encoding file: iso8859-8, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +0080008100820083008400850086008700880089008A008B008C008D008E008F +0090009100920093009400950096009700980099009A009B009C009D009E009F +00A0000000A200A300A400A500A600A700A800A900D700AB00AC00AD00AE203E +00B000B100B200B300B400B500B600B700B800B900F700BB00BC00BD00BE0000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000002017 +05D005D105D205D305D405D505D605D705D805D905DA05DB05DC05DD05DE05DF +05E005E105E205E305E405E505E605E705E805E905EA00000000000000000000 ADDED library/encoding/iso8859-9.enc Index: library/encoding/iso8859-9.enc ================================================================== --- /dev/null +++ library/encoding/iso8859-9.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/jis0201.enc Index: library/encoding/jis0201.enc ================================================================== --- /dev/null +++ library/encoding/jis0201.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/jis0208.enc Index: library/encoding/jis0208.enc ================================================================== --- /dev/null +++ library/encoding/jis0208.enc @@ -0,0 +1,1312 @@ +# 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 ADDED library/encoding/jis0212.enc Index: library/encoding/jis0212.enc ================================================================== --- /dev/null +++ library/encoding/jis0212.enc @@ -0,0 +1,1159 @@ +# 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 ADDED library/encoding/ksc5601.enc Index: library/encoding/ksc5601.enc ================================================================== --- /dev/null +++ library/encoding/ksc5601.enc @@ -0,0 +1,1516 @@ +# 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 ADDED library/encoding/macCentEuro.enc Index: library/encoding/macCentEuro.enc ================================================================== --- /dev/null +++ library/encoding/macCentEuro.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/macCroatian.enc Index: library/encoding/macCroatian.enc ================================================================== --- /dev/null +++ library/encoding/macCroatian.enc @@ -0,0 +1,20 @@ +# Encoding file: macCroatian, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00C400C500C700C900D100D600DC00E100E000E200E400E300E500E700E900E8 +00EA00EB00ED00EC00EE00EF00F100F300F200F400F600F500FA00F900FB00FC +202000B000A200A300A7202200B600DF00AE0160212200B400A82260017D00D8 +221E00B122642265220600B522022211220F0161222B00AA00BA2126017E00F8 +00BF00A100AC221A01922248010600AB010C202600A000C000C300D501520153 +01102014201C201D2018201900F725CAF8FF00A9204400A42039203A00C600BB +201300B7201A201E203000C2010700C1010D00C800CD00CE00CF00CC00D300D4 +011100D200DA00DB00D9013102C602DC00AF03C000CB02DA00B800CA00E602C7 ADDED library/encoding/macCyrillic.enc Index: library/encoding/macCyrillic.enc ================================================================== --- /dev/null +++ library/encoding/macCyrillic.enc @@ -0,0 +1,20 @@ +# Encoding file: macCyrillic, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +0410041104120413041404150416041704180419041A041B041C041D041E041F +0420042104220423042404250426042704280429042A042B042C042D042E042F +202000B000A200A300A7202200B6040600AE00A9212204020452226004030453 +221E00B122642265045600B522020408040404540407045704090459040A045A +0458040500AC221A01922248220600AB00BB202600A0040B045B040C045C0455 +20132014201C201D2018201900F7201E040E045E040F045F211604010451044F +0430043104320433043404350436043704380439043A043B043C043D043E043F +0440044104420443044404450446044704480449044A044B044C044D044E00A4 ADDED library/encoding/macDingbats.enc Index: library/encoding/macDingbats.enc ================================================================== --- /dev/null +++ library/encoding/macDingbats.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/macGreek.enc Index: library/encoding/macGreek.enc ================================================================== --- /dev/null +++ library/encoding/macGreek.enc @@ -0,0 +1,20 @@ +# Encoding file: macGreek, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00C400B900B200C900B300D600DC038500E000E200E4038400A800E700E900E8 +00EA00EB00A3212200EE00EF202200BD203000F400F600A600AD00F900FB00FC +2020039303940398039B039E03A000DF00AE00A903A303AA00A7226000B00387 +039100B12264226500A503920395039603970399039A039C03A603AB03A803A9 +03AC039D00AC039F03A1224803A400AB00BB202600A003A503A7038603880153 +20132015201C201D2018201900F70389038A038C038E03AD03AE03AF03CC038F +03CD03B103B203C803B403B503C603B303B703B903BE03BA03BB03BC03BD03BF +03C003CE03C103C303C403B803C903C203C703C503B603CA03CB039003B0F8A0 ADDED library/encoding/macIceland.enc Index: library/encoding/macIceland.enc ================================================================== --- /dev/null +++ library/encoding/macIceland.enc @@ -0,0 +1,20 @@ +# Encoding file: macIceland, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00C400C500C700C900D100D600DC00E100E000E200E400E300E500E700E900E8 +00EA00EB00ED00EC00EE00EF00F100F300F200F400F600F500FA00F900FB00FC +00DD00B000A200A300A7202200B600DF00AE00A9212200B400A8226000C600D8 +221E00B12264226500A500B522022211220F03C0222B00AA00BA212600E600F8 +00BF00A100AC221A01922248220600AB00BB202600A000C000C300D501520153 +20132014201C201D2018201900F725CA00FF0178204400A400D000F000DE00FE +00FD00B7201A201E203000C200CA00C100CB00C800CD00CE00CF00CC00D300D4 +F8FF00D200DA00DB00D9013102C602DC00AF02D802D902DA00B802DD02DB02C7 ADDED library/encoding/macJapan.enc Index: library/encoding/macJapan.enc ================================================================== --- /dev/null +++ library/encoding/macJapan.enc @@ -0,0 +1,785 @@ +# 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 ADDED library/encoding/macRoman.enc Index: library/encoding/macRoman.enc ================================================================== --- /dev/null +++ library/encoding/macRoman.enc @@ -0,0 +1,20 @@ +# Encoding file: macRoman, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00C400C500C700C900D100D600DC00E100E000E200E400E300E500E700E900E8 +00EA00EB00ED00EC00EE00EF00F100F300F200F400F600F500FA00F900FB00FC +202000B000A200A300A7202200B600DF00AE00A9212200B400A8226000C600D8 +221E00B12264226500A500B522022211220F03C0222B00AA00BA212600E600F8 +00BF00A100AC221A01922248220600AB00BB202600A000C000C300D501520153 +20132014201C201D2018201900F725CA00FF0178204400A42039203AFB01FB02 +202100B7201A201E203000C200CA00C100CB00C800CD00CE00CF00CC00D300D4 +F8FF00D200DA00DB00D9013102C602DC00AF02D802D902DA00B802DD02DB02C7 ADDED library/encoding/macRomania.enc Index: library/encoding/macRomania.enc ================================================================== --- /dev/null +++ library/encoding/macRomania.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/macThai.enc Index: library/encoding/macThai.enc ================================================================== --- /dev/null +++ library/encoding/macThai.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/macTurkish.enc Index: library/encoding/macTurkish.enc ================================================================== --- /dev/null +++ library/encoding/macTurkish.enc @@ -0,0 +1,20 @@ +# Encoding file: macTurkish, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00C400C500C700C900D100D600DC00E100E000E200E400E300E500E700E900E8 +00EA00EB00ED00EC00EE00EF00F100F300F200F400F600F500FA00F900FB00FC +202000B000A200A300A7202200B600DF00AE00A9212200B400A8226000C600D8 +221E00B12264226500A500B522022211220F03C0222B00AA00BA212600E600F8 +00BF00A100AC221A01922248220600AB00BB202600A000C000C300D501520153 +20132014201C201D2018201900F725CA00FF0178011E011F01300131015E015F +202100B7201A201E203000C200CA00C100CB00C800CD00CE00CF00CC00D300D4 +F8FF00D200DA00DB00D9F8A002C602DC00AF02D802D902DA00B802DD02DB02C7 ADDED library/encoding/macUkraine.enc Index: library/encoding/macUkraine.enc ================================================================== --- /dev/null +++ library/encoding/macUkraine.enc @@ -0,0 +1,20 @@ +# 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 ADDED library/encoding/shiftjis.enc Index: library/encoding/shiftjis.enc ================================================================== --- /dev/null +++ library/encoding/shiftjis.enc @@ -0,0 +1,683 @@ +# 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 ADDED library/encoding/symbol.enc Index: library/encoding/symbol.enc ================================================================== --- /dev/null +++ library/encoding/symbol.enc @@ -0,0 +1,20 @@ +# 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 Index: library/history.tcl ================================================================== --- library/history.tcl +++ library/history.tcl @@ -1,10 +1,10 @@ # history.tcl -- # # Implementation of the history command. # -# SCCS: @(#) history.tcl 1.7 97/08/07 16:45:50 +# RCS: @(#) $Id: history.tcl,v 1.1.2.2 1998/09/24 23:59:05 stanton Exp $ # # 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. @@ -17,11 +17,11 @@ # 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] { + if {![info exists history]} { array set history { nextid 0 keep 20 oldest -20 } @@ -116,11 +116,11 @@ } if {$len == 1} { return [tcl::HistKeep] } else { set limit [lindex $args 1] - if {[catch {expr $limit}] || ($limit < 0)} { + if {[catch {expr {~$limit}}] || ($limit < 0)} { return -code error "illegal keep count \"$limit\"" } return [tcl::HistKeep $limit] } } @@ -130,11 +130,11 @@ return -code error "wrong # args: should be \"history nextid\"" } if {![string match $key* nextid]} { return -code error "bad option \"$key\": must be $options" } - return [expr $tcl::history(nextid) + 1] + return [expr {$tcl::history(nextid) + 1}] } r* { # history redo if {$len > 2} { return -code error "wrong # args: should be \"history redo ?event?\"" @@ -194,11 +194,11 @@ variable history if {[string length $limit] == 0} { return $history(keep) } else { set oldold $history(oldest) - set history(oldest) [expr $history(nextid) - $limit] + set history(oldest) [expr {$history(nextid) - $limit}] for {} {$oldold <= $history(oldest)} {incr oldold} { if {[info exists history($oldold)]} {unset history($oldold)} } set history(keep) $limit } @@ -239,17 +239,17 @@ # A formatted history list proc tcl::HistInfo {{num {}}} { variable history if {$num == {}} { - set num [expr $history(keep) + 1] + set num [expr {$history(keep) + 1}] } set result {} set newline "" - for {set i [expr $history(nextid) - $num + 1]} \ + for {set i [expr {$history(nextid) - $num + 1}]} \ {$i <= $history(nextid)} {incr i} { - if ![info exists history($i)] { + if {![info exists history($i)]} { continue } set cmd [string trimright $history($i) \ \n] regsub -all \n $cmd "\n\t" cmd append result $newline[format "%6d %s" $i $cmd] @@ -302,11 +302,11 @@ # Results: # The index into history, or an error if the index didn't match. proc tcl::HistIndex {event} { variable history - if {[catch {expr $event}]} { + if {[catch {expr {~$event}}]} { for {set i $history(nextid)} {[info exists history($i)]} {incr i -1} { if {[string match $event* $history($i)]} { return $i; } if {[string match $event $history($i)]} { @@ -313,11 +313,11 @@ return $i; } } return -code error "no event matches \"$event\"" } elseif {$event <= 0} { - set i [expr $history(nextid) + $event] + 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" Index: library/http/http.tcl ================================================================== --- library/http/http.tcl +++ library/http/http.tcl @@ -7,11 +7,11 @@ # defined in the safe base. # # See the file "license.terms" for information on usage and # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# SCCS: @(#) http.tcl 1.8 97/10/28 16:23:30 +# RCS: @(#) $Id: http.tcl,v 1.1.2.4 1999/02/10 23:31:21 stanton Exp $ package provide http 2.0 ;# This uses Tcl namespaces namespace eval http { variable http @@ -71,11 +71,11 @@ } else { return -code error "Unknown option $flag, must be: $usage" } } else { foreach {flag value} $args { - if [regexp -- $pat $flag] { + if {[regexp -- $pat $flag]} { set http($flag) $value } else { return -code error "Unknown option $flag, must be: $usage" } } @@ -97,11 +97,14 @@ if {[string length $errormsg] == 0} { set state(error) [list $err $errorInfo $errorCode] set state(status) error } } - unset state(-command) + if {[info exist state(-command)]} { + # Command callback may already have unset our state + unset state(-command) + } } } # http::reset -- # @@ -138,11 +141,11 @@ # Returns a token for this connection. proc http::geturl { url args } { variable http - if ![info exists http(uid)] { + if {![info exists http(uid)]} { set http(uid) 0 } set token [namespace current]::[incr http(uid)] variable $token upvar 0 $token state @@ -164,11 +167,11 @@ -progress -query -validate -timeout} set usage [join $options ", "] regsub -all -- - $options {} options set pat ^-([join $options |])$ foreach {flag value} $args { - if [regexp $pat $flag] { + if {[regexp $pat $flag]} { # Validate numbers if {[info exists state($flag)] && \ [regexp {^[0-9]+$} $state($flag)] && \ ![regexp {^[0-9]+$} $value]} { return -code error "Bad value for $flag ($value), must be integer" @@ -283,19 +286,19 @@ proc http::Event {token} { variable $token upvar 0 $token state set s $state(sock) - if [::eof $s] then { + if {[::eof $s]} { Eof $token return } if {$state(state) == "header"} { set n [gets $s line] if {$n == 0} { set state(state) body - if ![regexp -nocase ^text $state(type)] { + if {![regexp -nocase ^text $state(type)]} { # Turn off conversions for non-text data fconfigure $s -translation binary if {[info exists state(-channel)]} { fconfigure $state(-channel) -translation binary } @@ -305,24 +308,24 @@ # Initiate a sequence of background fcopies fileevent $s readable {} CopyStart $s $token } } elseif {$n > 0} { - if [regexp -nocase {^content-type:(.+)$} $line x type] { + if {[regexp -nocase {^content-type:(.+)$} $line x type]} { set state(type) [string trim $type] } - if [regexp -nocase {^content-length:(.+)$} $line x length] { + if {[regexp -nocase {^content-length:(.+)$} $line x length]} { set state(totalsize) [string trim $length] } - if [regexp -nocase {^([^:]+):(.+)$} $line x key value] { + if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} { lappend state(meta) $key $value } elseif {[regexp ^HTTP $line]} { set state(http) $line } } } else { - if [catch { + if {[catch { if {[info exists state(-handler)]} { set n [eval $state(-handler) {$s $token}] } else { set block [read $s $state(-blocksize)] set n [string length $block] @@ -331,40 +334,41 @@ } } if {$n >= 0} { incr state(currentsize) $n } - } err] { + } err]} { Finish $token $err } else { - if [info exists state(-progress)] { + if {[info exists state(-progress)]} { eval $state(-progress) {$token $state(totalsize) $state(currentsize)} } } } } proc http::CopyStart {s token} { variable $token upvar 0 $token state - if [catch { + if {[catch { fcopy $s $state(-channel) -size $state(-blocksize) -command \ [list http::CopyDone $token] - } err] { + } err]} { Finish $token $err } } proc http::CopyDone {token count {error {}}} { variable $token upvar 0 $token state set s $state(sock) incr state(currentsize) $count - if [info exists state(-progress)] { + if {[info exists state(-progress)]} { eval $state(-progress) {$token $state(totalsize) $state(currentsize)} } + # At this point the token may have been reset if {([string length $error] != 0)} { Finish $token $error - } elseif {[::eof $s]} { + } elseif {[catch {::eof $s} iseof] || $iseof} { Eof $token } else { CopyStart $s $token } } Index: library/http1.0/http.tcl ================================================================== --- library/http1.0/http.tcl +++ library/http1.0/http.tcl @@ -3,11 +3,11 @@ # These routines can be used in untrusted code that uses the Safesock # security policy. # These procedures use a callback interface to avoid using vwait, # which is not defined in the safe base. # -# SCCS: @(#) http.tcl 1.10 97/10/29 16:12:55 +# RCS: @(#) $Id: http.tcl,v 1.1.2.2 1998/09/24 23:59:07 stanton Exp $ # # See the http.n man page for documentation package provide http 1.0 @@ -38,11 +38,11 @@ } else { return -code error "Unknown option $flag, must be: $usage" } } else { foreach {flag value} $args { - if [regexp -- $pat $flag] { + if {[regexp -- $pat $flag]} { set http($flag) $value } else { return -code error "Unknown option $flag, must be: $usage" } } @@ -79,11 +79,11 @@ eval error $errorlist } } proc http_get { url args } { global http - if ![info exists http(uid)] { + if {![info exists http(uid)]} { set http(uid) 0 } set token http#[incr http(uid)] upvar #0 $token state http_reset $token @@ -104,11 +104,11 @@ -progress -query -validate -timeout} set usage [join $options ", "] regsub -all -- - $options {} options set pat ^-([join $options |])$ foreach {flag value} $args { - if [regexp $pat $flag] { + if {[regexp $pat $flag]} { # Validate numbers if {[info exists state($flag)] && \ [regexp {^[0-9]+$} $state($flag)] && \ ![regexp {^[0-9]+$} $value]} { return -code error "Bad value for $flag ($value), must be integer" @@ -211,19 +211,19 @@ proc httpEvent {token} { upvar #0 $token state set s $state(sock) - if [eof $s] then { + if {[eof $s]} { httpEof $token return } if {$state(state) == "header"} { set n [gets $s line] if {$n == 0} { set state(state) body - if ![regexp -nocase ^text $state(type)] { + if {![regexp -nocase ^text $state(type)]} { # Turn off conversions for non-text data fconfigure $s -translation binary if {[info exists state(-channel)]} { fconfigure $state(-channel) -translation binary } @@ -233,24 +233,24 @@ # Initiate a sequence of background fcopies fileevent $s readable {} httpCopyStart $s $token } } elseif {$n > 0} { - if [regexp -nocase {^content-type:(.+)$} $line x type] { + if {[regexp -nocase {^content-type:(.+)$} $line x type]} { set state(type) [string trim $type] } - if [regexp -nocase {^content-length:(.+)$} $line x length] { + if {[regexp -nocase {^content-length:(.+)$} $line x length]} { set state(totalsize) [string trim $length] } - if [regexp -nocase {^([^:]+):(.+)$} $line x key value] { + if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} { lappend state(meta) $key $value } elseif {[regexp ^HTTP $line]} { set state(http) $line } } } else { - if [catch { + if {[catch { if {[info exists state(-handler)]} { set n [eval $state(-handler) {$s $token}] } else { set block [read $s $state(-blocksize)] set n [string length $block] @@ -259,33 +259,33 @@ } } if {$n >= 0} { incr state(currentsize) $n } - } err] { + } err]} { httpFinish $token $err } else { - if [info exists state(-progress)] { + if {[info exists state(-progress)]} { eval $state(-progress) {$token $state(totalsize) $state(currentsize)} } } } } proc httpCopyStart {s token} { upvar #0 $token state - if [catch { + if {[catch { fcopy $s $state(-channel) -size $state(-blocksize) -command \ [list httpCopyDone $token] - } err] { + } err]} { httpFinish $token $err } } proc httpCopyDone {token count {error {}}} { upvar #0 $token state set s $state(sock) incr state(currentsize) $count - if [info exists state(-progress)] { + if {[info exists state(-progress)]} { eval $state(-progress) {$token $state(totalsize) $state(currentsize)} } if {([string length $error] != 0)} { httpFinish $token $error } elseif {[eof $s]} { @@ -343,11 +343,11 @@ # 4 "subst" the result, doing all the array substitutions proc httpMapReply {string} { global httpFormMap set alphanumeric a-zA-Z0-9 - if ![info exists httpFormMap] { + if {![info exists httpFormMap]} { for {set i 1} {$i <= 256} {incr i} { set c [format %c $i] if {![string match \[$alphanumeric\] $c]} { set httpFormMap($c) %[format %.2x $i] Index: library/http2.0/http.tcl ================================================================== --- library/http2.0/http.tcl +++ library/http2.0/http.tcl @@ -7,11 +7,11 @@ # defined in the safe base. # # See the file "license.terms" for information on usage and # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# SCCS: @(#) http.tcl 1.8 97/10/28 16:23:30 +# RCS: @(#) $Id: http.tcl,v 1.1.2.4 1999/02/10 23:31:21 stanton Exp $ package provide http 2.0 ;# This uses Tcl namespaces namespace eval http { variable http @@ -71,11 +71,11 @@ } else { return -code error "Unknown option $flag, must be: $usage" } } else { foreach {flag value} $args { - if [regexp -- $pat $flag] { + if {[regexp -- $pat $flag]} { set http($flag) $value } else { return -code error "Unknown option $flag, must be: $usage" } } @@ -97,11 +97,14 @@ if {[string length $errormsg] == 0} { set state(error) [list $err $errorInfo $errorCode] set state(status) error } } - unset state(-command) + if {[info exist state(-command)]} { + # Command callback may already have unset our state + unset state(-command) + } } } # http::reset -- # @@ -138,11 +141,11 @@ # Returns a token for this connection. proc http::geturl { url args } { variable http - if ![info exists http(uid)] { + if {![info exists http(uid)]} { set http(uid) 0 } set token [namespace current]::[incr http(uid)] variable $token upvar 0 $token state @@ -164,11 +167,11 @@ -progress -query -validate -timeout} set usage [join $options ", "] regsub -all -- - $options {} options set pat ^-([join $options |])$ foreach {flag value} $args { - if [regexp $pat $flag] { + if {[regexp $pat $flag]} { # Validate numbers if {[info exists state($flag)] && \ [regexp {^[0-9]+$} $state($flag)] && \ ![regexp {^[0-9]+$} $value]} { return -code error "Bad value for $flag ($value), must be integer" @@ -283,19 +286,19 @@ proc http::Event {token} { variable $token upvar 0 $token state set s $state(sock) - if [::eof $s] then { + if {[::eof $s]} { Eof $token return } if {$state(state) == "header"} { set n [gets $s line] if {$n == 0} { set state(state) body - if ![regexp -nocase ^text $state(type)] { + if {![regexp -nocase ^text $state(type)]} { # Turn off conversions for non-text data fconfigure $s -translation binary if {[info exists state(-channel)]} { fconfigure $state(-channel) -translation binary } @@ -305,24 +308,24 @@ # Initiate a sequence of background fcopies fileevent $s readable {} CopyStart $s $token } } elseif {$n > 0} { - if [regexp -nocase {^content-type:(.+)$} $line x type] { + if {[regexp -nocase {^content-type:(.+)$} $line x type]} { set state(type) [string trim $type] } - if [regexp -nocase {^content-length:(.+)$} $line x length] { + if {[regexp -nocase {^content-length:(.+)$} $line x length]} { set state(totalsize) [string trim $length] } - if [regexp -nocase {^([^:]+):(.+)$} $line x key value] { + if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} { lappend state(meta) $key $value } elseif {[regexp ^HTTP $line]} { set state(http) $line } } } else { - if [catch { + if {[catch { if {[info exists state(-handler)]} { set n [eval $state(-handler) {$s $token}] } else { set block [read $s $state(-blocksize)] set n [string length $block] @@ -331,40 +334,41 @@ } } if {$n >= 0} { incr state(currentsize) $n } - } err] { + } err]} { Finish $token $err } else { - if [info exists state(-progress)] { + if {[info exists state(-progress)]} { eval $state(-progress) {$token $state(totalsize) $state(currentsize)} } } } } proc http::CopyStart {s token} { variable $token upvar 0 $token state - if [catch { + if {[catch { fcopy $s $state(-channel) -size $state(-blocksize) -command \ [list http::CopyDone $token] - } err] { + } err]} { Finish $token $err } } proc http::CopyDone {token count {error {}}} { variable $token upvar 0 $token state set s $state(sock) incr state(currentsize) $count - if [info exists state(-progress)] { + if {[info exists state(-progress)]} { eval $state(-progress) {$token $state(totalsize) $state(currentsize)} } + # At this point the token may have been reset if {([string length $error] != 0)} { Finish $token $error - } elseif {[::eof $s]} { + } elseif {[catch {::eof $s} iseof] || $iseof} { Eof $token } else { CopyStart $s $token } } Index: library/http2.1/http.tcl ================================================================== --- library/http2.1/http.tcl +++ library/http2.1/http.tcl @@ -7,11 +7,11 @@ # defined in the safe base. # # See the file "license.terms" for information on usage and # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# SCCS: @(#) http.tcl 1.8 97/10/28 16:23:30 +# RCS: @(#) $Id: http.tcl,v 1.1.2.4 1999/02/10 23:31:21 stanton Exp $ package provide http 2.0 ;# This uses Tcl namespaces namespace eval http { variable http @@ -71,11 +71,11 @@ } else { return -code error "Unknown option $flag, must be: $usage" } } else { foreach {flag value} $args { - if [regexp -- $pat $flag] { + if {[regexp -- $pat $flag]} { set http($flag) $value } else { return -code error "Unknown option $flag, must be: $usage" } } @@ -97,11 +97,14 @@ if {[string length $errormsg] == 0} { set state(error) [list $err $errorInfo $errorCode] set state(status) error } } - unset state(-command) + if {[info exist state(-command)]} { + # Command callback may already have unset our state + unset state(-command) + } } } # http::reset -- # @@ -138,11 +141,11 @@ # Returns a token for this connection. proc http::geturl { url args } { variable http - if ![info exists http(uid)] { + if {![info exists http(uid)]} { set http(uid) 0 } set token [namespace current]::[incr http(uid)] variable $token upvar 0 $token state @@ -164,11 +167,11 @@ -progress -query -validate -timeout} set usage [join $options ", "] regsub -all -- - $options {} options set pat ^-([join $options |])$ foreach {flag value} $args { - if [regexp $pat $flag] { + if {[regexp $pat $flag]} { # Validate numbers if {[info exists state($flag)] && \ [regexp {^[0-9]+$} $state($flag)] && \ ![regexp {^[0-9]+$} $value]} { return -code error "Bad value for $flag ($value), must be integer" @@ -283,19 +286,19 @@ proc http::Event {token} { variable $token upvar 0 $token state set s $state(sock) - if [::eof $s] then { + if {[::eof $s]} { Eof $token return } if {$state(state) == "header"} { set n [gets $s line] if {$n == 0} { set state(state) body - if ![regexp -nocase ^text $state(type)] { + if {![regexp -nocase ^text $state(type)]} { # Turn off conversions for non-text data fconfigure $s -translation binary if {[info exists state(-channel)]} { fconfigure $state(-channel) -translation binary } @@ -305,24 +308,24 @@ # Initiate a sequence of background fcopies fileevent $s readable {} CopyStart $s $token } } elseif {$n > 0} { - if [regexp -nocase {^content-type:(.+)$} $line x type] { + if {[regexp -nocase {^content-type:(.+)$} $line x type]} { set state(type) [string trim $type] } - if [regexp -nocase {^content-length:(.+)$} $line x length] { + if {[regexp -nocase {^content-length:(.+)$} $line x length]} { set state(totalsize) [string trim $length] } - if [regexp -nocase {^([^:]+):(.+)$} $line x key value] { + if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} { lappend state(meta) $key $value } elseif {[regexp ^HTTP $line]} { set state(http) $line } } } else { - if [catch { + if {[catch { if {[info exists state(-handler)]} { set n [eval $state(-handler) {$s $token}] } else { set block [read $s $state(-blocksize)] set n [string length $block] @@ -331,40 +334,41 @@ } } if {$n >= 0} { incr state(currentsize) $n } - } err] { + } err]} { Finish $token $err } else { - if [info exists state(-progress)] { + if {[info exists state(-progress)]} { eval $state(-progress) {$token $state(totalsize) $state(currentsize)} } } } } proc http::CopyStart {s token} { variable $token upvar 0 $token state - if [catch { + if {[catch { fcopy $s $state(-channel) -size $state(-blocksize) -command \ [list http::CopyDone $token] - } err] { + } err]} { Finish $token $err } } proc http::CopyDone {token count {error {}}} { variable $token upvar 0 $token state set s $state(sock) incr state(currentsize) $count - if [info exists state(-progress)] { + if {[info exists state(-progress)]} { eval $state(-progress) {$token $state(totalsize) $state(currentsize)} } + # At this point the token may have been reset if {([string length $error] != 0)} { Finish $token $error - } elseif {[::eof $s]} { + } elseif {[catch {::eof $s} iseof] || $iseof} { Eof $token } else { CopyStart $s $token } } Index: library/http2.3/http.tcl ================================================================== --- library/http2.3/http.tcl +++ library/http2.3/http.tcl @@ -7,11 +7,11 @@ # defined in the safe base. # # See the file "license.terms" for information on usage and # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# SCCS: @(#) http.tcl 1.8 97/10/28 16:23:30 +# RCS: @(#) $Id: http.tcl,v 1.1.2.4 1999/02/10 23:31:21 stanton Exp $ package provide http 2.0 ;# This uses Tcl namespaces namespace eval http { variable http @@ -71,11 +71,11 @@ } else { return -code error "Unknown option $flag, must be: $usage" } } else { foreach {flag value} $args { - if [regexp -- $pat $flag] { + if {[regexp -- $pat $flag]} { set http($flag) $value } else { return -code error "Unknown option $flag, must be: $usage" } } @@ -97,11 +97,14 @@ if {[string length $errormsg] == 0} { set state(error) [list $err $errorInfo $errorCode] set state(status) error } } - unset state(-command) + if {[info exist state(-command)]} { + # Command callback may already have unset our state + unset state(-command) + } } } # http::reset -- # @@ -138,11 +141,11 @@ # Returns a token for this connection. proc http::geturl { url args } { variable http - if ![info exists http(uid)] { + if {![info exists http(uid)]} { set http(uid) 0 } set token [namespace current]::[incr http(uid)] variable $token upvar 0 $token state @@ -164,11 +167,11 @@ -progress -query -validate -timeout} set usage [join $options ", "] regsub -all -- - $options {} options set pat ^-([join $options |])$ foreach {flag value} $args { - if [regexp $pat $flag] { + if {[regexp $pat $flag]} { # Validate numbers if {[info exists state($flag)] && \ [regexp {^[0-9]+$} $state($flag)] && \ ![regexp {^[0-9]+$} $value]} { return -code error "Bad value for $flag ($value), must be integer" @@ -283,19 +286,19 @@ proc http::Event {token} { variable $token upvar 0 $token state set s $state(sock) - if [::eof $s] then { + if {[::eof $s]} { Eof $token return } if {$state(state) == "header"} { set n [gets $s line] if {$n == 0} { set state(state) body - if ![regexp -nocase ^text $state(type)] { + if {![regexp -nocase ^text $state(type)]} { # Turn off conversions for non-text data fconfigure $s -translation binary if {[info exists state(-channel)]} { fconfigure $state(-channel) -translation binary } @@ -305,24 +308,24 @@ # Initiate a sequence of background fcopies fileevent $s readable {} CopyStart $s $token } } elseif {$n > 0} { - if [regexp -nocase {^content-type:(.+)$} $line x type] { + if {[regexp -nocase {^content-type:(.+)$} $line x type]} { set state(type) [string trim $type] } - if [regexp -nocase {^content-length:(.+)$} $line x length] { + if {[regexp -nocase {^content-length:(.+)$} $line x length]} { set state(totalsize) [string trim $length] } - if [regexp -nocase {^([^:]+):(.+)$} $line x key value] { + if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} { lappend state(meta) $key $value } elseif {[regexp ^HTTP $line]} { set state(http) $line } } } else { - if [catch { + if {[catch { if {[info exists state(-handler)]} { set n [eval $state(-handler) {$s $token}] } else { set block [read $s $state(-blocksize)] set n [string length $block] @@ -331,40 +334,41 @@ } } if {$n >= 0} { incr state(currentsize) $n } - } err] { + } err]} { Finish $token $err } else { - if [info exists state(-progress)] { + if {[info exists state(-progress)]} { eval $state(-progress) {$token $state(totalsize) $state(currentsize)} } } } } proc http::CopyStart {s token} { variable $token upvar 0 $token state - if [catch { + if {[catch { fcopy $s $state(-channel) -size $state(-blocksize) -command \ [list http::CopyDone $token] - } err] { + } err]} { Finish $token $err } } proc http::CopyDone {token count {error {}}} { variable $token upvar 0 $token state set s $state(sock) incr state(currentsize) $count - if [info exists state(-progress)] { + if {[info exists state(-progress)]} { eval $state(-progress) {$token $state(totalsize) $state(currentsize)} } + # At this point the token may have been reset if {([string length $error] != 0)} { Finish $token $error - } elseif {[::eof $s]} { + } elseif {[catch {::eof $s} iseof] || $iseof} { Eof $token } else { CopyStart $s $token } } Index: library/init.tcl ================================================================== --- library/init.tcl +++ library/init.tcl @@ -1,43 +1,106 @@ # init.tcl -- # # Default system startup file for Tcl-based applications. Defines # "unknown" procedure and auto-load facilities. # -# SCCS: @(#) init.tcl 1.95 97/11/19 17:16:34 +# RCS: @(#) $Id: init.tcl,v 1.1.2.7 1999/03/13 23:49:48 rjohnson Exp $ # # Copyright (c) 1991-1993 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. # if {[info commands package] == ""} { error "version mismatch: library\nscripts expect Tcl version 7.5b1 or later but the loaded version is\nonly [info patchlevel]" } -package require -exact Tcl 8.0 +package require -exact Tcl 8.1 # Compute the auto path to use in this interpreter. -# (auto_path could be already set, in safe interps for instance) +# The values on the path come from several locations: +# +# The environment variable TCLLIBPATH +# +# tcl_library, which is the directory containing this init.tcl script. +# tclInitScript.h searches around for the directory containing this +# init.tcl and defines tcl_library to that location before sourcing it. +# +# The parent directory of tcl_library. Adding the parent +# means that packages in peer directories will be found automatically. +# +# tcl_pkgPath, which is set by the platform-specific initialization routines +# On UNIX it is compiled in +# On Windows it comes from the registry +# On Macintosh it is "Tool Command Language" in the Extensions folder if {![info exists auto_path]} { - if [catch {set auto_path $env(TCLLIBPATH)}] { + if {[info exist env(TCLLIBPATH)]} { + set auto_path $env(TCLLIBPATH) + } else { set auto_path "" } } -if {[lsearch -exact $auto_path [info library]] < 0} { - lappend auto_path [info library] +if {[string compare [info library] {}]} { + foreach __dir [list [info library] [file dirname [info library]]] { + if {[lsearch -exact $auto_path $__dir] < 0} { + lappend auto_path $__dir + } + } } -catch { +if {[info exist tcl_pkgPath]} { foreach __dir $tcl_pkgPath { if {[lsearch -exact $auto_path $__dir] < 0} { lappend auto_path $__dir } } +} +if {[info exists __dir]} { unset __dir } + +# Windows specific end of initialization + +if {(![interp issafe]) && ($tcl_platform(platform) == "windows")} { + namespace eval tcl { + proc envTraceProc {lo n1 n2 op} { + set x $::env($n2) + set ::env($lo) $x + set ::env([string toupper $lo]) $x + } + } + foreach p [array names env] { + set u [string toupper $p] + if {$u != $p} { + switch -- $u { + COMSPEC - + PATH { + if {![info exists env($u)]} { + set env($u) $env($p) + } + trace variable env($p) w [list tcl::envTraceProc $p] + trace variable env($u) w [list tcl::envTraceProc $p] + } + } + } + } + if {[info exists p]} { + unset p + } + if {[info exists u]} { + unset u + } + if {![info exists env(COMSPEC)]} { + if {$tcl_platform(os) == {Windows NT}} { + set env(COMSPEC) cmd.exe + } else { + set env(COMSPEC) command.com + } + } +} # Setup the unknown package handler package unknown tclPkgUnknown @@ -59,24 +122,21 @@ if {[info commands tclLog] == ""} { proc tclLog {string} { catch {puts stderr $string} } } - -# The procs defined in this file that have a leading space -# are 'hidden' from auto_mkindex because they are not -# auto-loadable. - # unknown -- # This procedure is called when a Tcl command is invoked that doesn't # exist in the interpreter. It takes the following steps to make the # command available: # -# 1. See if the autoload facility can locate the command in a +# 1. See if the command has the form "namespace inscope ns cmd" and +# if so, concatenate its arguments onto the end and evaluate it. +# 2. See if the autoload facility can locate the command in a # Tcl script file. If so, load it and execute it. -# 2. If the command was invoked interactively at top-level: +# 3. If the command was invoked interactively at top-level: # (a) see if the command exists as an executable UNIX program. # If so, "exec" the command. # (b) see if the command requests csh-like history substitution # in one of the common forms !!, !, or ^old^new. If # so, emulate csh's history substitution. @@ -85,39 +145,53 @@ # # Arguments: # args - A list whose elements are the words of the original # command, including the command name. - proc unknown args { +proc unknown args { global auto_noexec auto_noload env unknown_pending tcl_interactive global errorCode errorInfo + + # If the command word has the form "namespace inscope ns cmd" + # then concatenate its arguments onto the end and evaluate it. + + set cmd [lindex $args 0] + if {[regexp "^namespace\[ \t\n\]+inscope" $cmd] && [llength $cmd] == 4} { + set arglist [lrange $args 1 end] + set ret [catch {uplevel $cmd $arglist} result] + if {$ret == 0} { + return $result + } else { + return -code $ret -errorcode $errorCode $result + } + } # Save the values of errorCode and errorInfo variables, since they # may get modified if caught errors occur below. The variables will # be restored just before re-executing the missing command. set savedErrorCode $errorCode set savedErrorInfo $errorInfo set name [lindex $args 0] - if ![info exists auto_noload] { + if {![info exists auto_noload]} { # # Make sure we're not trying to load the same proc twice. # - if [info exists unknown_pending($name)] { + if {[info exists unknown_pending($name)]} { return -code error "self-referential recursion in \"unknown\" for command \"$name\""; } set unknown_pending($name) pending; set ret [catch {auto_load $name [uplevel 1 {namespace current}]} msg] unset unknown_pending($name); if {$ret != 0} { return -code $ret -errorcode $errorCode \ "error while autoloading \"$name\": $msg" } - if ![array size unknown_pending] { + if {![array size unknown_pending]} { unset unknown_pending } - if $msg { + if {$msg} { set errorCode $savedErrorCode set errorInfo $savedErrorInfo set code [catch {uplevel 1 $args} msg] if {$code == 1} { # @@ -124,11 +198,11 @@ # Strip the last five lines off the error stack (they're # from the "uplevel" command). # set new [split $errorInfo \n] - set new [join [lrange $new 0 [expr [llength $new] - 6]] \n] + set new [join [lrange $new 0 [expr {[llength $new] - 6}]] \n] return -code error -errorcode $errorCode \ -errorinfo $new $msg } else { return -code $code $msg } @@ -135,11 +209,11 @@ } } if {([info level] == 1) && ([info script] == "") \ && [info exists tcl_interactive] && $tcl_interactive} { - if ![info exists auto_noexec] { + if {![info exists auto_noexec]} { set new [auto_execok $name] if {$new != ""} { set errorCode $savedErrorCode set errorInfo $savedErrorInfo set redir "" @@ -157,11 +231,11 @@ set newcmd [history event $event] } elseif {[regexp {^\^([^^]*)\^([^^]*)\^?$} $name dummy old new]} { set newcmd [history event -1] catch {regsub -all -- $old $newcmd $new newcmd} } - if [info exists newcmd] { + if {[info exists newcmd]} { tclLog $newcmd history change $newcmd 0 return [uplevel $newcmd] } @@ -198,30 +272,58 @@ # cmd - Name of the command to find and load. # namespace (optional) The namespace where the command is being used - must be # a canonical namespace as returned [namespace current] # for instance. If not given, namespace current is used. - proc auto_load {cmd {namespace {}}} { - global auto_index auto_oldpath auto_path env errorInfo errorCode +proc auto_load {cmd {namespace {}}} { + global auto_index auto_oldpath auto_path if {[string length $namespace] == 0} { set namespace [uplevel {namespace current}] } set nameList [auto_qualify $cmd $namespace] # workaround non canonical auto_index entries that might be around # from older auto_mkindex versions lappend nameList $cmd foreach name $nameList { - if [info exists auto_index($name)] { + if {[info exists auto_index($name)]} { uplevel #0 $auto_index($name) return [expr {[info commands $name] != ""}] } } - if ![info exists auto_path] { + if {![info exists auto_path]} { + return 0 + } + + if {![auto_load_index]} { return 0 } - if [info exists auto_oldpath] { + + foreach name $nameList { + if {[info exists auto_index($name)]} { + uplevel #0 $auto_index($name) + if {[info commands $name] != ""} { + return 1 + } + } + } + return 0 +} + +# auto_load_index -- +# Loads the contents of tclIndex files on the auto_path directory +# list. This is usually invoked within auto_load to load the index +# of available commands. Returns 1 if the index is loaded, and 0 if +# the index is already loaded and up to date. +# +# Arguments: +# None. + +proc auto_load_index {} { + global auto_index auto_oldpath auto_path errorInfo errorCode + + if {[info exists auto_oldpath]} { if {$auto_oldpath == $auto_path} { return 0 } } set auto_oldpath $auto_path @@ -228,16 +330,16 @@ # Check if we are a safe interpreter. In that case, we support only # newer format tclIndex files. set issafe [interp issafe] - for {set i [expr [llength $auto_path] - 1]} {$i >= 0} {incr i -1} { + for {set i [expr {[llength $auto_path] - 1}]} {$i >= 0} {incr i -1} { set dir [lindex $auto_path $i] set f "" if {$issafe} { catch {source [file join $dir tclIndex]} - } elseif [catch {set f [open [file join $dir tclIndex]]}] { + } elseif {[catch {set f [open [file join $dir tclIndex]]}]} { continue } else { set error [catch { set id [gets $f] if {$id == "# Tcl autoload index file, version 2.0"} { @@ -259,28 +361,21 @@ } } msg] if {$f != ""} { close $f } - if $error { + if {$error} { error $msg $errorInfo $errorCode } } } - foreach name $nameList { - if [info exists auto_index($name)] { - uplevel #0 $auto_index($name) - if {[info commands $name] != ""} { - return 1 - } - } - } - return 0 + return 1 } # auto_qualify -- -# compute a fully qualified names list for use in the auto_index array. +# +# Compute a fully qualified names list for use in the auto_index array. # For historical reasons, commands in the global namespace do not have leading # :: in the index key. The list has two elements when the command name is # relative (no leading ::) and the namespace is not the global one. Otherwise # only one name is returned (and searched in the auto_index). # @@ -289,11 +384,11 @@ # invocations (Like "foo::::bar"). # namespace The namespace where the command is being used - must be # a canonical namespace as returned by [namespace current] # for instance. - proc auto_qualify {cmd namespace} { +proc auto_qualify {cmd namespace} { # count separators and clean them up # (making sure that foo:::::bar will be treated as foo::bar) set n [regsub -all {::+} $cmd :: cmd] @@ -334,11 +429,37 @@ return [list ${namespace}::$cmd ::$cmd] } } } -if {[string compare $tcl_platform(platform) windows] == 0} { +# auto_import -- +# +# Invoked during "namespace import" to make see if the imported commands +# reside in an autoloaded library. If so, the commands are loaded so +# that they will be available for the import links. If not, then this +# procedure does nothing. +# +# Arguments - +# pattern The pattern of commands being imported (like "foo::*") +# a canonical namespace as returned by [namespace current] + +proc auto_import {pattern} { + global auto_index + + set ns [uplevel namespace current] + set patternList [auto_qualify $pattern $ns] + + auto_load_index + + foreach pattern $patternList { + foreach name [array names auto_index] { + if {[string match $pattern $name] && "" == [info commands $name]} { + uplevel #0 $auto_index($name) + } + } + } +} # auto_execok -- # # Returns string that indicates name of program to execute if # name corresponds to a shell builtin or an executable in the @@ -347,10 +468,11 @@ # for speed. # # Arguments: # name - Name of a command. +if {[string compare $tcl_platform(platform) windows] == 0} { # Windows version. # # Note that info executable doesn't work under Windows, so we have to # look for files with .exe, .com, or .bat extensions. Also, the path # may be in the Path or PATH environment variables, and path @@ -357,11 +479,11 @@ # components are separated with semicolons, not colons as under Unix. # proc auto_execok name { global auto_execs env tcl_platform - if [info exists auto_execs($name)] { + if {[info exists auto_execs($name)]} { return $auto_execs($name) } set auto_execs($name) "" if {[lsearch -exact {cls copy date del erase dir echo mkdir md rename @@ -407,27 +529,16 @@ } return "" } } else { - -# auto_execok -- -# -# Returns string that indicates name of program to execute if -# name corresponds to an executable in the path. Builds an associative -# array auto_execs that caches information about previous checks, -# for speed. -# -# Arguments: -# name - Name of a command. - # Unix version. # proc auto_execok name { global auto_execs env - if [info exists auto_execs($name)] { + if {[info exists auto_execs($name)]} { return $auto_execs($name) } set auto_execs($name) "" if {[llength [file split $name]] != 1} { if {[file executable $name] && ![file isdirectory $name]} { @@ -447,339 +558,5 @@ } return "" } } -# auto_reset -- -# Destroy all cached information for auto-loading and auto-execution, -# so that the information gets recomputed the next time it's needed. -# Also delete any procedures that are listed in the auto-load index -# except those defined in this file. -# -# Arguments: -# None. - -proc auto_reset {} { - global auto_execs auto_index auto_oldpath - foreach p [info procs] { - if {[info exists auto_index($p)] && ![string match auto_* $p] - && ([lsearch -exact {unknown pkg_mkIndex tclPkgSetup - tclMacPkgSearch tclPkgUnknown} $p] < 0)} { - rename $p {} - } - } - catch {unset auto_execs} - catch {unset auto_index} - catch {unset auto_oldpath} -} - -# auto_mkindex -- -# Regenerate a tclIndex file from Tcl source files. Takes as argument -# the name of the directory in which the tclIndex file is to be placed, -# followed by any number of glob patterns to use in that directory to -# locate all of the relevant files. It does not parse or source the file -# so the generated index will not contain the appropriate namespace qualifiers -# if you don't explicitly specify it. -# -# Arguments: -# dir - Name of the directory in which to create an index. -# args - Any number of additional arguments giving the -# names of files within dir. If no additional -# are given auto_mkindex will look for *.tcl. - -proc auto_mkindex {dir args} { - global errorCode errorInfo - set oldDir [pwd] - cd $dir - set dir [pwd] - append index "# Tcl autoload index file, version 2.0\n" - append index "# This file is generated by the \"auto_mkindex\" command\n" - append index "# and sourced to set up indexing information for one or\n" - append index "# more commands. Typically each line is a command that\n" - append index "# sets an element in the auto_index array, where the\n" - append index "# element name is the name of a command and the value is\n" - append index "# a script that loads the command.\n\n" - if {$args == ""} { - set args *.tcl - } - foreach file [eval glob $args] { - set f "" - set error [catch { - set f [open $file] - while {[gets $f line] >= 0} { - if [regexp {^proc[ ]+([^ ]*)} $line match procName] { - set procName [lindex [auto_qualify $procName "::"] 0] - append index "set [list auto_index($procName)]" - append index " \[list source \[file join \$dir [list $file]\]\]\n" - } - } - close $f - } msg] - if $error { - set code $errorCode - set info $errorInfo - catch {close $f} - cd $oldDir - error $msg $info $code - } - } - set f "" - set error [catch { - set f [open tclIndex w] - puts $f $index nonewline - close $f - cd $oldDir - } msg] - if $error { - set code $errorCode - set info $errorInfo - catch {close $f} - cd $oldDir - error $msg $info $code - } -} - -# pkg_mkIndex -- -# This procedure creates a package index in a given directory. The -# package index consists of a "pkgIndex.tcl" file whose contents are -# a Tcl script that sets up package information with "package require" -# commands. The commands describe all of the packages defined by the -# files given as arguments. -# -# Arguments: -# dir - Name of the directory in which to create the index. -# args - Any number of additional arguments, each giving -# a glob pattern that matches the names of one or -# more shared libraries or Tcl script files in -# dir. - -proc pkg_mkIndex {dir args} { - global errorCode errorInfo - if {[llength $args] == 0} { - return -code error "wrong # args: should be\ - \"pkg_mkIndex dir pattern ?pattern ...?\""; - } - append index "# Tcl package index file, version 1.0\n" - append index "# This file is generated by the \"pkg_mkIndex\" command\n" - append index "# and sourced either when an application starts up or\n" - append index "# by a \"package unknown\" script. It invokes the\n" - append index "# \"package ifneeded\" command to set up package-related\n" - append index "# information so that packages will be loaded automatically\n" - append index "# in response to \"package require\" commands. When this\n" - append index "# script is sourced, the variable \$dir must contain the\n" - append index "# full path name of this file's directory.\n" - set oldDir [pwd] - cd $dir - foreach file [eval glob $args] { - # For each file, figure out what commands and packages it provides. - # To do this, create a child interpreter, load the file into the - # interpreter, and get a list of the new commands and packages - # that are defined. Define an empty "package unknown" script so - # that there are no recursive package inclusions. - - set c [interp create] - - # If Tk is loaded in the parent interpreter, load it into the - # child also, in case the extension depends on it. - - foreach pkg [info loaded] { - if {[lindex $pkg 1] == "Tk"} { - $c eval {set argv {-geometry +0+0}} - load [lindex $pkg 0] Tk $c - break - } - } - $c eval [list set file $file] - if [catch { - $c eval { - proc dummy args {} - rename package package-orig - proc package {what args} { - switch -- $what { - require { return ; # ignore transitive requires } - default { eval package-orig {$what} $args } - } - } - proc pkgGetAllNamespaces {{root {}}} { - set list $root - foreach ns [namespace children $root] { - eval lappend list [pkgGetAllNamespaces $ns] - } - return $list - } - package unknown dummy - set origCmds [info commands] - set dir "" ;# in case file is pkgIndex.tcl - set pkgs "" - - # Try to load the file if it has the shared library extension, - # otherwise source it. It's important not to try to load - # files that aren't shared libraries, because on some systems - # (like SunOS) the loader will abort the whole application - # when it gets an error. - - if {[string compare [file extension $file] \ - [info sharedlibextension]] == 0} { - - # The "file join ." command below is necessary. Without - # it, if the file name has no \'s and we're on UNIX, the - # load command will invoke the LD_LIBRARY_PATH search - # mechanism, which could cause the wrong file to be used. - - load [file join . $file] - set type load - } else { - source $file - set type source - } - foreach ns [pkgGetAllNamespaces] { - namespace import ${ns}::* - } - foreach i [info commands] { - set cmds($i) 1 - } - foreach i $origCmds { - catch {unset cmds($i)} - - } - foreach i [array names cmds] { - # reverse engineer which namespace a command comes from - set absolute [namespace origin $i] - if {[string compare ::$i $absolute] != 0} { - set cmds($absolute) 1 - unset cmds($i) - } - } - foreach i [package names] { - if {([string compare [package provide $i] ""] != 0) - && ([string compare $i Tcl] != 0) - && ([string compare $i Tk] != 0)} { - lappend pkgs [list $i [package provide $i]] - } - } - } - } msg] { - tclLog "error while loading or sourcing $file: $msg" - } - foreach pkg [$c eval set pkgs] { - lappend files($pkg) [list $file [$c eval set type] \ - [lsort [$c eval array names cmds]]] - } - interp delete $c - } - foreach pkg [lsort [array names files]] { - append index "\npackage ifneeded $pkg\ - \[list tclPkgSetup \$dir [lrange $pkg 0 0] [lrange $pkg 1 1]\ - [list $files($pkg)]\]" - } - set f [open pkgIndex.tcl w] - puts $f $index - close $f - cd $oldDir -} - -# tclPkgSetup -- -# This is a utility procedure use by pkgIndex.tcl files. It is invoked -# as part of a "package ifneeded" script. It calls "package provide" -# to indicate that a package is available, then sets entries in the -# auto_index array so that the package's files will be auto-loaded when -# the commands are used. -# -# Arguments: -# dir - Directory containing all the files for this package. -# pkg - Name of the package (no version number). -# version - Version number for the package, such as 2.1.3. -# files - List of files that constitute the package. Each -# element is a sub-list with three elements. The first -# is the name of a file relative to $dir, the second is -# "load" or "source", indicating whether the file is a -# loadable binary or a script to source, and the third -# is a list of commands defined by this file. - -proc tclPkgSetup {dir pkg version files} { - global auto_index - - package provide $pkg $version - foreach fileInfo $files { - set f [lindex $fileInfo 0] - set type [lindex $fileInfo 1] - foreach cmd [lindex $fileInfo 2] { - if {$type == "load"} { - set auto_index($cmd) [list load [file join $dir $f] $pkg] - } else { - set auto_index($cmd) [list source [file join $dir $f]] - } - } - } -} - -# tclMacPkgSearch -- -# The procedure is used on the Macintosh to search a given directory for files -# with a TEXT resource named "pkgIndex". If it exists it is sourced in to the -# interpreter to setup the package database. - -proc tclMacPkgSearch {dir} { - foreach x [glob -nocomplain [file join $dir *.shlb]] { - if [file isfile $x] { - set res [resource open $x] - foreach y [resource list TEXT $res] { - if {$y == "pkgIndex"} {source -rsrc pkgIndex} - } - catch {resource close $res} - } - } -} - -# tclPkgUnknown -- -# This procedure provides the default for the "package unknown" function. -# It is invoked when a package that's needed can't be found. It scans -# the auto_path directories and their immediate children looking for -# pkgIndex.tcl files and sources any such files that are found to setup -# the package database. (On the Macintosh we also search for pkgIndex -# TEXT resources in all files.) -# -# Arguments: -# name - Name of desired package. Not used. -# version - Version of desired package. Not used. -# exact - Either "-exact" or omitted. Not used. - -proc tclPkgUnknown {name version {exact {}}} { - global auto_path tcl_platform env - - if ![info exists auto_path] { - return - } - for {set i [expr [llength $auto_path] - 1]} {$i >= 0} {incr i -1} { - # we can't use glob in safe interps, so enclose the following - # in a catch statement - catch { - foreach file [glob -nocomplain [file join [lindex $auto_path $i] \ - * pkgIndex.tcl]] { - set dir [file dirname $file] - if [catch {source $file} msg] { - tclLog "error reading package index file $file: $msg" - } - } - } - set dir [lindex $auto_path $i] - set file [file join $dir pkgIndex.tcl] - # safe interps usually don't have "file readable", nor stderr channel - if {[interp issafe] || [file readable $file]} { - if {[catch {source $file} msg] && ![interp issafe]} { - tclLog "error reading package index file $file: $msg" - } - } - # On the Macintosh we also look in the resource fork - # of shared libraries - # We can't use tclMacPkgSearch in safe interps because it uses glob - if {(![interp issafe]) && ($tcl_platform(platform) == "macintosh")} { - set dir [lindex $auto_path $i] - tclMacPkgSearch $dir - foreach x [glob -nocomplain [file join $dir *]] { - if [file isdirectory $x] { - set dir $x - tclMacPkgSearch $dir - } - } - } - } -} Index: library/ldAout.tcl ================================================================== --- library/ldAout.tcl +++ library/ldAout.tcl @@ -16,11 +16,11 @@ # entry and safe initialization entry are present. A trivial # C function that locates the entries is composed, compiled, and # its .o file placed before all others in the command; then # "ld" is executed to bind the objects together. # -# SCCS: @(#) ldAout.tcl 1.12 96/11/30 17:11:02 +# RCS: @(#) $Id: ldAout.tcl,v 1.1.2.2 1998/12/02 20:08:06 welch Exp $ # # Copyright (c) 1995, by General Electric Company. All rights reserved. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -96,13 +96,13 @@ set outputFile $a set minusO 0 } elseif {![string compare $a -o]} { set minusO 1 } - if [regexp {^-[lL]} $a] { + if {[regexp {^-[lL]} $a]} { lappend libraries $a - if [regexp {^-L} $a] { + if {[regexp {^-L} $a]} { lappend libdirs [string range $a 2 end] } } elseif {$seenDotO} { lappend tail $a } else { @@ -114,14 +114,14 @@ # MIPS -- If there are corresponding G0 libraries, replace the # ordinary ones with the G0 ones. set libs {} foreach lib $libraries { - if [regexp {^-l} $lib] { + if {[regexp {^-l} $lib]} { set lname [string range $lib 2 end] foreach dir $libdirs { - if [file exists [file join $dir lib${lname}_G0.a]] { + if {[file exists [file join $dir lib${lname}_G0.a]]} { set lname ${lname}_G0 break } } lappend libs -l$lname @@ -135,34 +135,34 @@ if {![info exists outputFile]} { error "-o option must be supplied to link a Tcl load module" } set m [file tail $outputFile] - if [regexp {\.a$} $outputFile] { + if {[regexp {\.a$} $outputFile]} { set shlib_suffix .a } else { set shlib_suffix "" } - if [regexp {\..*$} $outputFile match] { - set l [expr [string length $m] - [string length $match]] + if {[regexp {\..*$} $outputFile match]} { + set l [expr {[string length $m] - [string length $match]}] } else { error "Output file does not appear to have a suffix" } - set modName [string tolower [string range $m 0 [expr $l-1]]] - if [regexp {^lib} $modName] { + set modName [string tolower [string range $m 0 [expr {$l-1}]]] + if {[regexp {^lib} $modName]} { set modName [string range $modName 3 end] } - if [regexp {[0-9\.]*(_g0)?$} $modName match] { - set modName [string range $modName 0 [expr [string length $modName]-[string length $match]-1]] + if {[regexp {[0-9\.]*(_g0)?$} $modName match]} { + set modName [string range $modName 0 [expr {[string length $modName]-[string length $match]-1}]] } set modName "[string toupper [string index $modName 0]][string range $modName 1 end]" # Catalog initialization entry points found in the module set f [open $nmCommand r] while {[gets $f l] >= 0} { - if [regexp {T[ ]*_?([A-Z][a-z0-9_]*_(Safe)?Init(__FP10Tcl_Interp)?)$} $l trash symbol] { + if {[regexp {T[ ]*_?([A-Z][a-z0-9_]*_(Safe)?Init(__FP10Tcl_Interp)?)$} $l trash symbol]} { if {![regexp {_?([A-Z][a-z0-9_]*_(Safe)?Init)} $symbol trash s]} { set s $symbol } append entryProtos {extern int } $symbol { (); } \n append entryPoints { } \{ { "} $s {", } $symbol { } \} , \n @@ -217,14 +217,14 @@ if {$shlib_suffix == ".a"} { set ldCommand "ar cr $outputFile" regsub { -o} $tail {} tail } else { - set ldCommand ld - foreach item $head { - lappend ldCommand $item - } + set ldCommand ld + foreach item $head { + lappend ldCommand $item + } } lappend ldCommand tcl$modName.o foreach item $tail { lappend ldCommand $item } ADDED library/msgcat/msgcat.tcl Index: library/msgcat/msgcat.tcl ================================================================== --- /dev/null +++ library/msgcat/msgcat.tcl @@ -0,0 +1,177 @@ +# 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) 1998 by Scriptics Corporation. +# 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. +# +# RCS: @(#) $Id: msgcat.tcl,v 1.1.2.5 1998/12/10 01:40:55 stanton Exp $ + +package provide msgcat 1.0 + +namespace eval msgcat { + namespace export mc mcset mclocale mcpreferences mcunknown + + # Records the current locale as passed to mclocale + variable locale "" + + # Records the list of locales to search + variable loclist {} + + # Records the mapping between source strings and translated strings. The + # array key is of the form ",," and the value is + # the translated string. + array set msgs {} +} + +# msgcat::mc -- +# +# Find the translation for the given string based on the current +# locale setting. +# +# Arguments: +# src The string to translate. +# +# Results: +# Returns the translatd string. + +proc msgcat::mc {src} { + set ns [uplevel {namespace current}] + foreach loc $::msgcat::loclist { + if {[info exists ::msgcat::msgs($loc,$ns,$src)]} { + return $::msgcat::msgs($loc,$ns,$src) + } + } + # we have not found the translation + return [uplevel 1 [list [namespace origin mcunknown] \ + $::msgcat::locale $src]] +} + +# msgcat::mclocale -- +# +# Query or set the current locale. +# +# Arguments: +# newLocale (Optional) The new locale string. Locale strings +# should be composed of one or more sublocale parts +# separated by underscores (e.g. en_US). +# +# Results: +# Returns the current locale. + +proc msgcat::mclocale {args} { + set len [llength $args] + + if {$len > 1} { + error {wrong # args: should be "mclocale ?newLocale?"} + } + + set args [string tolower $args] + if {$len == 1} { + set ::msgcat::locale $args + set ::msgcat::loclist {} + set word "" + foreach part [split $args _] { + set word [string trimleft "${word}_${part}" _] + set ::msgcat::loclist \ + [linsert $::msgcat::loclist 0 $word] + } + } + return $::msgcat::locale +} + +# msgcat::mcpreferences -- +# +# Fetch the list of locales used to look up strings, ordered from +# most preferred to least preferred. +# +# Arguments: +# None. +# +# Results: +# Returns an ordered list of the locales preferred by the user. + +proc msgcat::mcpreferences {} { + return $::msgcat::loclist +} + +# msgcat::mcload -- +# +# Attempt to load message catalogs for each locale in the +# preference list from the specified directory. +# +# Arguments: +# langdir The directory to search. +# +# Results: +# Returns the number of message catalogs that were loaded. + +proc msgcat::mcload {langdir} { + set x 0 + foreach p [::msgcat::mcpreferences] { + set langfile [file join $langdir $p.msg] + if {[file exists $langfile]} { + incr x + uplevel [list source $langfile] + } + } + return $x +} + +# msgcat::mcset -- +# +# Set the translation for a given string in a specified locale. +# +# Arguments: +# locale The locale to use. +# src The source string. +# dest (Optional) The translated string. If omitted, +# the source string is used. +# +# Results: +# Returns the new locale. + +proc msgcat::mcset {locale src {dest ""}} { + if {$dest == ""} { + set dest $src + } + + set ns [uplevel {namespace current}] + + set ::msgcat::msgs([string tolower $locale],$ns,$src) $dest + return $dest +} + +# msgcat::mcunknown -- +# +# This routine is called by msgcat::mc if a translation cannot +# be found for a string. This routine is intended to be replaced +# by an application specific routine for error reporting +# purposes. The default behavior is to return the source string. +# +# Arguments: +# locale The current locale. +# src The string to be translated. +# +# Results: +# Returns the translated value. + +proc msgcat::mcunknown {locale src} { + return $src +} + +# Initialize the default locale + +namespace eval msgcat { + # set default locale, try to get from environment + if {[info exists ::env(LANG)]} { + mclocale $::env(LANG) + } else { + mclocale "C" + } +} ADDED library/msgcat/pkgIndex.tcl Index: library/msgcat/pkgIndex.tcl ================================================================== --- /dev/null +++ library/msgcat/pkgIndex.tcl @@ -0,0 +1,1 @@ +package ifneeded msgcat 1.0 [list source [file join $dir msgcat.tcl]] ADDED library/msgcat1.0/msgcat.tcl Index: library/msgcat1.0/msgcat.tcl ================================================================== --- /dev/null +++ library/msgcat1.0/msgcat.tcl @@ -0,0 +1,177 @@ +# 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) 1998 by Scriptics Corporation. +# 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. +# +# RCS: @(#) $Id: msgcat.tcl,v 1.1.2.5 1998/12/10 01:40:55 stanton Exp $ + +package provide msgcat 1.0 + +namespace eval msgcat { + namespace export mc mcset mclocale mcpreferences mcunknown + + # Records the current locale as passed to mclocale + variable locale "" + + # Records the list of locales to search + variable loclist {} + + # Records the mapping between source strings and translated strings. The + # array key is of the form ",," and the value is + # the translated string. + array set msgs {} +} + +# msgcat::mc -- +# +# Find the translation for the given string based on the current +# locale setting. +# +# Arguments: +# src The string to translate. +# +# Results: +# Returns the translatd string. + +proc msgcat::mc {src} { + set ns [uplevel {namespace current}] + foreach loc $::msgcat::loclist { + if {[info exists ::msgcat::msgs($loc,$ns,$src)]} { + return $::msgcat::msgs($loc,$ns,$src) + } + } + # we have not found the translation + return [uplevel 1 [list [namespace origin mcunknown] \ + $::msgcat::locale $src]] +} + +# msgcat::mclocale -- +# +# Query or set the current locale. +# +# Arguments: +# newLocale (Optional) The new locale string. Locale strings +# should be composed of one or more sublocale parts +# separated by underscores (e.g. en_US). +# +# Results: +# Returns the current locale. + +proc msgcat::mclocale {args} { + set len [llength $args] + + if {$len > 1} { + error {wrong # args: should be "mclocale ?newLocale?"} + } + + set args [string tolower $args] + if {$len == 1} { + set ::msgcat::locale $args + set ::msgcat::loclist {} + set word "" + foreach part [split $args _] { + set word [string trimleft "${word}_${part}" _] + set ::msgcat::loclist \ + [linsert $::msgcat::loclist 0 $word] + } + } + return $::msgcat::locale +} + +# msgcat::mcpreferences -- +# +# Fetch the list of locales used to look up strings, ordered from +# most preferred to least preferred. +# +# Arguments: +# None. +# +# Results: +# Returns an ordered list of the locales preferred by the user. + +proc msgcat::mcpreferences {} { + return $::msgcat::loclist +} + +# msgcat::mcload -- +# +# Attempt to load message catalogs for each locale in the +# preference list from the specified directory. +# +# Arguments: +# langdir The directory to search. +# +# Results: +# Returns the number of message catalogs that were loaded. + +proc msgcat::mcload {langdir} { + set x 0 + foreach p [::msgcat::mcpreferences] { + set langfile [file join $langdir $p.msg] + if {[file exists $langfile]} { + incr x + uplevel [list source $langfile] + } + } + return $x +} + +# msgcat::mcset -- +# +# Set the translation for a given string in a specified locale. +# +# Arguments: +# locale The locale to use. +# src The source string. +# dest (Optional) The translated string. If omitted, +# the source string is used. +# +# Results: +# Returns the new locale. + +proc msgcat::mcset {locale src {dest ""}} { + if {$dest == ""} { + set dest $src + } + + set ns [uplevel {namespace current}] + + set ::msgcat::msgs([string tolower $locale],$ns,$src) $dest + return $dest +} + +# msgcat::mcunknown -- +# +# This routine is called by msgcat::mc if a translation cannot +# be found for a string. This routine is intended to be replaced +# by an application specific routine for error reporting +# purposes. The default behavior is to return the source string. +# +# Arguments: +# locale The current locale. +# src The string to be translated. +# +# Results: +# Returns the translated value. + +proc msgcat::mcunknown {locale src} { + return $src +} + +# Initialize the default locale + +namespace eval msgcat { + # set default locale, try to get from environment + if {[info exists ::env(LANG)]} { + mclocale $::env(LANG) + } else { + mclocale "C" + } +} ADDED library/msgcat1.0/pkgIndex.tcl Index: library/msgcat1.0/pkgIndex.tcl ================================================================== --- /dev/null +++ library/msgcat1.0/pkgIndex.tcl @@ -0,0 +1,1 @@ +package ifneeded msgcat 1.0 [list source [file join $dir msgcat.tcl]] ADDED library/opt/optparse.tcl Index: library/opt/optparse.tcl ================================================================== --- /dev/null +++ library/opt/optparse.tcl @@ -0,0 +1,1097 @@ +# 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. +# +# RCS: @(#) $Id: optparse.tcl,v 1.1.2.2 1999/03/12 23:20:44 rjohnson Exp $ + +package provide opt 0.4.1 + +namespace eval ::tcl { + + # Exported APIs + namespace export OptKeyRegister OptKeyDelete OptKeyError OptKeyParse \ + OptProc OptProcArgGiven OptParse \ + Lempty Lget \ + Lassign Lvarpop Lvarpop1 Lvarset Lvarincr Lfirst Lrest \ + 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 ! ############### +# You should really not look any further : +# The following is private unexported undocumented unblessed... code +# time to hit "q" ;-) ! + +# Hmmm... ok, you really want to know ? + +# You've been warned... Here it is... + + # 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 [Lfirst $program] >= 2 +# while +# llength [Lfirst $singleStep] == 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 compare $key ""] == 0} { + # 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 [Lfirst $res]; + 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 [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 namespace current]; + if { ([string match $name "::*"]) + || ([string compare $namespace "::"]==0)} { + # 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 [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} { + Lfirst $lst; + } + # 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 {[Lfirst $item]=="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 [Lfirst $lst] 1 end] { + lappend res [Lget $lst $idx]; + } + return $res; + } + + # Advance to next description + proc OptNextDesc {descName} { + uplevel [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} { + Lfirst $item + } + + # current state + proc OptCurState {descriptions} { + OptState [OptCurDesc $descriptions]; + } + + ####### + # Arguments manipulation + + # Returns the argument that has to be processed now + proc OptCurrentArg {lst} { + Lfirst $lst; + } + # Advance to next argument + proc OptNextArg {argsName} { + uplevel [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 compare "--" $arg] == 0} { + # 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 compare "-help" [string tolower $arglist]] == 0} { + 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 {![regexp {^(-+)?[0-9]+$} $arg]} { + error "not an integer" + } + return $arg; + } + float { + return [expr {double($arg)}] + } + script - + list { + # if llength fail : malformed list + if {[llength $arg]==0} { + if {[OptIsFlag $arg]} { + error "no values with leading -" + } + } + return $arg; + } + boolean { + if {![regexp -nocase {^(true|false|0|1)$} $arg]} { + error "non canonic boolean" + } + # convert true/false because expr/if is broken with "!,... + if {$arg} { + return 1 + } else { + return 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 compare $larg $lflag]==0} { + # Exact match case + OptSetPrgCounter desc $i; + return 1; + } + } else { + if {[string compare $larg [string range $lflag 0 $last]]==0} { + 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} { + string compare [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 compare $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 compare $type "string"] == 0} { + 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 lasy type determination + proc OptGuessType {arg} { + if {[regexp -nocase {^(true|false)$} $arg]} { + return boolean + } + if {[regexp {^(-+)?[0-9]+$} $arg]} { + return int + } + if {![catch {expr {double($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 [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 [Lfirst $indexLst]] [Lrest $indexLst]; +} +# 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 [Lfirst $indexLst]; + 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 [Lrest $indexLst] $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 [Lfirst $indexLst]; + set targetList [lindex $list $idx]; + # reduce refcount on targetList + Lvarset1nc list $idx {}; + # recursively replace in targetList + Lvarincr targetList [Lrest $indexLst] $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; +} +# Returns the first element of a list +proc ::tcl::Lfirst {list} { + lindex $list 0 +} +# Returns the rest of the list minus first element +proc ::tcl::Lrest {list} { + lrange $list 1 end +} +# 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 [Lfirst $list]; + 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 [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 {} +} ADDED library/opt/pkgIndex.tcl Index: library/opt/pkgIndex.tcl ================================================================== --- /dev/null +++ library/opt/pkgIndex.tcl @@ -0,0 +1,11 @@ +# 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. + +package ifneeded opt 0.4.1 [list source [file join $dir optparse.tcl]] DELETED library/opt0.1/optparse.tcl Index: library/opt0.1/optparse.tcl ================================================================== --- library/opt0.1/optparse.tcl +++ /dev/null @@ -1,1094 +0,0 @@ -# optparse.tcl -- -# -# (Private) option parsing package -# -# This might be documented and exported in 8.1 -# and some function hopefully moved to the C core for -# efficiency, if there is enough demand. (mail! ;-) -# -# Author: Laurent Demailly - Laurent.Demailly@sun.com - dl@mail.box.eu.org -# -# Credits: -# this is a complete 'over kill' rewrite by me, from a version -# written initially with Brent Welch, itself initially -# based on work with Steve Uhler. Thanks them ! -# -# SCCS: @(#) optparse.tcl 1.13 97/08/21 11:50:42 - -package provide opt 0.2 - -namespace eval ::tcl { - - # Exported APIs - namespace export OptKeyRegister OptKeyDelete OptKeyError OptKeyParse \ - OptProc OptProcArgGiven OptParse \ - Lassign Lvarpop Lvarset Lvarincr Lfirst \ - 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 ! ############### -# You should really not look any further : -# The following is private unexported undocumented unblessed... code -# time to hit "q" ;-) ! - -# Hmmm... ok, you really want to know ? - -# You've been warned... Here it is... - - # 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 [Lfirst $program] >= 2 -# while -# llength [Lfirst $singleStep] == 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 compare $key ""] == 0} { - # 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 [Lfirst $res]; - 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 [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 namespace current]; - if { ([string match $name "::*"]) - || ([string compare $namespace "::"]==0)} { - # 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 [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} { - Lfirst $lst; - } - # 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 {[Lfirst $item]=="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 [Lfirst $lst] 1 end] { - lappend res [Lget $lst $idx]; - } - return $res; - } - - # Advance to next description - proc OptNextDesc {descName} { - uplevel [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} { - Lfirst $item - } - - # current state - proc OptCurState {descriptions} { - OptState [OptCurDesc $descriptions]; - } - - ####### - # Arguments manipulation - - # Returns the argument that has to be processed now - proc OptCurrentArg {lst} { - Lfirst $lst; - } - # Advance to next argument - proc OptNextArg {argsName} { - uplevel [list Lvarpop $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]; - } - if {![Lempty $arguments]} { - return -code error [OptTooManyArgs $descriptions $arguments]; - } - } - - # 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")} { - 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 compare "--" $arg] == 0} { - # 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 compare "-help" [string tolower $arglist]] == 0} { - return -code error [OptError "Usage information:" $desc 1]; - } - - OptDoAll 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 ![regexp {^(-+)?[0-9]+$} $arg] { - error "not an integer" - } - return $arg; - } - float { - return [expr double($arg)] - } - script - - list { - # if llength fail : malformed list - if {[llength $arg]==0} { - if {[OptIsFlag $arg]} { - error "no values with leading -" - } - } - return $arg; - } - boolean { - if ![regexp -nocase {^(true|false|0|1)$} $arg] { - error "non canonic boolean" - } - # convert true/false because expr/if is broken with "!,... - if {$arg} { - return 1 - } else { - return 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 compare $larg $lflag]==0} { - # Exact match case - OptSetPrgCounter desc $i; - return 1; - } - } else { - if {[string compare $larg [string range $lflag 0 $last]]==0} { - 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} { - string compare [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 compare $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 compare $type "string"] == 0} { - 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 lasy type determination - proc OptGuessType {arg} { - if [regexp -nocase {^(true|false)$} $arg] { - return boolean - } - if [regexp {^(-+)?[0-9]+$} $arg] { - return int - } - if ![catch {expr double($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 [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 [Lfirst $indexLst]] [Lrest $indexLst]; -} -# 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 [Lfirst $indexLst]; - 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 [Lrest $indexLst] $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 [Lfirst $indexLst]; - set targetList [lindex $list $idx]; - # reduce refcount on targetList - Lvarset1nc list $idx {}; - # recursively replace in targetList - Lvarincr targetList [Lrest $indexLst] $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; -} -# Returns the first element of a list -proc ::tcl::Lfirst {list} { - lindex $list 0 -} -# Returns the rest of the list minus first element -proc ::tcl::Lrest {list} { - lrange $list 1 end -} -# Removes the first element of a list -proc ::tcl::Lvarpop {listName} { - upvar $listName list; - set list [lrange $list 1 end]; -} -# Same but returns the removed element -proc ::tcl::Lvarpop2 {listName} { - upvar $listName list; - set el [Lfirst $list]; - 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 [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 {} -} DELETED library/opt0.1/pkgIndex.tcl Index: library/opt0.1/pkgIndex.tcl ================================================================== --- library/opt0.1/pkgIndex.tcl +++ /dev/null @@ -1,7 +0,0 @@ -# Tcl package index file, version 1.0 -# This file is NOT generated by the "pkg_mkIndex" command -# because if someone just did "package require opt", let's just load -# the package now, so they can readily use it -# and even "namespace import tcl::*" ... -# (tclPkgSetup just makes things slow and do not work so well with namespaces) -package ifneeded opt 0.2 [list source [file join $dir optparse.tcl]] ADDED library/opt0.4/optparse.tcl Index: library/opt0.4/optparse.tcl ================================================================== --- /dev/null +++ library/opt0.4/optparse.tcl @@ -0,0 +1,1097 @@ +# 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. +# +# RCS: @(#) $Id: optparse.tcl,v 1.1.2.2 1999/03/12 23:20:44 rjohnson Exp $ + +package provide opt 0.4.1 + +namespace eval ::tcl { + + # Exported APIs + namespace export OptKeyRegister OptKeyDelete OptKeyError OptKeyParse \ + OptProc OptProcArgGiven OptParse \ + Lempty Lget \ + Lassign Lvarpop Lvarpop1 Lvarset Lvarincr Lfirst Lrest \ + 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 ! ############### +# You should really not look any further : +# The following is private unexported undocumented unblessed... code +# time to hit "q" ;-) ! + +# Hmmm... ok, you really want to know ? + +# You've been warned... Here it is... + + # 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 [Lfirst $program] >= 2 +# while +# llength [Lfirst $singleStep] == 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 compare $key ""] == 0} { + # 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 [Lfirst $res]; + 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 [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 namespace current]; + if { ([string match $name "::*"]) + || ([string compare $namespace "::"]==0)} { + # 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 [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} { + Lfirst $lst; + } + # 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 {[Lfirst $item]=="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 [Lfirst $lst] 1 end] { + lappend res [Lget $lst $idx]; + } + return $res; + } + + # Advance to next description + proc OptNextDesc {descName} { + uplevel [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} { + Lfirst $item + } + + # current state + proc OptCurState {descriptions} { + OptState [OptCurDesc $descriptions]; + } + + ####### + # Arguments manipulation + + # Returns the argument that has to be processed now + proc OptCurrentArg {lst} { + Lfirst $lst; + } + # Advance to next argument + proc OptNextArg {argsName} { + uplevel [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 compare "--" $arg] == 0} { + # 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 compare "-help" [string tolower $arglist]] == 0} { + 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 {![regexp {^(-+)?[0-9]+$} $arg]} { + error "not an integer" + } + return $arg; + } + float { + return [expr {double($arg)}] + } + script - + list { + # if llength fail : malformed list + if {[llength $arg]==0} { + if {[OptIsFlag $arg]} { + error "no values with leading -" + } + } + return $arg; + } + boolean { + if {![regexp -nocase {^(true|false|0|1)$} $arg]} { + error "non canonic boolean" + } + # convert true/false because expr/if is broken with "!,... + if {$arg} { + return 1 + } else { + return 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 compare $larg $lflag]==0} { + # Exact match case + OptSetPrgCounter desc $i; + return 1; + } + } else { + if {[string compare $larg [string range $lflag 0 $last]]==0} { + 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} { + string compare [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 compare $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 compare $type "string"] == 0} { + 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 lasy type determination + proc OptGuessType {arg} { + if {[regexp -nocase {^(true|false)$} $arg]} { + return boolean + } + if {[regexp {^(-+)?[0-9]+$} $arg]} { + return int + } + if {![catch {expr {double($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 [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 [Lfirst $indexLst]] [Lrest $indexLst]; +} +# 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 [Lfirst $indexLst]; + 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 [Lrest $indexLst] $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 [Lfirst $indexLst]; + set targetList [lindex $list $idx]; + # reduce refcount on targetList + Lvarset1nc list $idx {}; + # recursively replace in targetList + Lvarincr targetList [Lrest $indexLst] $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; +} +# Returns the first element of a list +proc ::tcl::Lfirst {list} { + lindex $list 0 +} +# Returns the rest of the list minus first element +proc ::tcl::Lrest {list} { + lrange $list 1 end +} +# 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 [Lfirst $list]; + 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 [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 {} +} ADDED library/opt0.4/pkgIndex.tcl Index: library/opt0.4/pkgIndex.tcl ================================================================== --- /dev/null +++ library/opt0.4/pkgIndex.tcl @@ -0,0 +1,11 @@ +# 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. + +package ifneeded opt 0.4.1 [list source [file join $dir optparse.tcl]] ADDED library/package.tcl Index: library/package.tcl ================================================================== --- /dev/null +++ library/package.tcl @@ -0,0 +1,473 @@ +# package.tcl -- +# +# utility procs formerly in init.tcl which can be loaded on demand +# for package management. +# +# RCS: @(#) $Id: package.tcl,v 1.1.2.6 1999/04/01 23:21:33 welch Exp $ +# +# Copyright (c) 1991-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. +# + +# pkg_compareExtension -- +# +# Used internally by pkg_mkIndex to compare the extension of a file to +# a given extension. On Windows, it uses a case-insensitive comparison +# because the file system can be file insensitive. +# +# Arguments: +# fileName name of a file whose extension is compared +# ext (optional) The extension to compare against; you must +# provide the starting dot. +# Defaults to [info sharedlibextension] +# +# Results: +# Returns 1 if the extension matches, 0 otherwise + +proc pkg_compareExtension { fileName {ext {}} } { + global tcl_platform + if {[string length $ext] == 0} { + set ext [info sharedlibextension] + } + if {[string compare $tcl_platform(platform) "windows"] == 0} { + return [expr {[string compare \ + [string tolower [file extension $fileName]] \ + [string tolower $ext]] == 0}] + } else { + return [expr {[string compare [file extension $fileName] $ext] == 0}] + } +} + +# pkg_mkIndex -- +# This procedure creates a package index in a given directory. The +# package index consists of a "pkgIndex.tcl" file whose contents are +# a Tcl script that sets up package information with "package require" +# commands. The commands describe all of the packages defined by the +# files given as arguments. +# +# Arguments: +# -direct (optional) If this flag is present, the generated +# code in pkgMkIndex.tcl will cause the package to be +# loaded when "package require" is executed, rather +# than lazily when the first reference to an exported +# procedure in the package is made. +# -verbose (optional) Verbose output; the name of each file that +# was successfully rocessed is printed out. Additionally, +# if processing of a file failed a message is printed. +# -load pat (optional) Preload any packages whose names match +# the pattern. Used to handle DLLs that depend on +# other packages during their Init procedure. +# dir - Name of the directory in which to create the index. +# args - Any number of additional arguments, each giving +# a glob pattern that matches the names of one or +# more shared libraries or Tcl script files in +# dir. + +proc pkg_mkIndex {args} { + global errorCode errorInfo + set usage {"pkg_mkIndex ?-direct? ?-verbose? ?-load pattern? ?--? dir ?pattern ...?"}; + + set argCount [llength $args] + if {$argCount < 1} { + return -code error "wrong # args: should be\n$usage" + } + + set more "" + set direct 0 + set doVerbose 0 + set loadPat "" + for {set idx 0} {$idx < $argCount} {incr idx} { + set flag [lindex $args $idx] + switch -glob -- $flag { + -- { + # done with the flags + incr idx + break + } + -verbose { + set doVerbose 1 + } + -direct { + set direct 1 + append more " -direct" + } + -load { + incr idx + set loadPat [lindex $args $idx] + append more " -load $loadPat" + } + -* { + return -code error "unknown flag $flag: should be\n$usage" + } + default { + # done with the flags + break + } + } + } + + set dir [lindex $args $idx] + set patternList [lrange $args [expr {$idx + 1}] end] + if {[llength $patternList] == 0} { + set patternList [list "*.tcl" "*[info sharedlibextension]"] + } + + append index "# Tcl package index file, version 1.1\n" + append index "# This file is generated by the \"pkg_mkIndex$more\" command\n" + append index "# and sourced either when an application starts up or\n" + append index "# by a \"package unknown\" script. It invokes the\n" + append index "# \"package ifneeded\" command to set up package-related\n" + append index "# information so that packages will be loaded automatically\n" + append index "# in response to \"package require\" commands. When this\n" + append index "# script is sourced, the variable \$dir must contain the\n" + append index "# full path name of this file's directory.\n" + set oldDir [pwd] + cd $dir + + if {[catch {eval glob $patternList} fileList]} { + global errorCode errorInfo + cd $oldDir + return -code error -errorcode $errorCode -errorinfo $errorInfo $fileList + } + foreach file $fileList { + # For each file, figure out what commands and packages it provides. + # To do this, create a child interpreter, load the file into the + # interpreter, and get a list of the new commands and packages + # that are defined. + + if {[string compare $file "pkgIndex.tcl"] == 0} { + continue + } + + # Changed back to the original directory before initializing the + # slave in case TCL_LIBRARY is a relative path (e.g. in the test + # suite). + + cd $oldDir + set c [interp create] + + # Load into the child any packages currently loaded in the parent + # interpreter that match the -load pattern. + + foreach pkg [info loaded] { + if {! [string match $loadPat [lindex $pkg 1]]} { + continue + } + if {[lindex $pkg 1] == "Tk"} { + $c eval {set argv {-geometry +0+0}} + } + if {[catch { + load [lindex $pkg 0] [lindex $pkg 1] $c + } err]} { + if {$doVerbose} { + tclLog "warning: load [lindex $pkg 0] [lindex $pkg 1]\nfailed with: $err" + } + } else { + if {$doVerbose} { + tclLog "loaded [lindex $pkg 0] [lindex $pkg 1]" + } + } + } + cd $dir + + $c eval { + # Stub out the package command so packages can + # require other packages. + + rename package __package_orig + proc package {what args} { + switch -- $what { + require { return ; # ignore transitive requires } + default { eval __package_orig {$what} $args } + } + } + proc tclPkgUnknown args {} + package unknown tclPkgUnknown + + # Stub out the unknown command so package can call + # into each other during their initialilzation. + + proc unknown {args} {} + + # Stub out the auto_import mechanism + + proc auto_import {args} {} + + # reserve the ::tcl namespace for support procs + # and temporary variables. This might make it awkward + # to generate a pkgIndex.tcl file for the ::tcl namespace. + + namespace eval ::tcl { + variable file ;# Current file being processed + variable direct ;# -direct flag value + variable x ;# Loop variable + variable debug ;# For debugging + variable type ;# "load" or "source", for -direct + variable namespaces ;# Existing namespaces (e.g., ::tcl) + variable packages ;# Existing packages (e.g., Tcl) + variable origCmds ;# Existing commands + variable newCmds ;# Newly created commands + variable newPkgs {} ;# Newly created packages + } + } + + $c eval [list set ::tcl::file $file] + $c eval [list set ::tcl::direct $direct] + + # Download needed procedures into the slave because we've + # just deleted the unknown procedure. This doesn't handle + # procedures with default arguments. + + foreach p {pkg_compareExtension} { + $c eval [list proc $p [info args $p] [info body $p]] + } + + if {[catch { + $c eval { + set ::tcl::debug "loading or sourcing" + + # we need to track command defined by each package even in + # the -direct case, because they are needed internally by + # the "partial pkgIndex.tcl" step above. + + proc ::tcl::GetAllNamespaces {{root ::}} { + set list $root + foreach ns [namespace children $root] { + eval lappend list [::tcl::GetAllNamespaces $ns] + } + return $list + } + + # initialize the list of existing namespaces, packages, commands + + foreach ::tcl::x [::tcl::GetAllNamespaces] { + set ::tcl::namespaces($::tcl::x) 1 + } + foreach ::tcl::x [package names] { + set ::tcl::packages($::tcl::x) 1 + } + set ::tcl::origCmds [info commands] + + # Try to load the file if it has the shared library + # extension, otherwise source it. It's important not to + # try to load files that aren't shared libraries, because + # on some systems (like SunOS) the loader will abort the + # whole application when it gets an error. + + if {[pkg_compareExtension $::tcl::file [info sharedlibextension]]} { + # The "file join ." command below is necessary. + # Without it, if the file name has no \'s and we're + # on UNIX, the load command will invoke the + # LD_LIBRARY_PATH search mechanism, which could cause + # the wrong file to be used. + + set ::tcl::debug loading + load [file join . $::tcl::file] + set ::tcl::type load + } else { + set ::tcl::debug sourcing + source $::tcl::file + set ::tcl::type source + } + + # See what new namespaces appeared, and import commands + # from them. Only exported commands go into the index. + + foreach ::tcl::x [::tcl::GetAllNamespaces] { + if {! [info exists ::tcl::namespaces($::tcl::x)]} { + namespace import -force ${::tcl::x}::* + } + } + + # Figure out what commands appeared + + foreach ::tcl::x [info commands] { + set ::tcl::newCmds($::tcl::x) 1 + } + foreach ::tcl::x $::tcl::origCmds { + catch {unset ::tcl::newCmds($::tcl::x)} + } + foreach ::tcl::x [array names ::tcl::newCmds] { + # reverse engineer which namespace a command comes from + + set ::tcl::abs [namespace origin $::tcl::x] + + # special case so that global names have no leading + # ::, this is required by the unknown command + + set ::tcl::abs [auto_qualify $::tcl::abs ::] + + if {[string compare $::tcl::x $::tcl::abs] != 0} { + # Name changed during qualification + + set ::tcl::newCmds($::tcl::abs) 1 + unset ::tcl::newCmds($::tcl::x) + } + } + + # Look through the packages that appeared, and if there is + # a version provided, then record it + + foreach ::tcl::x [package names] { + if {([string compare [package provide $::tcl::x] ""] != 0) \ + && ![info exists ::tcl::packages($::tcl::x)]} { + lappend ::tcl::newPkgs \ + [list $::tcl::x [package provide $::tcl::x]] + } + } + } + } msg] == 1} { + set what [$c eval set ::tcl::debug] + if {$doVerbose} { + tclLog "warning: error while $what $file: $msg" + } + } else { + set type [$c eval set ::tcl::type] + set cmds [lsort [$c eval array names ::tcl::newCmds]] + set pkgs [$c eval set ::tcl::newPkgs] + if {[llength $pkgs] > 1} { + tclLog "warning: \"$file\" provides more than one package ($pkgs)" + } + foreach pkg $pkgs { + # cmds is empty/not used in the direct case + lappend files($pkg) [list $file $type $cmds] + } + + if {$doVerbose} { + tclLog "processed $file" + } + interp delete $c + } + } + + foreach pkg [lsort [array names files]] { + append index "\npackage ifneeded $pkg " + if {$direct} { + set cmdList {} + foreach elem $files($pkg) { + set file [lindex $elem 0] + set type [lindex $elem 1] + lappend cmdList "\[list $type \[file join \$dir\ + [list $file]\]\]" + } + append index [join $cmdList "\\n"] + } else { + append index "\[list tclPkgSetup \$dir [lrange $pkg 0 0]\ + [lrange $pkg 1 1] [list $files($pkg)]\]" + } + } + set f [open pkgIndex.tcl w] + puts $f $index + close $f + cd $oldDir +} + +# tclPkgSetup -- +# This is a utility procedure use by pkgIndex.tcl files. It is invoked +# as part of a "package ifneeded" script. It calls "package provide" +# to indicate that a package is available, then sets entries in the +# auto_index array so that the package's files will be auto-loaded when +# the commands are used. +# +# Arguments: +# dir - Directory containing all the files for this package. +# pkg - Name of the package (no version number). +# version - Version number for the package, such as 2.1.3. +# files - List of files that constitute the package. Each +# element is a sub-list with three elements. The first +# is the name of a file relative to $dir, the second is +# "load" or "source", indicating whether the file is a +# loadable binary or a script to source, and the third +# is a list of commands defined by this file. + +proc tclPkgSetup {dir pkg version files} { + global auto_index + + package provide $pkg $version + foreach fileInfo $files { + set f [lindex $fileInfo 0] + set type [lindex $fileInfo 1] + foreach cmd [lindex $fileInfo 2] { + if {$type == "load"} { + set auto_index($cmd) [list load [file join $dir $f] $pkg] + } else { + set auto_index($cmd) [list source [file join $dir $f]] + } + } + } +} + +# tclMacPkgSearch -- +# The procedure is used on the Macintosh to search a given directory for files +# with a TEXT resource named "pkgIndex". If it exists it is sourced in to the +# interpreter to setup the package database. + +proc tclMacPkgSearch {dir} { + foreach x [glob -nocomplain [file join $dir *.shlb]] { + if {[file isfile $x]} { + set res [resource open $x] + foreach y [resource list TEXT $res] { + if {$y == "pkgIndex"} {source -rsrc pkgIndex} + } + catch {resource close $res} + } + } +} + +# tclPkgUnknown -- +# This procedure provides the default for the "package unknown" function. +# It is invoked when a package that's needed can't be found. It scans +# the auto_path directories and their immediate children looking for +# pkgIndex.tcl files and sources any such files that are found to setup +# the package database. (On the Macintosh we also search for pkgIndex +# TEXT resources in all files.) +# +# Arguments: +# name - Name of desired package. Not used. +# version - Version of desired package. Not used. +# exact - Either "-exact" or omitted. Not used. + +proc tclPkgUnknown {name version {exact {}}} { + global auto_path tcl_platform env + + if {![info exists auto_path]} { + return + } + for {set i [expr {[llength $auto_path] - 1}]} {$i >= 0} {incr i -1} { + # we can't use glob in safe interps, so enclose the following + # in a catch statement + catch { + foreach file [glob -nocomplain [file join [lindex $auto_path $i] \ + * pkgIndex.tcl]] { + set dir [file dirname $file] + if {[catch {source $file} msg]} { + tclLog "error reading package index file $file: $msg" + } + } + } + set dir [lindex $auto_path $i] + set file [file join $dir pkgIndex.tcl] + # safe interps usually don't have "file readable", nor stderr channel + if {[interp issafe] || [file readable $file]} { + if {[catch {source $file} msg] && ![interp issafe]} { + tclLog "error reading package index file $file: $msg" + } + } + # On the Macintosh we also look in the resource fork + # of shared libraries + # We can't use tclMacPkgSearch in safe interps because it uses glob + if {(![interp issafe]) && ($tcl_platform(platform) == "macintosh")} { + set dir [lindex $auto_path $i] + tclMacPkgSearch $dir + foreach x [glob -nocomplain [file join $dir *]] { + if {[file isdirectory $x]} { + set dir $x + tclMacPkgSearch $dir + } + } + } + } +} Index: library/parray.tcl ================================================================== --- library/parray.tcl +++ library/parray.tcl @@ -1,9 +1,9 @@ # parray: # Print the contents of a global array on stdout. # -# SCCS: @(#) parray.tcl 1.9 96/02/16 08:56:44 +# RCS: @(#) $Id: parray.tcl,v 1.1.2.2 1998/09/24 23:59:06 stanton Exp $ # # 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 @@ -10,11 +10,11 @@ # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # proc parray {a {pattern *}} { upvar 1 $a array - if ![array exists array] { + if {![array exists array]} { error "\"$a\" isn't an array" } set maxl 0 foreach name [lsort [array names array $pattern]] { if {[string length $name] > $maxl} { Index: library/safe.tcl ================================================================== --- library/safe.tcl +++ library/safe.tcl @@ -10,35 +10,29 @@ # 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. # -# SCCS: @(#) safe.tcl 1.26 97/08/21 11:57:20 +# RCS: @(#) $Id: safe.tcl,v 1.1.2.4 1999/04/06 00:43:17 redman Exp $ # # 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.2; +package require opt 0.4.1; # Create the safe namespace namespace eval ::safe { # Exported API: namespace export interpCreate interpInit interpConfigure interpDelete \ interpAddToAccessPath interpFindInAccessPath \ setLogCmd ; - -# Proto/dummy declarations for auto_mkIndex -proc ::safe::interpCreate {} {} -proc ::safe::interpInit {} {} -proc ::safe::interpConfigure {} {} - #### # # Setup the arguments parsing # @@ -415,11 +409,11 @@ set token "\$[PathToken $n]"; Lappend [VirtualPathListName $slave] $token; Lappend [PathListName $slave] $path; - Set $nname [expr $n+1]; + Set $nname [expr {$n+1}]; SyncAccessPath $slave; return $token; } @@ -443,10 +437,17 @@ # NB we need to add [namespace current], aliases are always # absolute paths. ::interp alias $slave source {} [namespace current]::AliasSource $slave ::interp alias $slave load {} [namespace current]::AliasLoad $slave + + # This alias lets the slave use the encoding names, convertfrom, + # convertto, and system, but not "encoding system " to set + # the system encoding. + + ::interp alias $slave encoding {} [namespace current]::AliasEncoding \ + $slave # This alias lets the slave have access to a subset of the 'file' # command functionality. AliasSubset $slave file file dir.* join root.* ext.* tail \ @@ -526,11 +527,11 @@ set hook [Set $hookname]; if {![::tcl::Lempty $hook]} { # remove the hook now, otherwise if the hook # calls us somehow, we'll loop Unset $hookname; - if {[catch {eval $hook $slave} err]} { + if {[catch {eval $hook [list $slave]} err]} { Log $slave "Delete hook error ($err)"; } } } @@ -679,11 +680,11 @@ # somehow strip the namespaces 'functionality' out (the danger # is that we would strip valid macintosh "../" queries... : if {[regexp {(::)|(\.\.)} $path]} { error "invalid characters in path $path"; } - set n [expr [Set [PathNumberName $slave]]-1]; + set n [expr {[Set [PathNumberName $slave]]-1}]; for {} {$n>=0} {incr n -1} { # fill the token virtual names with their real value set [PathToken $n] [Set [PathToken $n $slave]]; } # replaces the token by their value @@ -887,7 +888,44 @@ } append pat )\$ ::interp alias $slave $alias {}\ [namespace current]::Subset $slave $target $pat } + + # AliasEncoding is the target of the "encoding" alias in safe interpreters. + + proc AliasEncoding {slave args} { + + set argc [llength $args]; + + set okpat "^(name.*|convert.*)\$" + set subcommand [lindex $args 0] + + if {[regexp $okpat $subcommand]} { + return [eval ::interp invokehidden $slave encoding $subcommand \ + [lrange $args 1 end]] + } + + if {[string match $subcommand system]} { + if {$argc == 1} { + # passed all the tests , lets source it: + if {[catch {::interp invokehidden \ + $slave encoding system} msg]} { + Log $slave $msg; + return -code error "script error"; + } + } else { + set msg "wrong # args: should be \"encoding system\""; + Log $slave $msg; + error $msg; + } + } else { + set msg "wrong # args: should be \"encoding option ?arg ...?\""; + Log $slave $msg; + error $msg; + } + + + return $msg + } } Index: library/tclIndex ================================================================== --- library/tclIndex +++ library/tclIndex @@ -4,27 +4,78 @@ # more commands. Typically each line is a command that # sets an element in the auto_index array, where the # element name is the name of a command and the value is # a script that loads the command. -set auto_index(auto_execok) [list source [file join $dir init.tcl]] -set auto_index(auto_reset) [list source [file join $dir init.tcl]] -set auto_index(auto_mkindex) [list source [file join $dir init.tcl]] -set auto_index(pkg_mkIndex) [list source [file join $dir init.tcl]] -set auto_index(tclPkgSetup) [list source [file join $dir init.tcl]] -set auto_index(tclMacPkgSearch) [list source [file join $dir init.tcl]] -set auto_index(tclPkgUnknown) [list source [file join $dir init.tcl]] -set auto_index(parray) [list source [file join $dir parray.tcl]] +set auto_index(auto_reset) [list source [file join $dir auto.tcl]] +set auto_index(tcl_findLibrary) [list source [file join $dir auto.tcl]] +set auto_index(auto_mkindex) [list source [file join $dir auto.tcl]] +set auto_index(auto_mkindex_old) [list source [file join $dir auto.tcl]] +set auto_index(::auto_mkindex_parser::init) [list source [file join $dir auto.tcl]] +set auto_index(::auto_mkindex_parser::cleanup) [list source [file join $dir auto.tcl]] +set auto_index(::auto_mkindex_parser::mkindex) [list source [file join $dir auto.tcl]] +set auto_index(::auto_mkindex_parser::hook) [list source [file join $dir auto.tcl]] +set auto_index(::auto_mkindex_parser::slavehook) [list source [file join $dir auto.tcl]] +set auto_index(::auto_mkindex_parser::command) [list source [file join $dir auto.tcl]] +set auto_index(::auto_mkindex_parser::commandInit) [list source [file join $dir auto.tcl]] +set auto_index(::auto_mkindex_parser::fullname) [list source [file join $dir auto.tcl]] +set auto_index(history) [list source [file join $dir history.tcl]] +set auto_index(::tcl::HistAdd) [list source [file join $dir history.tcl]] +set auto_index(::tcl::HistKeep) [list source [file join $dir history.tcl]] +set auto_index(::tcl::HistClear) [list source [file join $dir history.tcl]] +set auto_index(::tcl::HistInfo) [list source [file join $dir history.tcl]] +set auto_index(::tcl::HistRedo) [list source [file join $dir history.tcl]] +set auto_index(::tcl::HistIndex) [list source [file join $dir history.tcl]] +set auto_index(::tcl::HistEvent) [list source [file join $dir history.tcl]] +set auto_index(::tcl::HistChange) [list source [file join $dir history.tcl]] set auto_index(tclLdAout) [list source [file join $dir ldAout.tcl]] +set auto_index(pkg_compareExtension) [list source [file join $dir package.tcl]] +set auto_index(pkg_mkIndex) [list source [file join $dir package.tcl]] +set auto_index(tclPkgSetup) [list source [file join $dir package.tcl]] +set auto_index(tclMacPkgSearch) [list source [file join $dir package.tcl]] +set auto_index(tclPkgUnknown) [list source [file join $dir package.tcl]] +set auto_index(parray) [list source [file join $dir parray.tcl]] +set auto_index(::safe::InterpStatics) [list source [file join $dir safe.tcl]] +set auto_index(::safe::InterpNested) [list source [file join $dir safe.tcl]] +set auto_index(::safe::interpCreate) [list source [file join $dir safe.tcl]] +set auto_index(::safe::interpInit) [list source [file join $dir safe.tcl]] +set auto_index(::safe::CheckInterp) [list source [file join $dir safe.tcl]] +set auto_index(::safe::interpConfigure) [list source [file join $dir safe.tcl]] +set auto_index(::safe::InterpCreate) [list source [file join $dir safe.tcl]] +set auto_index(::safe::InterpSetConfig) [list source [file join $dir safe.tcl]] +set auto_index(::safe::interpFindInAccessPath) [list source [file join $dir safe.tcl]] +set auto_index(::safe::interpAddToAccessPath) [list source [file join $dir safe.tcl]] +set auto_index(::safe::InterpInit) [list source [file join $dir safe.tcl]] +set auto_index(::safe::AddSubDirs) [list source [file join $dir safe.tcl]] +set auto_index(::safe::interpDelete) [list source [file join $dir safe.tcl]] +set auto_index(::safe::setLogCmd) [list source [file join $dir safe.tcl]] +set auto_index(::safe::SyncAccessPath) [list source [file join $dir safe.tcl]] +set auto_index(::safe::InterpStateName) [list source [file join $dir safe.tcl]] +set auto_index(::safe::IsInterp) [list source [file join $dir safe.tcl]] +set auto_index(::safe::PathToken) [list source [file join $dir safe.tcl]] +set auto_index(::safe::PathListName) [list source [file join $dir safe.tcl]] +set auto_index(::safe::VirtualPathListName) [list source [file join $dir safe.tcl]] +set auto_index(::safe::PathNumberName) [list source [file join $dir safe.tcl]] +set auto_index(::safe::StaticsOkName) [list source [file join $dir safe.tcl]] +set auto_index(::safe::NestedOkName) [list source [file join $dir safe.tcl]] +set auto_index(::safe::Toplevel) [list source [file join $dir safe.tcl]] +set auto_index(::safe::Set) [list source [file join $dir safe.tcl]] +set auto_index(::safe::Lappend) [list source [file join $dir safe.tcl]] +set auto_index(::safe::Unset) [list source [file join $dir safe.tcl]] +set auto_index(::safe::Exists) [list source [file join $dir safe.tcl]] +set auto_index(::safe::GetAccessPath) [list source [file join $dir safe.tcl]] +set auto_index(::safe::StaticsOk) [list source [file join $dir safe.tcl]] +set auto_index(::safe::NestedOk) [list source [file join $dir safe.tcl]] +set auto_index(::safe::DeleteHookName) [list source [file join $dir safe.tcl]] +set auto_index(::safe::TranslatePath) [list source [file join $dir safe.tcl]] +set auto_index(::safe::Log) [list source [file join $dir safe.tcl]] +set auto_index(::safe::CheckFileName) [list source [file join $dir safe.tcl]] +set auto_index(::safe::AliasSource) [list source [file join $dir safe.tcl]] +set auto_index(::safe::AliasLoad) [list source [file join $dir safe.tcl]] +set auto_index(::safe::FileInAccessPath) [list source [file join $dir safe.tcl]] +set auto_index(::safe::Subset) [list source [file join $dir safe.tcl]] +set auto_index(::safe::AliasSubset) [list source [file join $dir safe.tcl]] set auto_index(tcl_wordBreakAfter) [list source [file join $dir word.tcl]] set auto_index(tcl_wordBreakBefore) [list source [file join $dir word.tcl]] set auto_index(tcl_endOfWord) [list source [file join $dir word.tcl]] set auto_index(tcl_startOfNextWord) [list source [file join $dir word.tcl]] set auto_index(tcl_startOfPreviousWord) [list source [file join $dir word.tcl]] -set auto_index(::safe::interpCreate) [list source [file join $dir safe.tcl]] -set auto_index(::safe::interpInit) [list source [file join $dir safe.tcl]] -set auto_index(::safe::interpConfigure) [list source [file join $dir safe.tcl]] -set auto_index(::safe::interpFindInAccessPath) [list source [file join $dir safe.tcl]] -set auto_index(::safe::interpAddToAccessPath) [list source [file join $dir safe.tcl]] -set auto_index(::safe::interpDelete) [list source [file join $dir safe.tcl]] -set auto_index(::safe::setLogCmd) [list source [file join $dir safe.tcl]] -set auto_index(history) [list source [file join $dir history.tcl]] Index: library/word.tcl ================================================================== --- library/word.tcl +++ library/word.tcl @@ -3,19 +3,16 @@ # 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. # -# SCCS: @(#) word.tcl 1.2 96/11/20 14:07:22 -# -# See the file "license.terms" for information on usage and redistribution -# of this file, and for a DISCLAIMER OF ALL WARRANTIES. -# +# RCS: @(#) $Id: word.tcl,v 1.1.2.2 1998/09/24 23:59:07 stanton Exp $ # The following variables are used to determine which characters are # interpreted as white space. if {$tcl_platform(platform) == "windows"} { @@ -40,12 +37,12 @@ # start - Index into string specifying starting point. proc tcl_wordBreakAfter {str start} { global tcl_nonwordchars tcl_wordchars set str [string range $str $start end] - if [regexp -indices "$tcl_wordchars$tcl_nonwordchars|$tcl_nonwordchars$tcl_wordchars" $str result] { - return [expr [lindex $result 1] + $start] + if {[regexp -indices "$tcl_wordchars$tcl_nonwordchars|$tcl_nonwordchars$tcl_wordchars" $str result]} { + return [expr {[lindex $result 1] + $start}] } return -1 } # tcl_wordBreakBefore -- @@ -62,11 +59,11 @@ proc tcl_wordBreakBefore {str start} { global tcl_nonwordchars tcl_wordchars if {[string compare $start end] == 0} { set start [string length $str] } - if [regexp -indices "^.*($tcl_wordchars$tcl_nonwordchars|$tcl_nonwordchars$tcl_wordchars)" [string range $str 0 $start] result] { + if {[regexp -indices "^.*($tcl_wordchars$tcl_nonwordchars|$tcl_nonwordchars$tcl_wordchars)" [string range $str 0 $start] result]} { return [lindex $result 1] } return -1 } @@ -82,13 +79,13 @@ # str - String to search. # start - Index into string specifying starting point. proc tcl_endOfWord {str start} { global tcl_nonwordchars tcl_wordchars - if [regexp -indices "$tcl_nonwordchars*$tcl_wordchars+$tcl_nonwordchars" \ - [string range $str $start end] result] { - return [expr [lindex $result 1] + $start] + if {[regexp -indices "$tcl_nonwordchars*$tcl_wordchars+$tcl_nonwordchars" \ + [string range $str $start end] result]} { + return [expr {[lindex $result 1] + $start}] } return -1 } # tcl_startOfNextWord -- @@ -103,13 +100,13 @@ # str - String to search. # start - Index into string specifying starting point. proc tcl_startOfNextWord {str start} { global tcl_nonwordchars tcl_wordchars - if [regexp -indices "$tcl_wordchars*$tcl_nonwordchars+$tcl_wordchars" \ - [string range $str $start end] result] { - return [expr [lindex $result 1] + $start] + if {[regexp -indices "$tcl_wordchars*$tcl_nonwordchars+$tcl_wordchars" \ + [string range $str $start end] result]} { + return [expr {[lindex $result 1] + $start}] } return -1 } # tcl_startOfPreviousWord -- @@ -124,12 +121,12 @@ proc tcl_startOfPreviousWord {str start} { global tcl_nonwordchars tcl_wordchars if {[string compare $start end] == 0} { set start [string length $str] } - if [regexp -indices \ + if {[regexp -indices \ "$tcl_nonwordchars*($tcl_wordchars+)$tcl_nonwordchars*\$" \ - [string range $str 0 [expr $start - 1]] result word] { + [string range $str 0 [expr {$start - 1}]] result word]} { return [lindex $word 0] } return -1 } Index: license.terms ================================================================== --- license.terms +++ license.terms @@ -1,9 +1,9 @@ This software is copyrighted by the Regents of the University of -California, Sun Microsystems, Inc., and other parties. The following -terms apply to all files associated with the software unless explicitly -disclaimed in individual files. +California, Sun Microsystems, Inc., Scriptics 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, Index: mac/Background.doc ================================================================== --- mac/Background.doc +++ mac/Background.doc @@ -1,9 +1,9 @@ Notes about the Background Only application template ==================================================== -SCCS: @(#) Background.doc 1.1 97/11/03 17:05:54 +RCS: @(#) $Id: Background.doc,v 1.1.2.1 1998/09/24 23:59:08 stanton Exp $ We have included sample code and project files for making a Background-Only application (BOA) in Tcl. This could be used for server processes (like the Tcl Web-Server). Index: mac/MW_TclAppleScriptHeader.pch ================================================================== --- mac/MW_TclAppleScriptHeader.pch +++ mac/MW_TclAppleScriptHeader.pch @@ -10,20 +10,21 @@ * 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. * - * SCCS: @(#) MW_TclAppleScriptHeader.pch 1.1 97/09/09 16:38:07 + * RCS: @(#) $Id: MW_TclAppleScriptHeader.pch,v 1.1.2.2 1998/11/11 04:08:26 stanton Exp $ */ /* * To use the compilied header you need to set the "Prefix file" in * the "C/C++ Language" preference panel to point to the created * compilied header. The name of the header depends on the * architecture we are compiling for (see the code below). For * example, for a 68k app the prefix file should be: MW_TclHeader68K. */ + #if __POWERPC__ #pragma precompile_target "MW_TclAppleScriptHeaderPPC" #include "MW_TclHeaderPPC" #elif __CFM68K__ #pragma precompile_target "MW_TclAppleScriptHeaderCFM68K" Index: mac/MW_TclHeader.pch ================================================================== --- mac/MW_TclHeader.pch +++ mac/MW_TclHeader.pch @@ -10,11 +10,11 @@ * 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. * - * SCCS: @(#) MW_TclHeader.pch 1.27 97/11/20 18:45:25 + * RCS: @(#) $Id: MW_TclHeader.pch,v 1.1.2.3 1998/11/11 04:08:26 stanton Exp $ */ /* * To use the compilied header you need to set the "Prefix file" in * the "C/C++ Language" preference panel to point to the created @@ -28,77 +28,11 @@ #pragma precompile_target "MW_TclHeaderCFM68K" #else #pragma precompile_target "MW_TclHeader68K" #endif -/* - * Macintosh Tcl must be compiled with certain compiler options to - * ensure that it will work correctly. The following pragmas are - * used to ensure that those options are set correctly. An error - * will occur at compile time if they are not set correctly. - */ - -#if !__option(enumsalwaysint) -#error Tcl requires the Metrowerks setting "Enums always ints". -#endif - -#if !defined(__POWERPC__) -#if !__option(far_data) -#error Tcl requires the Metrowerks setting "Far data". -#endif -#endif - -#if !defined(__POWERPC__) -#if !__option(fourbyteints) -#error Tcl requires the Metrowerks setting "4 byte ints". -#endif -#endif - -#if !defined(__POWERPC__) -#if !__option(IEEEdoubles) -#error Tcl requires the Metrowerks setting "8 byte doubles". -#endif -#endif - -/* - * The define is used most everywhere to tell Tcl (or any Tcl - * extensions) that we are compiling for the Macintosh platform. - */ - -#define MAC_TCL - -/* - * The following defines control the behavior of the Macintosh - * Universial Headers. - */ - -#define SystemSevenOrLater 1 -#define STRICT_CONTROLS 1 -#define STRICT_WINDOWS 1 - -/* - * Define the following symbol if you want - * comprehensive debugging turned on. - */ - -/* #define TCL_DEBUG */ - -#ifdef TCL_DEBUG -# define TCL_MEM_DEBUG -# define TCL_TEST -#endif - - -/* - * For a while, we will continue to use the old routine names, so that - * people with older versions of CodeWarrior will still be able to compile - * the source (albeit they will have to update the project files themselves). - * - * At some point, we will convert over to the new routine names. - */ - -#define OLDROUTINENAMES 1 +#include "tclMacCommonPch.h" /* * Place any includes below that will are needed by the majority of the * and is OK to be in any file in the system. The pragma's are used * to control what functions are exported in the Tcl shared library. @@ -106,7 +40,8 @@ #pragma export on #include "tcl.h" #include "tclMac.h" #include "tclInt.h" -#pragma export off + +#pragma export reset Index: mac/README ================================================================== --- mac/README +++ mac/README @@ -1,12 +1,16 @@ -Tcl 8.0p1 for Macintosh +Tcl 8.1b2 for Macintosh by Ray Johnson -Sun Microsystems Laboratories -rjohnson@eng.sun.com +Scriptics Corporation +rjohnson@scriptics.com +with major help from +Jim Ingham +Cygnus Solutions +jingham@cygnus.com -SCCS: @(#) README 1.30 97/11/20 22:01:16 +RCS: @(#) $Id: README,v 1.1.2.4 1999/02/12 00:57:59 stanton Exp $ 1. Introduction --------------- This is the README file for the Macintosh version of the Tcl @@ -15,38 +19,18 @@ please read the README file in the main Tcl directory. 2. What's new? -------------- -The main new feature is the Tcl compilier. You should certainly -notice the speed improvements. Any problems are probably -generic rather than Mac specific. If you have questions or -comments about the compilier feel free to forward them to the -author of the compilier: Brian Lewis . -Several things were fixed/changed since the a1 release so be -sure to check this out. - -The largest incompatible change on the Mac is the removal of the -following commands: "rm", "rmdir", "mkdir", "mv" and "cp". These -commands were never really supported and their functionality is -superceded by the file command. - -I've also added in a new "AppleScript" command. This was contributed -by Jim Ingham who is a new member of the Tcl group. It's very cool. -The command isn't actually in the core - you need to do a "package -require Tclapplescript" to get access to it. This code is officially -unsupported and will change in the next release. However, the core -functionality is there and is stable enough to use. Documentation -can be found in "AppleScript.html" in the mac subdirectory. - -The resource command has also been rewacked. You can now read and -write any Mac resource. Tcl now has the new (and VERY COOL) binary -command that will allow you to pack and unpack the resources into -useful Tcl code. We will eventually provide Tcl libraries for -accessing the most common resources. - -See the main Tcl README for other features new to Tcl 8.0. +Internationalization! This is the first Tcl release that features +can handle international characters. + +On the Macintosh, the System Encoding is taken from the script of the +Finder Font as set in the Views control panel, or in the Finder +Preferences in OS8.0. + +See the main Tcl README for other features new to Tcl 8. 3. Mac specific features ------------------------ There are several features or enhancements in Tcl that are unique to @@ -61,12 +45,12 @@ for details. * The only command NOT available on the Mac is the exec command. However, we include a Mac only package called Tclapplescript that provides access to Mac's AppleScript system. This command is still - under design & construction. Documentatin can be found in the mac - subdirectory in a file called "AppleScript.html". + under design & construction. Documentatin can be found in the "HTML + Docs:tcl8.1" folder in a file called "AppleScript.html". * The env variable on the Macintosh works rather differently than on Windows or UNIX platforms. Check out the tclvars man page for details. @@ -82,35 +66,36 @@ the file background.doc. If you are writing cross platform code but would still like to use some of these Mac specific commands, please remember to use the tcl_platform variable to special case your code. + 4. The Distribution ------------------- Macintosh Tcl is distributed in three different forms. This should make it easier to only download what you need. The packages are as follows: -mactk8.0.1.sea.hqx +mactk8.1b2.sea.hqx This distribution is a "binary" only release. It contains an installer program that will install a 68k, PowerPC, or Fat version of the "Tcl Shell" and "Wish" applications. In addition, it installs the Tcl & Tk libraries in the Extensions folder inside your System Folder. -mactcltk-full-8.0.1.sea.hqx +mactcltk-full-8.1b2.sea.hqx This release contains the full release of Tcl and Tk for the Macintosh plus the More Files packages which Macintosh Tcl and Tk rely on. -mactcl-source-8.0.1.sea.hqx +mactcl-source-8.1b2.sea.hqx - This release contains the complete source for Tcl 8.0. In + This release contains the complete source for Tcl 8.1. In addition, Metrowerks CodeWarrior libraries and project files are included. However, you must already have the More Files package to compile this code. 5. Documentation @@ -117,17 +102,21 @@ ---------------- The "html" subdirectory contains reference documentation in in the HTML format. You may also find these pages at: - http://sunscript.sun.com/man/tcl8.0/contents.html + http://www.scriptics.com/man/tcl8.1/contents.html Other documentation and sample Tcl scripts can be found at -the Tcl ftp site: +the Tcl archive site: ftp://ftp.neosoft.com/tcl/ +and the Tcl resource center: + + http://www.scriptics.com/resource/ + The internet news group comp.lang.tcl is also a valuable source of information about Tcl. A mailing list is also available (see below). 6. Compiling Tcl @@ -134,18 +123,18 @@ ---------------- In order to compile Macintosh Tcl you must have the following items: - CodeWarrior Pro 1 - Mac Tcl 8.0 (source) + CodeWarrior Pro 2 or 3 + Mac Tcl 8.1 (source) More Files 1.4.3 There are two sets of project files included with the package. The ones -we use for the release are for CodeWarrior Pro 1, and are not compatible +we use for the release are for CodeWarrior Pro 3, and are not compatible with CodeWarrior Gold release 11 and earlier. We have included the files -for earlier versions of CodeWarrior in the folder tcl8.0:mac:CW11 Projects, +for earlier versions of CodeWarrior in the folder tcl8.1:mac:CW11 Projects, but they are unsupported, and a little out of date. As of Tcl8.0p2, the code will also build under CW Pro 2. The only change that needs to be made is that float.mac.c should be replaced by float.c in the MacTcl MSL project file. @@ -181,7 +170,7 @@ * Check out the file bugs.doc for information about known bugs. If you have comments or Bug reports send them to: Jim Ingham -jingham@eng.sun.com +jingham@cygnus.com Index: mac/bugs.doc ================================================================== --- mac/bugs.doc +++ mac/bugs.doc @@ -2,11 +2,11 @@ by Ray Johnson Sun Microsystems Laboratories rjohnson@eng.sun.com -SCCS: @(#) bugs.doc 1.6 97/08/13 18:09:12 +RCS: @(#) $Id: bugs.doc,v 1.1.2.1 1998/09/24 23:59:08 stanton Exp $ This was a new feature as of Tcl7.6b1 and as such I'll started with a clean slate. I currently know of no reproducable bugs. I often get vague reports - but nothing I've been able to confirm. Let me know what bugs you find! Index: mac/libmoto.doc ================================================================== --- mac/libmoto.doc +++ mac/libmoto.doc @@ -1,9 +1,9 @@ Notes about the use of libmoto ------------------------------ -@(#) libmoto.doc 1.1 96/07/17 14:29:48 +RCS: @(#) $Id: libmoto.doc,v 1.1.2.1 1998/09/24 23:59:08 stanton Exp $ First of all, libmoto is not required! If you don't have it, you can simply remove the library reference from the project file and everything should compile just fine. Index: mac/morefiles.doc ================================================================== --- mac/morefiles.doc +++ mac/morefiles.doc @@ -1,9 +1,9 @@ Notes about MoreFiles, dnr.c & other non-Tcl source files --------------------------------------------------------- -@(#) morefiles.doc 1.4 97/08/13 12:57:08 +RCS: @(#) $Id: morefiles.doc,v 1.1.2.1 1998/09/24 23:59:09 stanton Exp $ The Macintosh distribution uses several source files that don't actually ship with Tcl. This sometimes causes problems or confusion to developers. This document should help clear up a few things. Index: mac/porting.notes ================================================================== --- mac/porting.notes +++ mac/porting.notes @@ -1,9 +1,9 @@ Porting Notes ------------- -@(#) porting.notes 1.5 96/07/31 14:59:28 +RCS: @(#) $Id: porting.notes,v 1.1.2.1 1998/09/24 23:59:09 stanton Exp $ Currently, the Macintosh version Tcl only compilies with the CodeWarrior C compilier from MetroWerks. It should be straight forward to port the Tcl source to MPW. Index: mac/tclMac.h ================================================================== --- mac/tclMac.h +++ mac/tclMac.h @@ -6,11 +6,11 @@ * 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. * - * SCCS: @(#) tclMac.h 1.8 97/06/24 18:59:08 + * RCS: @(#) $Id: tclMac.h,v 1.1.2.4 1999/03/10 06:49:24 stanton Exp $ */ #ifndef _TCLMAC #define _TCLMAC @@ -29,73 +29,10 @@ #pragma export on typedef int (*Tcl_MacConvertEventPtr) _ANSI_ARGS_((EventRecord *eventPtr)); -/* - * This is needed by the shells to handle Macintosh events. - */ - -EXTERN void Tcl_MacSetEventProc _ANSI_ARGS_((Tcl_MacConvertEventPtr procPtr)); - -/* - * These routines are useful for handling using scripts from resources - * in the application shell - */ - -EXTERN char * Tcl_MacConvertTextResource _ANSI_ARGS_((Handle resource)); -EXTERN int Tcl_MacEvalResource _ANSI_ARGS_((Tcl_Interp *interp, - char *resourceName, int resourceNumber, char *fileName)); -EXTERN Handle Tcl_MacFindResource _ANSI_ARGS_((Tcl_Interp *interp, - long resourceType, char *resourceName, - int resourceNumber, char *resFileRef, int * releaseIt)); - -/* These routines support the new OSType object type (i.e. the packed 4 - * character type and creator codes). - */ - -EXTERN int Tcl_GetOSTypeFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, OSType *osTypePtr)); -EXTERN void Tcl_SetOSTypeObj _ANSI_ARGS_((Tcl_Obj *objPtr, - OSType osType)); -EXTERN Tcl_Obj * Tcl_NewOSTypeObj _ANSI_ARGS_((OSType osType)); - - - -/* - * The following routines are utility functions in Tcl. They are exported - * here because they are needed in Tk. They are not officially supported, - * however. The first set are from the MoreFiles package. - */ - -EXTERN pascal OSErr FSpGetDirectoryID(const FSSpec *spec, - long *theDirID, Boolean *isDirectory); -EXTERN pascal short FSpOpenResFileCompat(const FSSpec *spec, - SignedByte permission); -EXTERN pascal void FSpCreateResFileCompat(const FSSpec *spec, - OSType creator, OSType fileType, - ScriptCode scriptTag); -/* - * Like the MoreFiles routines these fix problems in the standard - * Mac calls. These routines is from tclMacUtils.h. - */ - -EXTERN int FSpLocationFromPath _ANSI_ARGS_((int length, char *path, - FSSpecPtr theSpec)); -EXTERN OSErr FSpPathFromLocation _ANSI_ARGS_((FSSpecPtr theSpec, - int *length, Handle *fullPath)); - -/* - * These are not in MSL 2.1.2, so we need to export them from the - * Tcl shared library. They are found in the compat directory - * except the panic routine which is found in tclMacPanic.h. - */ - -EXTERN int strncasecmp _ANSI_ARGS_((CONST char *s1, - CONST char *s2, size_t n)); -EXTERN int strcasecmp _ANSI_ARGS_((CONST char *s1, - CONST char *s2)); -EXTERN void panic _ANSI_ARGS_(TCL_VARARGS(char *,format)); +#include "tclPlatDecls.h" #pragma export reset #endif /* _TCLMAC */ Index: mac/tclMacAETE.r ================================================================== --- mac/tclMacAETE.r +++ mac/tclMacAETE.r @@ -10,11 +10,11 @@ * 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. * - * SCCS: @(#) tclMacAETE.r 1.1 97/11/03 17:06:22 + * RCS: @(#) $Id: tclMacAETE.r,v 1.1.2.1 1998/09/24 23:59:09 stanton Exp $ */ #define SystemSevenOrLater 1 #include Index: mac/tclMacAlloc.c ================================================================== --- mac/tclMacAlloc.c +++ mac/tclMacAlloc.c @@ -12,18 +12,19 @@ * 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. * - * SCCS: @(#) tclMacAlloc.c 1.13 97/07/24 14:42:19 + * RCS: @(#) $Id: tclMacAlloc.c,v 1.1.2.3 1999/03/10 06:49:24 stanton Exp $ */ #include "tclMacInt.h" #include "tclInt.h" #include #include #include + /* * Flags that are used by ConfigureMemory to define how the allocator * should work. They can be or'd together. */ @@ -240,10 +241,11 @@ Handle hand; OSErr err; hand = * (Handle *) ((Ptr) ptr - sizeof(Handle)); DisposeHandle(hand); + *hand = NULL; err = MemError(); } /* *---------------------------------------------------------------------- @@ -270,11 +272,13 @@ ListEl * memRecord; while (systemMemory != NULL) { memRecord = systemMemory; systemMemory = memRecord->next; - DisposeHandle(memRecord->memoryHandle); + if (*(memRecord->memoryHandle) != NULL) { + DisposeHandle(memRecord->memoryHandle); + } DisposePtr((void *) memRecord); } } /* @@ -301,17 +305,21 @@ ListEl * memRecord; while (systemMemory != NULL) { memRecord = systemMemory; systemMemory = memRecord->next; - DisposeHandle(memRecord->memoryHandle); + if (*(memRecord->memoryHandle) != NULL) { + DisposeHandle(memRecord->memoryHandle); + } DisposePtr((void *) memRecord); } while (appMemory != NULL) { memRecord = appMemory; appMemory = memRecord->next; - DisposeHandle(memRecord->memoryHandle); + if (*(memRecord->memoryHandle) != NULL) { + DisposeHandle(memRecord->memoryHandle); + } DisposePtr((void *) memRecord); } } /* Index: mac/tclMacAppInit.c ================================================================== --- mac/tclMacAppInit.c +++ mac/tclMacAppInit.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) tclMacAppInit.c 1.20 97/07/28 11:03:58 + * RCS: @(#) $Id: tclMacAppInit.c,v 1.1.2.4 1999/02/10 23:31:21 stanton Exp $ */ #include "tcl.h" #include "tclInt.h" #include "tclPort.h" @@ -24,12 +24,14 @@ # include short InstallConsole _ANSI_ARGS_((short fd)); #endif #ifdef TCL_TEST -EXTERN int TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp)); +extern int Procbodytest_Init _ANSI_ARGS_((Tcl_Interp *interp)); +extern int Procbodytest_SafeInit _ANSI_ARGS_((Tcl_Interp *interp)); +extern int TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp)); +extern int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp)); #endif /* TCL_TEST */ /* * Forward declarations for procedures defined later in this file: */ @@ -81,11 +83,11 @@ * 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 interp->result if an error occurs. + * message in the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- @@ -106,10 +108,15 @@ Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, (Tcl_PackageInitProc *) NULL); if (TclObjTest_Init(interp) == TCL_ERROR) { return TCL_ERROR; } + if (Procbodytest_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "procbodytest", Procbodytest_Init, + Procbodytest_SafeInit); #endif /* TCL_TEST */ /* * Call the init procedures for included packages. Each call should * look like this: Index: mac/tclMacApplication.r ================================================================== --- mac/tclMacApplication.r +++ mac/tclMacApplication.r @@ -8,11 +8,11 @@ * 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. * - * SCCS: @(#) tclMacApplication.r 1.2 97/06/20 11:27:07 + * RCS: @(#) $Id: tclMacApplication.r,v 1.1.2.1 1998/09/24 23:59:10 stanton Exp $ */ #include #include Index: mac/tclMacBOAAppInit.c ================================================================== --- mac/tclMacBOAAppInit.c +++ mac/tclMacBOAAppInit.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) tclMacBOAAppInit.c 1.1 97/11/03 17:06:21 + * RCS: @(#) $Id: tclMacBOAAppInit.c,v 1.1.2.2 1998/09/24 23:59:10 stanton Exp $ */ #include "tcl.h" #include "tclInt.h" #include "tclPort.h" @@ -95,11 +95,11 @@ * 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 interp->result if an error occurs. + * message in the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- Index: mac/tclMacBOAMain.c ================================================================== --- mac/tclMacBOAMain.c +++ mac/tclMacBOAMain.c @@ -6,11 +6,11 @@ * 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. * - * SCCS: @(#) tclMacBOAMain.c 1.1 97/11/03 17:06:22 + * RCS: @(#) $Id: tclMacBOAMain.c,v 1.1.2.2 1998/09/24 23:59:10 stanton Exp $ */ #include "tcl.h" #include "tclInt.h" #include "tclMacInt.h" @@ -145,18 +145,20 @@ /* * Invoke application-specific initialization. */ if ((*appInitProc)(interp) != TCL_OK) { - Tcl_DString errStr; - Tcl_DStringInit(&errStr); - Tcl_DStringAppend(&errStr, - "application-specific initialization failed: \n", -1); - Tcl_DStringAppend(&errStr, interp->result, -1); - Tcl_DStringAppend(&errStr, "\n", 1); - TclMacDoNotification(Tcl_DStringValue(&errStr)); - goto done; + Tcl_DString errStr; + + Tcl_DStringInit(&errStr); + Tcl_DStringAppend(&errStr, + "application-specific initialization failed: \n", -1); + Tcl_DStringAppend(&errStr, Tcl_GetStringResult(interp), -1); + Tcl_DStringAppend(&errStr, "\n", 1); + TclMacDoNotification(Tcl_DStringValue(&errStr)); + Tcl_DStringFree(&errStr); + goto done; } /* * Install the BGNotify command: */ @@ -190,14 +192,13 @@ Tcl_DStringInit(&errStr); Tcl_DStringAppend(&errStr, " Error sourcing resource or file: ", -1); Tcl_DStringAppend(&errStr, fileName, -1); Tcl_DStringAppend(&errStr, "\n\nError was: ", -1); - Tcl_DStringAppend(&errStr, interp->result, -1); - + Tcl_DStringAppend(&errStr, Tcl_GetStringResult(interp), -1); TclMacDoNotification(Tcl_DStringValue(&errStr)); - + Tcl_DStringFree(&errStr); } goto done; } @@ -310,11 +311,11 @@ if ( objc != 2 ) { Tcl_WrongNumArgs(interp, 1, objv, "message"); return TCL_ERROR; } - TclMacDoNotification(Tcl_GetStringFromObj(objv[1], (int *) NULL)); + TclMacDoNotification(Tcl_GetString(objv[1])); return TCL_OK; } Index: mac/tclMacChan.c ================================================================== --- mac/tclMacChan.c +++ mac/tclMacChan.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) tclMacChan.c 1.43 97/06/20 11:27:48 + * RCS: @(#) $Id: tclMacChan.c,v 1.1.2.4 1999/04/14 00:34:52 surles Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclMacInt.h" @@ -23,16 +23,10 @@ #include #include #include #include -/* - * The following variable is used to tell whether this module has been - * initialized. - */ - -static int initialized = 0; /* * The following are flags returned by GetOpenMode. They * are or'd together to determine how opening and handling * a file should occur. @@ -64,16 +58,20 @@ int volumeRef; /* Flag to tell if in O_APPEND mode or not. */ int pending; /* 1 if message is pending on queue. */ struct FileState *nextPtr; /* Pointer to next registered file. */ } FileState; -/* - * The following pointer refers to the head of the list of files managed - * that are being watched for file events. - */ +typedef struct ThreadSpecificData { + int initialized; /* True after the thread initializes */ + FileState *firstFilePtr; /* the head of the list of files managed + * that are being watched for file events. */ + Tcl_Channel stdinChannel; + Tcl_Channel stdoutChannel; /* Note - these seem unused */ + Tcl_Channel stderrChannel; +} ThreadSpecificData; -static FileState *firstFilePtr; +static Tcl_ThreadDataKey dataKey; /* * The following structure is what is added to the Tcl event queue when * file events are generated. */ @@ -104,23 +102,23 @@ int flags)); static int FileClose _ANSI_ARGS_((ClientData instanceData, Tcl_Interp *interp)); static int FileEventProc _ANSI_ARGS_((Tcl_Event *evPtr, int flags)); -static void FileInit _ANSI_ARGS_((void)); +static ThreadSpecificData *FileInit _ANSI_ARGS_((void)); static int FileInput _ANSI_ARGS_((ClientData instanceData, char *buf, int toRead, int *errorCode)); static int FileOutput _ANSI_ARGS_((ClientData instanceData, char *buf, int toWrite, int *errorCode)); static int FileSeek _ANSI_ARGS_((ClientData instanceData, long offset, int mode, int *errorCode)); static void FileSetupProc _ANSI_ARGS_((ClientData clientData, int flags)); static int GetOpenMode _ANSI_ARGS_((Tcl_Interp *interp, - char *string)); -static Tcl_Channel OpenFileChannel _ANSI_ARGS_((char *fileName, int mode, - int permissions, int *errorCodePtr)); + CONST char *string)); +static Tcl_Channel OpenFileChannel _ANSI_ARGS_((CONST char *fileName, + int mode, int permissions, int *errorCodePtr)); static int StdIOBlockMode _ANSI_ARGS_((ClientData instanceData, int mode)); static int StdIOClose _ANSI_ARGS_((ClientData instanceData, Tcl_Interp *interp)); static int StdIOInput _ANSI_ARGS_((ClientData instanceData, @@ -175,17 +173,10 @@ typedef void (*TclGetStdChannelsProc) _ANSI_ARGS_((Tcl_Channel *stdinPtr, Tcl_Channel *stdoutPtr, Tcl_Channel *stderrPtr)); TclGetStdChannelsProc getStdChannelsProc = NULL; -/* - * Static variables to hold channels for stdin, stdout and stderr. - */ - -static Tcl_Channel stdinChannel = NULL; -static Tcl_Channel stdoutChannel = NULL; -static Tcl_Channel stderrChannel = NULL; /* *---------------------------------------------------------------------- * * FileInit -- @@ -199,17 +190,22 @@ * Creates a new event source. * *---------------------------------------------------------------------- */ -static void +static ThreadSpecificData * FileInit() { - initialized = 1; - firstFilePtr = NULL; - Tcl_CreateEventSource(FileSetupProc, FileCheckProc, NULL); - Tcl_CreateExitHandler(FileChannelExitHandler, NULL); + 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; } /* *---------------------------------------------------------------------- * @@ -230,11 +226,10 @@ static void FileChannelExitHandler( ClientData clientData) /* Old window proc */ { Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL); - initialized = 0; } /* *---------------------------------------------------------------------- * @@ -257,20 +252,22 @@ ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { FileState *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 = firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { + for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; + infoPtr = infoPtr->nextPtr) { if (infoPtr->watchMask) { Tcl_SetMaxBlockTime(&blockTime); break; } } @@ -300,10 +297,11 @@ { FileEvent *evPtr; FileState *infoPtr; int sentMsg = 0; Tcl_Time blockTime = { 0, 0 }; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } @@ -311,11 +309,12 @@ * 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 = firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { + for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; + infoPtr = infoPtr->nextPtr) { if (infoPtr->watchMask && !infoPtr->pending) { infoPtr->pending = 1; evPtr = (FileEvent *) ckalloc(sizeof(FileEvent)); evPtr->header.proc = FileEventProc; evPtr->infoPtr = infoPtr; @@ -350,10 +349,11 @@ int flags) /* Flags that indicate what events to * handle, such as TCL_FILE_EVENTS. */ { FileEvent *fileEvPtr = (FileEvent *)evPtr; FileState *infoPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; } @@ -362,11 +362,12 @@ * 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 = firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { + for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; + infoPtr = infoPtr->nextPtr) { if (fileEvPtr->infoPtr == infoPtr) { infoPtr->pending = 0; Tcl_NotifyChannel(infoPtr->fileChan, infoPtr->watchMask); break; } @@ -426,42 +427,44 @@ StdIOClose( ClientData instanceData, /* Unused. */ Tcl_Interp *interp) /* Unused. */ { int fd, errorCode = 0; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Invalidate the stdio cache if necessary. Note that we assume that * the stdio file and channel pointers will become invalid at the same * time. + * Do not close standard channels while in thread-exit. */ fd = (int) ((FileState*)instanceData)->fileRef; - if (fd == 0) { - fd = 0; - stdinChannel = NULL; - } else if (fd == 1) { - stdoutChannel = NULL; - } else if (fd == 2) { - stderrChannel = NULL; - } else { - panic("recieved invalid std file"); - } - - if (close(fd) < 0) { - errorCode = errno; - } - + if (!TclInExit()) { + if (fd == 0) { + tsdPtr->stdinChannel = NULL; + } else if (fd == 1) { + tsdPtr->stdoutChannel = NULL; + } else if (fd == 2) { + tsdPtr->stderrChannel = NULL; + } else { + panic("recieved invalid std file"); + } + + if (close(fd) < 0) { + errorCode = errno; + } + } return errorCode; } /* *---------------------------------------------------------------------- * * CommonGetHandle -- * - * Called from Tcl_GetChannelFile to retrieve OS handles from inside + * Called from Tcl_GetChannelHandle to retrieve OS handles from inside * a file based channel. * * Results: * The appropriate handle or NULL if not present. * @@ -640,11 +643,11 @@ resultPtr = Tcl_GetObjResult(interp); GetCurrentProcess(&psn); sprintf(buf, "0x%08x%08x", psn.highLongOfPSN, psn.lowLongOfPSN); Tcl_SetStringObj(resultPtr, buf, -1); } else { - chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], NULL), + chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } /* @@ -657,11 +660,11 @@ } /* *---------------------------------------------------------------------- * - * TclGetDefaultStdChannel -- + * TclpGetDefaultStdChannel -- * * Constructs a channel for the specified standard OS handle. * * Results: * Returns the specified default standard channel, or NULL. @@ -672,18 +675,18 @@ * *---------------------------------------------------------------------- */ Tcl_Channel -TclGetDefaultStdChannel( +TclpGetDefaultStdChannel( int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */ { Tcl_Channel channel = NULL; int fd = 0; /* Initializations needed to prevent */ int mode = 0; /* compiler warning (used before set). */ char *bufMode = NULL; - char channelName[20]; + char channelName[16 + TCL_INTEGER_SPACE]; int channelPermissions; FileState *fileState; /* * If the channels were not created yet, create them now and @@ -729,11 +732,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_OpenFileChannel -- + * TclpOpenFileChannel -- * * Open an File based channel on Unix systems. * * Results: * The new channel or NULL. If NULL, the output argument @@ -745,11 +748,11 @@ * *---------------------------------------------------------------------- */ Tcl_Channel -Tcl_OpenFileChannel( +TclpOpenFileChannel( Tcl_Interp *interp, /* Interpreter for error reporting; * can be NULL. */ char *fileName, /* Name of file to open. */ char *modeString, /* A list of POSIX open modes or * a string such as "rw". */ @@ -757,25 +760,26 @@ * file, with what modes to create * it? */ { Tcl_Channel chan; int mode; - char *nativeName; - Tcl_DString buffer; + char *native; + Tcl_DString ds, buffer; int errorCode; mode = GetOpenMode(interp, modeString); if (mode == -1) { return NULL; } - nativeName = Tcl_TranslateFileName(interp, fileName, &buffer); - if (nativeName == NULL) { + if (Tcl_TranslateFileName(interp, fileName, &buffer) == NULL) { return NULL; } - - chan = OpenFileChannel(nativeName, mode, permissions, &errorCode); + native = Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&buffer), + Tcl_DStringLength(&buffer), &ds); + chan = OpenFileChannel(native, mode, permissions, &errorCode); + Tcl_DStringFree(&ds); Tcl_DStringFree(&buffer); if (chan == NULL) { Tcl_SetErrno(errorCode); if (interp != (Tcl_Interp *) NULL) { @@ -804,11 +808,11 @@ *---------------------------------------------------------------------- */ static Tcl_Channel OpenFileChannel( - char *fileName, /* Name of file to open. */ + CONST char *fileName, /* Name of file to open (native). */ int mode, /* Mode for opening file. */ int permissions, /* If the open involves creating a * file, with what modes to create * it? */ int *errorCodePtr) /* Where to store error code. */ @@ -818,11 +822,11 @@ char macPermision; FSSpec fileSpec; OSErr err; short fileRef; FileState *fileState; - char channelName[64]; + char channelName[16 + TCL_INTEGER_SPACE]; /* * Note we use fsRdWrShPerm instead of fsRdWrPerm which allows shared * writes on a file. This isn't common on a mac but is common with * Windows and UNIX and the feature is used by Tcl. @@ -915,10 +919,39 @@ } } return chan; } + +/* + *---------------------------------------------------------------------- + * + * Tcl_MakeFileChannel -- + * + * Makes a Tcl_Channel from an existing OS level file handle. + * + * Results: + * The Tcl_Channel created around the preexisting OS level file handle. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tcl_Channel +Tcl_MakeFileChannel(handle, mode) + ClientData handle; /* OS level handle. */ + int mode; /* ORed combination of TCL_READABLE and + * TCL_WRITABLE to indicate file mode. */ +{ + /* + * Not implemented yet. + */ + + return NULL; +} /* *---------------------------------------------------------------------- * * FileBlockMode -- @@ -1188,28 +1221,27 @@ * TCL_WRITABLE and TCL_EXCEPTION. */ { FileState **nextPtrPtr, *ptr; FileState *infoPtr = (FileState *) instanceData; int oldMask = infoPtr->watchMask; + ThreadSpecificData *tsdPtr; - if (!initialized) { - FileInit(); - } + tsdPtr = FileInit(); infoPtr->watchMask = mask; if (infoPtr->watchMask) { if (!oldMask) { - infoPtr->nextPtr = firstFilePtr; - firstFilePtr = infoPtr; + infoPtr->nextPtr = tsdPtr->firstFilePtr; + tsdPtr->firstFilePtr = infoPtr; } } else { if (oldMask) { /* * Remove the file from the list of watched files. */ - for (nextPtrPtr = &firstFilePtr, ptr = *nextPtrPtr; + for (nextPtrPtr = &(tsdPtr->firstFilePtr), ptr = *nextPtrPtr; ptr != NULL; nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) { if (infoPtr == ptr) { *nextPtrPtr = ptr->nextPtr; break; @@ -1229,11 +1261,11 @@ * a flag to indicate whether the caller should seek to EOF during * opening of the file. * * Results: * On success, returns mode to pass to "open". If an error occurs, the - * returns -1 and if interp is not NULL, sets interp->result to an + * returns -1 and if interp is not NULL, sets the interp's result to an * error message. * * Side effects: * Sets the integer referenced by seekFlagPtr to 1 if the caller * should seek to EOF during opening the file. @@ -1247,11 +1279,11 @@ static int GetOpenMode( Tcl_Interp *interp, /* Interpreter to use for error * reporting - may be NULL. */ - char *string) /* Mode string, e.g. "r+" or + CONST char *string) /* Mode string, e.g. "r+" or * "RDONLY CREAT". */ { int mode, modeArgc, c, i, gotRW; char **modeArgv, *flag; @@ -1260,11 +1292,17 @@ * are distinguished from the POSIX access modes by the presence * of a lower-case first letter. */ mode = 0; - if (islower(UCHAR(string[0]))) { + /* + * Guard against international characters before using byte oriented + * routines. + */ + + if (!(string[0] & 0x80) + && islower(UCHAR(string[0]))) { /* INTL: ISO only. */ switch (string[0]) { case 'r': mode = TCL_RDONLY; break; case 'w': Index: mac/tclMacDNR.c ================================================================== --- mac/tclMacDNR.c +++ mac/tclMacDNR.c @@ -13,11 +13,11 @@ * 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. * - * SCCS: @(#) tclMacDNR.c 1.2 97/01/28 10:37:21 + * RCS: @(#) $Id: tclMacDNR.c,v 1.1.2.1 1998/09/24 23:59:10 stanton Exp $ */ #pragma ANSI_strict off #include #pragma ANSI_strict reset Index: mac/tclMacEnv.c ================================================================== --- mac/tclMacEnv.c +++ mac/tclMacEnv.c @@ -6,11 +6,11 @@ * 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. * - * SCCS: @(#) tclMacEnv.c 1.29 96/12/06 14:19:57 + * RCS: @(#) $Id: tclMacEnv.c,v 1.1.2.1 1998/09/24 23:59:10 stanton Exp $ */ #include #include #include Index: mac/tclMacExit.c ================================================================== --- mac/tclMacExit.c +++ mac/tclMacExit.c @@ -12,11 +12,11 @@ * 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. * - * SCCS: @(#) tclMacExit.c 1.6 97/11/20 18:37:38 + * RCS: @(#) $Id: tclMacExit.c,v 1.1.2.3 1998/12/02 20:08:07 welch Exp $ */ #include "tclInt.h" #include "tclMacInt.h" #include @@ -102,15 +102,31 @@ * *---------------------------------------------------------------------- */ void -TclPlatformExit( +TclpExit( int status) /* Ignored. */ { TclMacExitHandler(); + +/* + * If we are using the Metrowerks Standard Library, then we will call its exit so that it + * will get a chance to clean up temp files, and so forth. It always calls the standard + * ExitToShell, so the Tcl handlers will also get called. + * + * If you have another exit, make sure that it does not patch ExitToShell, and does + * call it. If so, it will probably work as well. + * + */ + +#ifdef __MSL__ + exit(status); +#else ExitToShell(); +#endif + } /* *---------------------------------------------------------------------- * Index: mac/tclMacFCmd.c ================================================================== --- mac/tclMacFCmd.c +++ mac/tclMacFCmd.c @@ -2,16 +2,16 @@ * tclMacFCmd.c -- * * Implements the Macintosh specific portions of the file manipulation * subcommands of the "file" command. * - * Copyright (c) 1996-1997 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclMacFCmd.c 1.22 97/05/20 15:44:26 + * RCS: @(#) $Id: tclMacFCmd.c,v 1.1.2.2 1998/09/24 23:59:11 stanton Exp $ */ #include "tclInt.h" #include "tclMac.h" #include "tclMacInt.h" @@ -29,20 +29,20 @@ /* * Callback for the file attributes code. */ static int GetFileFinderAttributes _ANSI_ARGS_((Tcl_Interp *interp, - int objIndex, char *fileName, + int objIndex, CONST char *fileName, Tcl_Obj **attributePtrPtr)); static int GetFileReadOnly _ANSI_ARGS_((Tcl_Interp *interp, - int objIndex, char *fileName, + int objIndex, CONST char *fileName, Tcl_Obj **readOnlyPtrPtr)); static int SetFileFinderAttributes _ANSI_ARGS_((Tcl_Interp *interp, - int objIndex, char *fileName, + int objIndex, CONST char *fileName, Tcl_Obj *attributePtr)); static int SetFileReadOnly _ANSI_ARGS_((Tcl_Interp *interp, - int objIndex, char *fileName, + int objIndex, CONST char *fileName, Tcl_Obj *readOnlyPtr)); /* * These are indeces into the tclpFileAttrsStrings table below. */ @@ -72,26 +72,37 @@ static pascal Boolean CopyErrHandler _ANSI_ARGS_((OSErr error, short failedOperation, short srcVRefNum, long srcDirID, StringPtr srcName, short dstVRefNum, long dstDirID,StringPtr dstName)); +static int DoCopyDirectory _ANSI_ARGS_((CONST char *src, + CONST char *dst, Tcl_DString *errorPtr)); +static int DoCopyFile _ANSI_ARGS_((CONST char *src, + CONST char *dst)); +static int DoCreateDirectory _ANSI_ARGS_((CONST char *path)); +static int DoDeleteFile _ANSI_ARGS_((CONST char *path)); +static int DoRemoveDirectory _ANSI_ARGS_((CONST char *path, + int recursive, Tcl_DString *errorPtr)); +static int DoRenameFile _ANSI_ARGS_((CONST char *src, + CONST char *dst)); OSErr FSpGetFLockCompat _ANSI_ARGS_((const FSSpec *specPtr, Boolean *lockedPtr)); static OSErr GenerateUniqueName _ANSI_ARGS_((short vRefNum, long dirID1, long dirID2, Str31 uniqueName)); -static OSErr GetFileSpecs _ANSI_ARGS_((char *path, FSSpec *pathSpecPtr, - FSSpec *dirSpecPtr, Boolean *pathExistsPtr, +static OSErr GetFileSpecs _ANSI_ARGS_((CONST char *path, + FSSpec *pathSpecPtr, FSSpec *dirSpecPtr, + Boolean *pathExistsPtr, Boolean *pathIsDirectoryPtr)); static OSErr MoveRename _ANSI_ARGS_((const FSSpec *srcSpecPtr, const FSSpec *dstSpecPtr, StringPtr copyName)); static int Pstrequal _ANSI_ARGS_((ConstStr255Param stringA, ConstStr255Param stringB)); /* *--------------------------------------------------------------------------- * - * TclpRenameFile -- + * TclpRenameFile, 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: @@ -121,12 +132,33 @@ *--------------------------------------------------------------------------- */ int TclpRenameFile( - char *src, /* Pathname of file or dir to be renamed. */ - char *dst) /* New pathname for file or directory. */ + CONST char *src, /* Pathname of file or dir to be renamed + * (UTF-8). */ + CONST char *dst) /* New pathname of file or directory + * (UTF-8). */ +{ + int result; + Tcl_DString srcString, dstString; + + Tcl_UtfToExternalDString(NULL, src, -1, &srcString); + Tcl_UtfToExternalDString(NULL, dst, -1, &dstString); + result = DoRenameFile(Tcl_DStringValue(&srcString), + Tcl_DStringValue(&dstString)); + Tcl_DStringFree(&srcString); + Tcl_DStringFree(&dstString); + return result; +} + +static int +DoRenameFile( + CONST char *src, /* Pathname of file or dir to be renamed + * (native). */ + CONST char *dst) /* New pathname of file or directory + * (native). */ { FSSpec srcFileSpec, dstFileSpec, dstDirSpec; OSErr err; long srcID, dummy; Boolean srcIsDirectory, dstIsDirectory, dstExists, dstLocked; @@ -155,11 +187,11 @@ /* * The following call will remove an empty directory. If it * fails, it's because it wasn't empty. */ - if (TclpRemoveDirectory(dst, 0, NULL) != TCL_OK) { + if (DoRemoveDirectory(dst, 0, NULL) != TCL_OK) { return TCL_ERROR; } /* * Now that that empty directory is gone, we can try @@ -224,507 +256,10 @@ end: if (err != noErr) { errno = TclMacOSErrorToPosixError(err); return TCL_ERROR; } - return TCL_OK; -} - -/* - *--------------------------------------------------------------------------- - * - * TclpCopyFile -- - * - * 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 "". - * - * Side effects: - * This procedure will also copy symbolic links, block, and - * character devices, and fifos. For symbolic links, the links - * themselves will be copied and not what they point to. For the - * other special file types, the directory entry will be copied and - * not the contents of the device that it refers to. - * - *--------------------------------------------------------------------------- - */ - -int -TclpCopyFile( - char *src, /* Pathname of file to be copied. */ - char *dst) /* Pathname of file to copy to. */ -{ - OSErr err, dstErr; - Boolean dstExists, dstIsDirectory, dstLocked; - FSSpec srcFileSpec, dstFileSpec, dstDirSpec, tmpFileSpec; - Str31 tmpName; - - err = FSpLocationFromPath(strlen(src), src, &srcFileSpec); - if (err == noErr) { - err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists, - &dstIsDirectory); - } - if (dstExists) { - if (dstIsDirectory) { - errno = EISDIR; - return TCL_ERROR; - } - err = FSpGetFLockCompat(&dstFileSpec, &dstLocked); - if (dstLocked) { - FSpRstFLockCompat(&dstFileSpec); - } - - /* - * Backup dest file. - */ - - dstErr = GenerateUniqueName(dstFileSpec.vRefNum, dstFileSpec.parID, - dstFileSpec.parID, tmpName); - if (dstErr == noErr) { - dstErr = FSpRenameCompat(&dstFileSpec, tmpName); - } - } - if (err == noErr) { - err = FSpFileCopy(&srcFileSpec, &dstDirSpec, - (StringPtr) dstFileSpec.name, NULL, 0, true); - } - if ((dstExists != false) && (dstErr == noErr)) { - FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID, - tmpName, &tmpFileSpec); - if (err == noErr) { - /* - * Delete backup file. - */ - - FSpDeleteCompat(&tmpFileSpec); - } else { - - /* - * Restore backup file. - */ - - FSpDeleteCompat(&dstFileSpec); - FSpRenameCompat(&tmpFileSpec, dstFileSpec.name); - if (dstLocked) { - FSpSetFLockCompat(&dstFileSpec); - } - } - } - - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *--------------------------------------------------------------------------- - * - * 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 "". - * - * Side effects: - * The file is deleted, even if it is read-only. - * - *--------------------------------------------------------------------------- - */ - -int -TclpDeleteFile( - char *path) /* Pathname of file to be removed. */ -{ - OSErr err; - FSSpec fileSpec; - Boolean isDirectory; - long dirID; - - err = FSpLocationFromPath(strlen(path), path, &fileSpec); - if (err == noErr) { - /* - * Since FSpDeleteCompat will delete an empty directory, make sure - * that this isn't a directory first. - */ - - FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); - if (isDirectory == true) { - errno = EISDIR; - return TCL_ERROR; - } - } - err = FSpDeleteCompat(&fileSpec); - if (err == fLckdErr) { - FSpRstFLockCompat(&fileSpec); - err = FSpDeleteCompat(&fileSpec); - if (err != noErr) { - FSpSetFLockCompat(&fileSpec); - } - } - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *--------------------------------------------------------------------------- - * - * TclpCreateDirectory -- - * - * 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 with the current umask, except that - * permission for u+rwx will always be added. - * - *--------------------------------------------------------------------------- - */ - -int -TclpCreateDirectory( - char *path) /* Pathname of directory to create. */ -{ - OSErr err; - FSSpec dirSpec; - long outDirID; - - err = FSpLocationFromPath(strlen(path), path, &dirSpec); - if (err == noErr) { - err = dupFNErr; /* EEXIST. */ - } else if (err == fnfErr) { - err = FSpDirCreateCompat(&dirSpec, smSystemScript, &outDirID); - } - - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *--------------------------------------------------------------------------- - * - * TclpCopyDirectory -- - * - * 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 -TclpCopyDirectory( - char *src, /* Pathname of directory to be copied. */ - char *dst, /* Pathname of target directory. */ - Tcl_DString *errorPtr) /* If non-NULL, initialized DString for - * error reporting. */ -{ - OSErr err, saveErr; - long srcID, tmpDirID; - FSSpec srcFileSpec, dstFileSpec, dstDirSpec, tmpDirSpec, tmpFileSpec; - Boolean srcIsDirectory, srcLocked; - Boolean dstIsDirectory, dstExists; - Str31 tmpName; - - err = FSpLocationFromPath(strlen(src), src, &srcFileSpec); - if (err == noErr) { - err = FSpGetDirectoryID(&srcFileSpec, &srcID, &srcIsDirectory); - } - if (err == noErr) { - if (srcIsDirectory == false) { - err = afpObjectTypeErr; /* ENOTDIR. */ - } - } - if (err == noErr) { - err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists, - &dstIsDirectory); - } - if (dstExists) { - if (dstIsDirectory == false) { - err = afpObjectTypeErr; /* ENOTDIR. */ - } else { - err = dupFNErr; /* EEXIST. */ - } - } - if (err != noErr) { - goto done; - } - if ((srcFileSpec.vRefNum == dstFileSpec.vRefNum) && - (srcFileSpec.parID == dstFileSpec.parID) && - (Pstrequal(srcFileSpec.name, dstFileSpec.name) != 0)) { - /* - * Copying on top of self. No-op. - */ - - goto done; - } - - /* - * This algorthm will work making a copy of the source directory in - * the current directory with a new name, in a new directory with the - * same name, and in a new directory with a new name: - * - * 1. Make dstDir/tmpDir. - * 2. Copy srcDir/src to dstDir/tmpDir/src - * 3. Rename dstDir/tmpDir/src to dstDir/tmpDir/dst (if necessary). - * 4. CatMove dstDir/tmpDir/dst to dstDir/dst. - * 5. Remove dstDir/tmpDir. - */ - - err = FSpGetFLockCompat(&srcFileSpec, &srcLocked); - if (srcLocked) { - FSpRstFLockCompat(&srcFileSpec); - } - if (err == noErr) { - err = GenerateUniqueName(dstFileSpec.vRefNum, dstFileSpec.parID, - dstFileSpec.parID, tmpName); - } - if (err == noErr) { - FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID, - tmpName, &tmpDirSpec); - err = FSpDirCreateCompat(&tmpDirSpec, smSystemScript, &tmpDirID); - } - if (err == noErr) { - err = FSpDirectoryCopy(&srcFileSpec, &tmpDirSpec, NULL, 0, true, - CopyErrHandler); - } - - /* - * Even if the Copy failed, Rename/Move whatever did get copied to the - * appropriate final destination, if possible. - */ - - saveErr = err; - err = noErr; - if (Pstrequal(srcFileSpec.name, dstFileSpec.name) == 0) { - err = FSMakeFSSpecCompat(tmpDirSpec.vRefNum, tmpDirID, - srcFileSpec.name, &tmpFileSpec); - if (err == noErr) { - err = FSpRenameCompat(&tmpFileSpec, dstFileSpec.name); - } - } - if (err == noErr) { - err = FSMakeFSSpecCompat(tmpDirSpec.vRefNum, tmpDirID, - dstFileSpec.name, &tmpFileSpec); - } - if (err == noErr) { - err = FSpCatMoveCompat(&tmpFileSpec, &dstDirSpec); - } - if (err == noErr) { - if (srcLocked) { - FSpSetFLockCompat(&dstFileSpec); - } - } - - FSpDeleteCompat(&tmpDirSpec); - - if (saveErr != noErr) { - err = saveErr; - } - - done: - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - if (errorPtr != NULL) { - Tcl_DStringAppend(errorPtr, dst, -1); - } - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * CopyErrHandler -- - * - * This procedure is called from the MoreFiles procedure - * FSpDirectoryCopy whenever an error occurs. - * - * Results: - * False if the condition should not be considered an error, true - * otherwise. - * - * Side effects: - * Since FSpDirectoryCopy() is called only after removing any - * existing target directories, there shouldn't be any errors. - * - *---------------------------------------------------------------------- - */ - -static pascal Boolean -CopyErrHandler( - OSErr error, /* Error that occured */ - short failedOperation, /* operation that caused the error */ - short srcVRefNum, /* volume ref number of source */ - long srcDirID, /* directory id of source */ - StringPtr srcName, /* name of source */ - short dstVRefNum, /* volume ref number of dst */ - long dstDirID, /* directory id of dst */ - StringPtr dstName) /* name of dst directory */ -{ - return true; -} - -/* - *--------------------------------------------------------------------------- - * - * TclpRemoveDirectory -- - * - * 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 a root directory. - * ENOENT: path doesn't exist or is "". - * ENOTDIR: path is not a directory. - * - * Side effects: - * Directory removed. If an error occurs, the error will be returned - * immediately, and remaining files will not be deleted. - * - *--------------------------------------------------------------------------- - */ - -int -TclpRemoveDirectory( - char *path, /* Pathname of directory to be removed. */ - int recursive, /* If non-zero, removes directories that - * are nonempty. Otherwise, will only remove - * empty directories. */ - Tcl_DString *errorPtr) /* If non-NULL, initialized DString for - * error reporting. */ -{ - OSErr err; - FSSpec fileSpec; - long dirID; - int locked; - Boolean isDirectory; - CInfoPBRec pb; - Str255 fileName; - - locked = 0; - err = FSpLocationFromPath(strlen(path), path, &fileSpec); - if (err != noErr) { - goto done; - } - - /* - * Since FSpDeleteCompat will delete a file, make sure this isn't - * a file first. - */ - - isDirectory = 1; - FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); - if (isDirectory == 0) { - errno = ENOTDIR; - return TCL_ERROR; - } - - err = FSpDeleteCompat(&fileSpec); - if (err == fLckdErr) { - locked = 1; - FSpRstFLockCompat(&fileSpec); - err = FSpDeleteCompat(&fileSpec); - } - if (err == noErr) { - return TCL_OK; - } - if (err != fBsyErr) { - goto done; - } - - if (recursive == 0) { - /* - * fBsyErr means one of three things: file busy, directory not empty, - * or working directory control block open. Determine if directory - * is empty. If directory is not empty, return EEXIST. - */ - - pb.hFileInfo.ioVRefNum = fileSpec.vRefNum; - pb.hFileInfo.ioDirID = dirID; - pb.hFileInfo.ioNamePtr = (StringPtr) fileName; - pb.hFileInfo.ioFDirIndex = 1; - if (PBGetCatInfoSync(&pb) == noErr) { - err = dupFNErr; /* EEXIST */ - goto done; - } - } - - /* - * DeleteDirectory removes a directory and all its contents, including - * any locked files. There is no interface to get the name of the - * file that caused the error, if an error occurs deleting this tree, - * unless we rewrite DeleteDirectory ourselves. - */ - - err = DeleteDirectory(fileSpec.vRefNum, dirID, NULL); - - done: - if (err != noErr) { - if (errorPtr != NULL) { - Tcl_DStringAppend(errorPtr, path, -1); - } - if (locked) { - FSpSetFLockCompat(&fileSpec); - } - errno = TclMacOSErrorToPosixError(err); - return TCL_ERROR; - } return TCL_OK; } /* *-------------------------------------------------------------------------- @@ -842,15 +377,603 @@ FSpSetFLockCompat(srcFileSpecPtr); } } return err; } + +/* + *--------------------------------------------------------------------------- + * + * TclpCopyFile, 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 "". + * + * Side effects: + * This procedure will also copy symbolic links, block, and + * character devices, and fifos. For symbolic links, the links + * themselves will be copied and not what they point to. For the + * other special file types, the directory entry will be copied and + * not the contents of the device that it refers to. + * + *--------------------------------------------------------------------------- + */ + +int +TclpCopyFile( + CONST char *src, /* Pathname of file to be copied (UTF-8). */ + CONST char *dst) /* Pathname of file to copy to (UTF-8). */ +{ + int result; + Tcl_DString srcString, dstString; + + Tcl_UtfToExternalDString(NULL, src, -1, &srcString); + Tcl_UtfToExternalDString(NULL, dst, -1, &dstString); + result = DoCopyFile(Tcl_DStringValue(&srcString), + Tcl_DStringValue(&dstString)); + Tcl_DStringFree(&srcString); + Tcl_DStringFree(&dstString); + return result; +} + +static int +DoCopyFile( + CONST char *src, /* Pathname of file to be copied (native). */ + CONST char *dst) /* Pathname of file to copy to (native). */ +{ + OSErr err, dstErr; + Boolean dstExists, dstIsDirectory, dstLocked; + FSSpec srcFileSpec, dstFileSpec, dstDirSpec, tmpFileSpec; + Str31 tmpName; + + err = FSpLocationFromPath(strlen(src), src, &srcFileSpec); + if (err == noErr) { + err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists, + &dstIsDirectory); + } + if (dstExists) { + if (dstIsDirectory) { + errno = EISDIR; + return TCL_ERROR; + } + err = FSpGetFLockCompat(&dstFileSpec, &dstLocked); + if (dstLocked) { + FSpRstFLockCompat(&dstFileSpec); + } + + /* + * Backup dest file. + */ + + dstErr = GenerateUniqueName(dstFileSpec.vRefNum, dstFileSpec.parID, + dstFileSpec.parID, tmpName); + if (dstErr == noErr) { + dstErr = FSpRenameCompat(&dstFileSpec, tmpName); + } + } + if (err == noErr) { + err = FSpFileCopy(&srcFileSpec, &dstDirSpec, + (StringPtr) dstFileSpec.name, NULL, 0, true); + } + if ((dstExists != false) && (dstErr == noErr)) { + FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID, + tmpName, &tmpFileSpec); + if (err == noErr) { + /* + * Delete backup file. + */ + + FSpDeleteCompat(&tmpFileSpec); + } else { + + /* + * Restore backup file. + */ + + FSpDeleteCompat(&dstFileSpec); + FSpRenameCompat(&tmpFileSpec, dstFileSpec.name); + if (dstLocked) { + FSpSetFLockCompat(&dstFileSpec); + } + } + } + + if (err != noErr) { + errno = TclMacOSErrorToPosixError(err); + return TCL_ERROR; + } + return TCL_OK; +} + +/* + *--------------------------------------------------------------------------- + * + * TclpDeleteFile, DoDeleteFile -- + * + * 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 "". + * + * Side effects: + * The file is deleted, even if it is read-only. + * + *--------------------------------------------------------------------------- + */ + +int +TclpDeleteFile( + CONST char *path) /* Pathname of file to be removed (UTF-8). */ +{ + int result; + Tcl_DString pathString; + + Tcl_UtfToExternalDString(NULL, path, -1, &pathString); + result = DoDeleteFile(Tcl_DStringValue(&pathString)); + Tcl_DStringFree(&pathString); + return result; +} + +static int +DoDeleteFile( + CONST char *path) /* Pathname of file to be removed (native). */ +{ + OSErr err; + FSSpec fileSpec; + Boolean isDirectory; + long dirID; + + err = FSpLocationFromPath(strlen(path), path, &fileSpec); + if (err == noErr) { + /* + * Since FSpDeleteCompat will delete an empty directory, make sure + * that this isn't a directory first. + */ + + FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); + if (isDirectory == true) { + errno = EISDIR; + return TCL_ERROR; + } + } + err = FSpDeleteCompat(&fileSpec); + if (err == fLckdErr) { + FSpRstFLockCompat(&fileSpec); + err = FSpDeleteCompat(&fileSpec); + if (err != noErr) { + FSpSetFLockCompat(&fileSpec); + } + } + if (err != noErr) { + errno = TclMacOSErrorToPosixError(err); + return TCL_ERROR; + } + return TCL_OK; +} + +/* + *--------------------------------------------------------------------------- + * + * TclpCreateDirectory, DoCreateDirectory -- + * + * 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 with the current umask, except that + * permission for u+rwx will always be added. + * + *--------------------------------------------------------------------------- + */ + +int +TclpCreateDirectory( + CONST char *path) /* Pathname of directory to create (UTF-8). */ +{ + int result; + Tcl_DString pathString; + + Tcl_UtfToExternalDString(NULL, path, -1, &pathString); + result = DoCreateDirectory(Tcl_DStringValue(&pathString)); + Tcl_DStringFree(&pathString); + return result; +} + +static int +DoCreateDirectory( + CONST char *path) /* Pathname of directory to create (native). */ +{ + OSErr err; + FSSpec dirSpec; + long outDirID; + + err = FSpLocationFromPath(strlen(path), path, &dirSpec); + if (err == noErr) { + err = dupFNErr; /* EEXIST. */ + } else if (err == fnfErr) { + err = FSpDirCreateCompat(&dirSpec, smSystemScript, &outDirID); + } + + if (err != noErr) { + errno = TclMacOSErrorToPosixError(err); + return TCL_ERROR; + } + return TCL_OK; +} + +/* + *--------------------------------------------------------------------------- + * + * TclpCopyDirectory, DoCopyDirectory -- + * + * 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 +TclpCopyDirectory( + CONST char *src, /* Pathname of directory to be copied + * (UTF-8). */ + CONST char *dst, /* Pathname of target directory (UTF-8). */ + Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free + * DString filled with UTF-8 name of file + * causing error. */ +{ + int result; + Tcl_DString srcString, dstString; + + Tcl_UtfToExternalDString(NULL, src, -1, &srcString); + Tcl_UtfToExternalDString(NULL, dst, -1, &dstString); + result = DoCopyDirectory(Tcl_DStringValue(&srcString), + Tcl_DStringValue(&dstString), errorPtr); + Tcl_DStringFree(&srcString); + Tcl_DStringFree(&dstString); + return result; +} + +static int +DoCopyDirectory( + CONST char *src, /* Pathname of directory to be copied + * (UTF-8). */ + CONST char *dst, /* Pathname of target directory (UTF-8). */ + Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free + * DString filled with UTF-8 name of file + * causing error. */ +{ + OSErr err, saveErr; + long srcID, tmpDirID; + FSSpec srcFileSpec, dstFileSpec, dstDirSpec, tmpDirSpec, tmpFileSpec; + Boolean srcIsDirectory, srcLocked; + Boolean dstIsDirectory, dstExists; + Str31 tmpName; + + err = FSpLocationFromPath(strlen(src), src, &srcFileSpec); + if (err == noErr) { + err = FSpGetDirectoryID(&srcFileSpec, &srcID, &srcIsDirectory); + } + if (err == noErr) { + if (srcIsDirectory == false) { + err = afpObjectTypeErr; /* ENOTDIR. */ + } + } + if (err == noErr) { + err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists, + &dstIsDirectory); + } + if (dstExists) { + if (dstIsDirectory == false) { + err = afpObjectTypeErr; /* ENOTDIR. */ + } else { + err = dupFNErr; /* EEXIST. */ + } + } + if (err != noErr) { + goto done; + } + if ((srcFileSpec.vRefNum == dstFileSpec.vRefNum) && + (srcFileSpec.parID == dstFileSpec.parID) && + (Pstrequal(srcFileSpec.name, dstFileSpec.name) != 0)) { + /* + * Copying on top of self. No-op. + */ + + goto done; + } + + /* + * This algorthm will work making a copy of the source directory in + * the current directory with a new name, in a new directory with the + * same name, and in a new directory with a new name: + * + * 1. Make dstDir/tmpDir. + * 2. Copy srcDir/src to dstDir/tmpDir/src + * 3. Rename dstDir/tmpDir/src to dstDir/tmpDir/dst (if necessary). + * 4. CatMove dstDir/tmpDir/dst to dstDir/dst. + * 5. Remove dstDir/tmpDir. + */ + + err = FSpGetFLockCompat(&srcFileSpec, &srcLocked); + if (srcLocked) { + FSpRstFLockCompat(&srcFileSpec); + } + if (err == noErr) { + err = GenerateUniqueName(dstFileSpec.vRefNum, dstFileSpec.parID, + dstFileSpec.parID, tmpName); + } + if (err == noErr) { + FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID, + tmpName, &tmpDirSpec); + err = FSpDirCreateCompat(&tmpDirSpec, smSystemScript, &tmpDirID); + } + if (err == noErr) { + err = FSpDirectoryCopy(&srcFileSpec, &tmpDirSpec, NULL, 0, true, + CopyErrHandler); + } + + /* + * Even if the Copy failed, Rename/Move whatever did get copied to the + * appropriate final destination, if possible. + */ + + saveErr = err; + err = noErr; + if (Pstrequal(srcFileSpec.name, dstFileSpec.name) == 0) { + err = FSMakeFSSpecCompat(tmpDirSpec.vRefNum, tmpDirID, + srcFileSpec.name, &tmpFileSpec); + if (err == noErr) { + err = FSpRenameCompat(&tmpFileSpec, dstFileSpec.name); + } + } + if (err == noErr) { + err = FSMakeFSSpecCompat(tmpDirSpec.vRefNum, tmpDirID, + dstFileSpec.name, &tmpFileSpec); + } + if (err == noErr) { + err = FSpCatMoveCompat(&tmpFileSpec, &dstDirSpec); + } + if (err == noErr) { + if (srcLocked) { + FSpSetFLockCompat(&dstFileSpec); + } + } + + FSpDeleteCompat(&tmpDirSpec); + + if (saveErr != noErr) { + err = saveErr; + } + + done: + if (err != noErr) { + errno = TclMacOSErrorToPosixError(err); + if (errorPtr != NULL) { + Tcl_ExternalToUtfDString(NULL, dst, -1, errorPtr); + } + return TCL_ERROR; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * CopyErrHandler -- + * + * This procedure is called from the MoreFiles procedure + * FSpDirectoryCopy whenever an error occurs. + * + * Results: + * False if the condition should not be considered an error, true + * otherwise. + * + * Side effects: + * Since FSpDirectoryCopy() is called only after removing any + * existing target directories, there shouldn't be any errors. + * + *---------------------------------------------------------------------- + */ + +static pascal Boolean +CopyErrHandler( + OSErr error, /* Error that occured */ + short failedOperation, /* operation that caused the error */ + short srcVRefNum, /* volume ref number of source */ + long srcDirID, /* directory id of source */ + StringPtr srcName, /* name of source */ + short dstVRefNum, /* volume ref number of dst */ + long dstDirID, /* directory id of dst */ + StringPtr dstName) /* name of dst directory */ +{ + return true; +} + +/* + *--------------------------------------------------------------------------- + * + * TclpRemoveDirectory, 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 a root directory. + * ENOENT: path doesn't exist or is "". + * ENOTDIR: path is not a directory. + * + * Side effects: + * Directory removed. If an error occurs, the error will be returned + * immediately, and remaining files will not be deleted. + * + *--------------------------------------------------------------------------- + */ + +int +TclpRemoveDirectory( + CONST char *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_DString *errorPtr) /* If non-NULL, uninitialized or free + * DString filled with UTF-8 name of file + * causing error. */ +{ + int result; + Tcl_DString pathString; + + Tcl_UtfToExternalDString(NULL, path, -1, &pathString); + result = DoRemoveDirectory(Tcl_DStringValue(&pathString), recursive, + errorPtr); + Tcl_DStringFree(&pathString); + + return result; +} + +static int +DoRemoveDirectory( + CONST char *path, /* 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. */ +{ + OSErr err; + FSSpec fileSpec; + long dirID; + int locked; + Boolean isDirectory; + CInfoPBRec pb; + Str255 fileName; + + + locked = 0; + err = FSpLocationFromPath(strlen(path), path, &fileSpec); + if (err != noErr) { + goto done; + } + + /* + * Since FSpDeleteCompat will delete a file, make sure this isn't + * a file first. + */ + + isDirectory = 1; + FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); + if (isDirectory == 0) { + errno = ENOTDIR; + return TCL_ERROR; + } + + err = FSpDeleteCompat(&fileSpec); + if (err == fLckdErr) { + locked = 1; + FSpRstFLockCompat(&fileSpec); + err = FSpDeleteCompat(&fileSpec); + } + if (err == noErr) { + return TCL_OK; + } + if (err != fBsyErr) { + goto done; + } + + if (recursive == 0) { + /* + * fBsyErr means one of three things: file busy, directory not empty, + * or working directory control block open. Determine if directory + * is empty. If directory is not empty, return EEXIST. + */ + + pb.hFileInfo.ioVRefNum = fileSpec.vRefNum; + pb.hFileInfo.ioDirID = dirID; + pb.hFileInfo.ioNamePtr = (StringPtr) fileName; + pb.hFileInfo.ioFDirIndex = 1; + if (PBGetCatInfoSync(&pb) == noErr) { + err = dupFNErr; /* EEXIST */ + goto done; + } + } + + /* + * DeleteDirectory removes a directory and all its contents, including + * any locked files. There is no interface to get the name of the + * file that caused the error, if an error occurs deleting this tree, + * unless we rewrite DeleteDirectory ourselves. + */ + + err = DeleteDirectory(fileSpec.vRefNum, dirID, NULL); + + done: + if (err != noErr) { + if (errorPtr != NULL) { + Tcl_UtfToExternalDString(NULL, path, -1, errorPtr); + } + if (locked) { + FSpSetFLockCompat(&fileSpec); + } + errno = TclMacOSErrorToPosixError(err); + return TCL_ERROR; + } + return TCL_OK; +} /* *--------------------------------------------------------------------------- * - * GetFileSpecs -- + * GenerateUniqueName -- * * Generate a filename that is not in either of the two specified * directories (on the same volume). * * Results: @@ -926,11 +1049,11 @@ *--------------------------------------------------------------------------- */ static OSErr GetFileSpecs( - char *path, /* The path to query. */ + CONST char *path, /* The path to query. */ FSSpec *pathSpecPtr, /* Filled with information about path. */ FSSpec *dirSpecPtr, /* Filled with information about path's * parent directory. */ Boolean *pathExistsPtr, /* Set to true if path actually exists, * false if it doesn't or there was an @@ -1069,11 +1192,11 @@ static int GetFileFinderAttributes( Tcl_Interp *interp, /* The interp to report errors with. */ int objIndex, /* The index of the attribute option. */ - char *fileName, /* The name of the file. */ + CONST char *fileName, /* The name of the file. */ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */ { OSErr err; FSSpec fileSpec; FInfo finfo; @@ -1112,11 +1235,11 @@ } if (err != noErr) { errno = TclMacOSErrorToPosixError(err); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "couldn't get attributes for file \"", fileName, "\": ", + "could not read \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } return TCL_OK; } @@ -1144,11 +1267,11 @@ static int GetFileReadOnly( Tcl_Interp *interp, /* The interp to report errors with. */ int objIndex, /* The index of the attribute. */ - char *fileName, /* The name of the file. */ + CONST char *fileName, /* The name of the file. */ Tcl_Obj **readOnlyPtrPtr) /* A pointer to return the object with. */ { OSErr err; FSSpec fileSpec; CInfoPBRec paramBlock; @@ -1177,11 +1300,11 @@ } } if (err != noErr) { errno = TclMacOSErrorToPosixError(err); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "couldn't get attributes for file \"", fileName, "\": ", + "could not read \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } return TCL_OK; } @@ -1205,11 +1328,11 @@ static int SetFileFinderAttributes( Tcl_Interp *interp, /* The interp to report errors with. */ int objIndex, /* The index of the attribute. */ - char *fileName, /* The name of the file. */ + CONST char *fileName, /* The name of the file. */ Tcl_Obj *attributePtr) /* The command line object. */ { OSErr err; FSSpec fileSpec; FInfo finfo; @@ -1265,11 +1388,11 @@ } if (err != noErr) { errno = TclMacOSErrorToPosixError(err); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "couldn't set attributes for file \"", fileName, "\": ", + "could not read \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } return TCL_OK; } @@ -1293,11 +1416,11 @@ static int SetFileReadOnly( Tcl_Interp *interp, /* The interp to report errors with. */ int objIndex, /* The index of the attribute. */ - char *fileName, /* The name of the file. */ + CONST char *fileName, /* The name of the file. */ Tcl_Obj *readOnlyPtr) /* The command line object. */ { OSErr err; FSSpec fileSpec; HParamBlockRec paramBlock; @@ -1336,11 +1459,11 @@ } if (err != noErr) { errno = TclMacOSErrorToPosixError(err); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "couldn't set attributes for file \"", fileName, "\": ", + "could not read \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } return TCL_OK; } @@ -1360,20 +1483,20 @@ * Side effects: * None * *--------------------------------------------------------------------------- */ - int TclpListVolumes( Tcl_Interp *interp) /* Interpreter to which to pass the volume list */ { HParamBlockRec pb; Str255 name; OSErr theError = noErr; Tcl_Obj *resultPtr, *elemPtr; short volIndex = 1; + Tcl_DString dstr; resultPtr = Tcl_NewObj(); /* * We use two facts: @@ -1384,25 +1507,29 @@ * that does not exist. * */ while ( 1 ) { - pb.volumeParam.ioNamePtr = (StringPtr) & name; + pb.volumeParam.ioNamePtr = (StringPtr) &name; pb.volumeParam.ioVolIndex = volIndex; theError = PBHGetVInfoSync(&pb); if ( theError != noErr ) { break; } - - elemPtr = Tcl_NewStringObj((char *) name + 1, (int) name[0]); + + Tcl_ExternalToUtfDString(NULL, (char *) &name[1], name[0], &dstr); + elemPtr = Tcl_NewStringObj(Tcl_DStringValue(&dstr), + Tcl_DStringLength(&dstr)); Tcl_AppendToObj(elemPtr, ":", 1); Tcl_ListObjAppendElement(interp, resultPtr, elemPtr); + + Tcl_DStringFree(&dstr); volIndex++; } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } Index: mac/tclMacFile.c ================================================================== --- mac/tclMacFile.c +++ mac/tclMacFile.c @@ -3,16 +3,16 @@ * * This file implements the channel drivers for Macintosh * files. It also comtains Macintosh version of other Tcl * functions that deal with the file system. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclMacFile.c 1.57 97/04/23 16:23:05 + * RCS: @(#) $Id: tclMacFile.c,v 1.1.2.3 1998/10/06 00:37:43 stanton Exp $ */ /* * Note: This code eventually needs to support async I/O. In doing this * we will need to keep track of all current async I/O. If exit to shell @@ -30,179 +30,25 @@ #include #include #include /* - * Static variables used by the TclMacStat function. + * Static variables used by the TclpStat function. */ -static int initalized = false; +static int initialized = false; static long gmt_offset; - -/* - * The variable below caches the name of the current working directory - * in order to avoid repeated calls to getcwd. The string is malloc-ed. - * NULL means the cache needs to be refreshed. - */ - -static char *currentDir = NULL; - -/* - *---------------------------------------------------------------------- - * - * TclChdir -- - * - * Change the current working directory. - * - * Results: - * The result is a standard Tcl result. If an error occurs and - * interp isn't NULL, an error message is left in interp->result. - * - * Side effects: - * The working directory for this application is changed. Also - * the cache maintained used by TclGetCwd is deallocated and - * set to NULL. - * - *---------------------------------------------------------------------- - */ - -int -TclChdir( - Tcl_Interp *interp, /* If non NULL, used for error reporting. */ - char *dirName) /* Path to new working directory. */ -{ - FSSpec spec; - OSErr err; - Boolean isFolder; - long dirID; - - if (currentDir != NULL) { - ckfree(currentDir); - currentDir = NULL; - } - - err = FSpLocationFromPath(strlen(dirName), dirName, &spec); - if (err != noErr) { - errno = ENOENT; - goto chdirError; - } - - err = FSpGetDirectoryID(&spec, &dirID, &isFolder); - if (err != noErr) { - errno = ENOENT; - goto chdirError; - } - - if (isFolder != true) { - errno = ENOTDIR; - goto chdirError; - } - - err = FSpSetDefaultDir(&spec); - if (err != noErr) { - switch (err) { - case afpAccessDenied: - errno = EACCES; - break; - default: - errno = ENOENT; - } - goto chdirError; - } - - return TCL_OK; - chdirError: - if (interp != NULL) { - Tcl_AppendResult(interp, "couldn't change working directory to \"", - dirName, "\": ", Tcl_PosixError(interp), (char *) NULL); - } - return TCL_ERROR; -} - -/* - *---------------------------------------------------------------------- - * - * TclGetCwd -- - * - * Return the path name of the current working directory. - * - * Results: - * The result is the full path name of the current working - * directory, or NULL if an error occurred while figuring it - * out. If an error occurs and interp isn't NULL, an error - * message is left in interp->result. - * - * Side effects: - * The path name is cached to avoid having to recompute it - * on future calls; if it is already cached, the cached - * value is returned. - * - *---------------------------------------------------------------------- - */ - -char * -TclGetCwd( - Tcl_Interp *interp) /* If non NULL, used for error reporting. */ -{ - FSSpec theSpec; - int length; - Handle pathHandle = NULL; - - if (currentDir == NULL) { - if (FSpGetDefaultDir(&theSpec) != noErr) { - if (interp != NULL) { - interp->result = "error getting working directory name"; - } - return NULL; - } - if (FSpPathFromLocation(&theSpec, &length, &pathHandle) != noErr) { - if (interp != NULL) { - interp->result = "error getting working directory name"; - } - return NULL; - } - HLock(pathHandle); - currentDir = (char *) ckalloc((unsigned) (length + 1)); - strcpy(currentDir, *pathHandle); - HUnlock(pathHandle); - DisposeHandle(pathHandle); - } - return currentDir; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_WaitPid -- - * - * Fakes a call to wait pid. - * - * Results: - * Always returns -1. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -Tcl_Pid -Tcl_WaitPid( - Tcl_Pid pid, - int *statPtr, - int options) -{ - return (Tcl_Pid) -1; -} +TCL_DECLARE_MUTEX(gmtMutex) + /* *---------------------------------------------------------------------- * * Tcl_FindExecutable -- * * This procedure computes the absolute path name of the current * application, given its argv[0] value. However, this - * implementation doesn't use of need the argv[0] value. NULL + * implementation doesn't need the argv[0] value. NULL * may be passed in its place. * * Results: * None. * @@ -214,19 +60,22 @@ *---------------------------------------------------------------------- */ void Tcl_FindExecutable( - char *argv0) /* The value of the application's argv[0]. */ + CONST char *argv0) /* The value of the application's argv[0]. */ { ProcessSerialNumber psn; ProcessInfoRec info; Str63 appName; FSSpec fileSpec; int pathLength; Handle pathName = NULL; OSErr err; + Tcl_DString ds; + + TclInitSubsystems(argv0); GetCurrentProcess(&psn); info.processInfoLength = sizeof(ProcessInfoRec); info.processName = appName; info.processAppSpec = &fileSpec; @@ -236,56 +85,32 @@ ckfree(tclExecutableName); tclExecutableName = NULL; } err = FSpPathFromLocation(&fileSpec, &pathLength, &pathName); - - tclExecutableName = (char *) ckalloc((unsigned) pathLength + 1); HLock(pathName); - strcpy(tclExecutableName, *pathName); + Tcl_ExternalToUtfDString(NULL, *pathName, pathLength, &ds); HUnlock(pathName); DisposeHandle(pathName); + + tclExecutableName = (char *) ckalloc((unsigned) + (Tcl_DStringLength(&ds) + 1)); + strcpy(tclExecutableName, Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); } /* *---------------------------------------------------------------------- * - * TclGetUserHome -- - * - * This function takes the passed in user name and finds the - * corresponding home directory specified in the password file. - * - * Results: - * On a Macintosh we always return a NULL. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -char * -TclGetUserHome( - char *name, /* User name to use to find home directory. */ - Tcl_DString *bufferPtr) /* May be used to hold result. Must not hold - * anything at the time of the call, and need - * not even be initialized. */ -{ - return NULL; -} - -/* - *---------------------------------------------------------------------- - * - * TclMatchFiles -- + * TclpMatchFiles -- * * This routine is used by the globbing code to search a * directory for all files which match a given pattern. * * Results: * If the tail argument is NULL, then the matching files are - * added to the interp->result. Otherwise, TclDoGlob is called + * added to the the interp's result. Otherwise, TclDoGlob is called * recursively for each matching subdirectory. The return value * is a standard Tcl result indicating whether an error occurred * in globbing. * * Side effects: @@ -292,17 +117,18 @@ * None. * *---------------------------------------------------------------------- */ int -TclMatchFiles( +TclpMatchFiles( Tcl_Interp *interp, /* Interpreter to receive results. */ char *separators, /* Directory separators to pass to TclDoGlob. */ Tcl_DString *dirPtr, /* Contains path to directory to search. */ char *pattern, /* Pattern to match against. */ char *tail) /* Pointer to end of pattern. Tail must - * point to a location in pattern. */ + * point to a location in pattern and must + * not be static.*/ { char *dirName, *patternEnd = tail; char savedChar; int result = TCL_OK; int baseLength = Tcl_DStringLength(dirPtr); @@ -311,11 +137,11 @@ FSSpec dirSpec; Boolean isDirectory; long dirID; short itemIndex; Str255 fileName; - + Tcl_DString fileString; /* * Make sure that the directory part of the name really is a * directory. */ @@ -366,15 +192,16 @@ * Now check to see if the file matches. If there are more * characters to be processed, then ensure matching files are * directories before calling TclDoGlob. Otherwise, just add * the file to the result. */ - - p2cstr(fileName); - if (Tcl_StringMatch((char *) fileName, pattern)) { + + Tcl_ExternalToUtfDString(NULL, (char *) fileName + 1, fileName[0], + &fileString); + if (Tcl_StringMatch(Tcl_DStringValue(&fileString), pattern)) { Tcl_DStringSetLength(dirPtr, baseLength); - Tcl_DStringAppend(dirPtr, (char *) fileName, -1); + Tcl_DStringAppend(dirPtr, Tcl_DStringValue(&fileString), -1); if (tail == NULL) { if ((dirPtr->length > 1) && (strchr(dirPtr->string+1, ':') == NULL)) { Tcl_AppendElement(interp, dirPtr->string+1); } else { @@ -382,14 +209,16 @@ } } else if ((pb.hFileInfo.ioFlAttrib & ioDirMask) != 0) { Tcl_DStringAppend(dirPtr, ":", 1); result = TclDoGlob(interp, separators, dirPtr, tail); if (result != TCL_OK) { + Tcl_DStringFree(&fileString); break; } } } + Tcl_DStringFree(&fileString); itemIndex++; } *patternEnd = savedChar; @@ -397,262 +226,13 @@ } /* *---------------------------------------------------------------------- * - * TclMacStat -- - * - * This function replaces the library version of stat. The stat - * function provided by most Mac compiliers is rather broken and - * incomplete. - * - * Results: - * See stat documentation. - * - * Side effects: - * See stat documentation. - * - *---------------------------------------------------------------------- - */ - -int -TclMacStat( - char *path, - struct stat *buf) -{ - HFileInfo fpb; - HVolumeParam vpb; - OSErr err; - FSSpec fileSpec; - Boolean isDirectory; - long dirID; - - err = FSpLocationFromPath(strlen(path), path, &fileSpec); - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - return -1; - } - - /* - * Fill the fpb & vpb struct up with info about file or directory. - */ - - FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); - vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum; - vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name; - if (isDirectory) { - fpb.ioDirID = fileSpec.parID; - } else { - fpb.ioDirID = dirID; - } - - fpb.ioFDirIndex = 0; - err = PBGetCatInfoSync((CInfoPBPtr)&fpb); - if (err == noErr) { - vpb.ioVolIndex = 0; - err = PBHGetVInfoSync((HParmBlkPtr)&vpb); - if (err == noErr && buf != NULL) { - /* - * Files are always readable by everyone. - */ - - buf->st_mode = S_IRUSR | S_IRGRP | S_IROTH; - - /* - * Use the Volume Info & File Info to fill out stat buf. - */ - if (fpb.ioFlAttrib & 0x10) { - buf->st_mode |= S_IFDIR; - buf->st_nlink = 2; - } else { - buf->st_nlink = 1; - if (fpb.ioFlFndrInfo.fdFlags & 0x8000) { - buf->st_mode |= S_IFLNK; - } else { - buf->st_mode |= S_IFREG; - } - } - if ((fpb.ioFlAttrib & 0x10) || (fpb.ioFlFndrInfo.fdType == 'APPL')) { - /* - * Directories and applications are executable by everyone. - */ - - buf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; - } - if ((fpb.ioFlAttrib & 0x01) == 0){ - /* - * If not locked, then everyone has write acces. - */ - - buf->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; - } - buf->st_ino = fpb.ioDirID; - buf->st_dev = fpb.ioVRefNum; - buf->st_uid = -1; - buf->st_gid = -1; - buf->st_rdev = 0; - buf->st_size = fpb.ioFlLgLen; - buf->st_blksize = vpb.ioVAlBlkSiz; - buf->st_blocks = (buf->st_size + buf->st_blksize - 1) - / buf->st_blksize; - - /* - * The times returned by the Mac file system are in the - * local time zone. We convert them to GMT so that the - * epoch starts from GMT. This is also consistant with - * what is returned from "clock seconds". - */ - if (initalized == false) { - MachineLocation loc; - - ReadLocation(&loc); - gmt_offset = loc.u.gmtDelta & 0x00ffffff; - if (gmt_offset & 0x00800000) { - gmt_offset = gmt_offset | 0xff000000; - } - initalized = true; - } - buf->st_atime = buf->st_mtime = fpb.ioFlMdDat - gmt_offset; - buf->st_ctime = fpb.ioFlCrDat - gmt_offset; - - } - } - - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - } - - return (err == noErr ? 0 : -1); -} - -/* - *---------------------------------------------------------------------- - * - * TclMacReadlink -- - * - * This function replaces the library version of readlink. - * - * Results: - * See readlink documentation. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -TclMacReadlink( - char *path, - char *buf, - int size) -{ - HFileInfo fpb; - OSErr err; - FSSpec fileSpec; - Boolean isDirectory; - Boolean wasAlias; - long dirID; - char fileName[256]; - char *end; - Handle theString = NULL; - int pathSize; - - /* - * Remove ending colons if they exist. - */ - while ((strlen(path) != 0) && (path[strlen(path) - 1] == ':')) { - path[strlen(path) - 1] = NULL; - } - - if (strchr(path, ':') == NULL) { - strcpy(fileName, path); - path = NULL; - } else { - end = strrchr(path, ':') + 1; - strcpy(fileName, end); - *end = NULL; - } - c2pstr(fileName); - - /* - * Create the file spec for the directory of the file - * we want to look at. - */ - if (path != NULL) { - err = FSpLocationFromPath(strlen(path), path, &fileSpec); - if (err != noErr) { - errno = EINVAL; - return -1; - } - } else { - FSMakeFSSpecCompat(0, 0, NULL, &fileSpec); - } - - /* - * Fill the fpb struct up with info about file or directory. - */ - FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); - fpb.ioVRefNum = fileSpec.vRefNum; - fpb.ioDirID = dirID; - fpb.ioNamePtr = (StringPtr) fileName; - - fpb.ioFDirIndex = 0; - err = PBGetCatInfoSync((CInfoPBPtr)&fpb); - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - return -1; - } else { - if (fpb.ioFlAttrib & 0x10) { - errno = EINVAL; - return -1; - } else { - if (fpb.ioFlFndrInfo.fdFlags & 0x8000) { - /* - * The file is a link! - */ - } else { - errno = EINVAL; - return -1; - } - } - } - - /* - * If we are here it's really a link - now find out - * where it points to. - */ - err = FSMakeFSSpecCompat(fileSpec.vRefNum, dirID, (StringPtr) fileName, &fileSpec); - if (err == noErr) { - err = ResolveAliasFile(&fileSpec, true, &isDirectory, &wasAlias); - } - if ((err == fnfErr) || wasAlias) { - err = FSpPathFromLocation(&fileSpec, &pathSize, &theString); - if ((err != noErr) || (pathSize > size)) { - DisposeHandle(theString); - errno = ENAMETOOLONG; - return -1; - } - } else { - errno = EINVAL; - return -1; - } - - strncpy(buf, *theString, pathSize); - DisposeHandle(theString); - - return pathSize; -} - -/* - *---------------------------------------------------------------------- - * - * TclMacAccess -- - * - * This function replaces the library version of access. The - * access function provided by most Mac compiliers is rather - * broken or incomplete. + * TclpAccess -- + * + * This function replaces the library version of access(). * * Results: * See access documentation. * * Side effects: @@ -660,23 +240,28 @@ * *---------------------------------------------------------------------- */ int -TclMacAccess( - const char *path, - int mode) +TclpAccess( + CONST char *path, /* Path of file to access (UTF-8). */ + int mode) /* Permission setting. */ { HFileInfo fpb; HVolumeParam vpb; OSErr err; FSSpec fileSpec; Boolean isDirectory; long dirID; + Tcl_DString ds; + char *native; int full_mode = 0; - err = FSpLocationFromPath(strlen(path), (char *) path, &fileSpec); + native = Tcl_UtfToExternalDString(NULL, path, -1, &ds); + err = FSpLocationFromPath(Tcl_DStringLength(&ds), native, &fileSpec); + Tcl_DStringFree(&ds); + if (err != noErr) { errno = TclMacOSErrorToPosixError(err); return -1; } @@ -740,10 +325,417 @@ } /* *---------------------------------------------------------------------- * + * TclpChdir -- + * + * This function replaces the library version of chdir(). + * + * Results: + * See chdir() documentation. + * + * Side effects: + * See chdir() documentation. Also the cache maintained used by + * TclGetCwd() is deallocated and set to NULL. + * + *---------------------------------------------------------------------- + */ + +int +TclpChdir( + CONST char *dirName) /* Path to new working directory (UTF-8). */ +{ + FSSpec spec; + OSErr err; + Boolean isFolder; + long dirID; + Tcl_DString ds; + char *native; + + native = Tcl_UtfToExternalDString(NULL, dirName, -1, &ds); + err = FSpLocationFromPath(Tcl_DStringLength(&ds), native, &spec); + Tcl_DStringFree(&ds); + + if (err != noErr) { + errno = ENOENT; + return -1; + } + + err = FSpGetDirectoryID(&spec, &dirID, &isFolder); + if (err != noErr) { + errno = ENOENT; + return -1; + } + + if (isFolder != true) { + errno = ENOTDIR; + return -1; + } + + err = FSpSetDefaultDir(&spec); + if (err != noErr) { + switch (err) { + case afpAccessDenied: + errno = EACCES; + break; + default: + errno = ENOENT; + } + return -1; + } + + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * TclpGetCwd -- + * + * This function replaces the library version of getcwd(). + * + * 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. + * + *---------------------------------------------------------------------- + */ + +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. */ +{ + FSSpec theSpec; + int length; + Handle pathHandle = NULL; + + if (FSpGetDefaultDir(&theSpec) != noErr) { + if (interp != NULL) { + Tcl_SetResult(interp, "error getting working directory name", + TCL_STATIC); + } + return NULL; + } + if (FSpPathFromLocation(&theSpec, &length, &pathHandle) != noErr) { + if (interp != NULL) { + Tcl_SetResult(interp, "error getting working directory name", + TCL_STATIC); + } + return NULL; + } + HLock(pathHandle); + Tcl_ExternalToUtfDString(NULL, *pathHandle, length, bufferPtr); + HUnlock(pathHandle); + DisposeHandle(pathHandle); + + return Tcl_DStringValue(bufferPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TclpReadlink -- + * + * This function replaces the library version of readlink(). + * + * Results: + * The result is a pointer to a string specifying the contents + * of the symbolic link given by 'path', or NULL if the symbolic + * link could not be read. Storage for the result string is + * allocated in bufferPtr; the caller must call Tcl_DStringFree() + * when the result is no longer needed. + * + * Side effects: + * See readlink() documentation. + * + *--------------------------------------------------------------------------- + */ + +char * +TclpReadlink( + CONST char *path, /* Path of file to readlink (UTF-8). */ + Tcl_DString *linkPtr) /* Uninitialized or free DString filled + * with contents of link (UTF-8). */ +{ + HFileInfo fpb; + OSErr err; + FSSpec fileSpec; + Boolean isDirectory; + Boolean wasAlias; + long dirID; + char fileName[257]; + char *end; + Handle theString = NULL; + int pathSize; + Tcl_DString ds; + char *native; + + native = Tcl_UtfToExternalDString(NULL, path, -1, &ds); + + /* + * Remove ending colons if they exist. + */ + + while ((strlen(native) != 0) && (path[strlen(native) - 1] == ':')) { + native[strlen(native) - 1] = NULL; + } + + if (strchr(native, ':') == NULL) { + strcpy(fileName + 1, native); + native = NULL; + } else { + end = strrchr(native, ':') + 1; + strcpy(fileName + 1, end); + *end = NULL; + } + fileName[0] = (char) strlen(fileName + 1); + + /* + * Create the file spec for the directory of the file + * we want to look at. + */ + + if (native != NULL) { + err = FSpLocationFromPath(strlen(native), native, &fileSpec); + if (err != noErr) { + Tcl_DStringFree(&ds); + errno = EINVAL; + return NULL; + } + } else { + FSMakeFSSpecCompat(0, 0, NULL, &fileSpec); + } + Tcl_DStringFree(&ds); + + /* + * Fill the fpb struct up with info about file or directory. + */ + + FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); + fpb.ioVRefNum = fileSpec.vRefNum; + fpb.ioDirID = dirID; + fpb.ioNamePtr = (StringPtr) fileName; + + fpb.ioFDirIndex = 0; + err = PBGetCatInfoSync((CInfoPBPtr)&fpb); + if (err != noErr) { + errno = TclMacOSErrorToPosixError(err); + return NULL; + } else { + if (fpb.ioFlAttrib & 0x10) { + errno = EINVAL; + return NULL; + } else { + if (fpb.ioFlFndrInfo.fdFlags & 0x8000) { + /* + * The file is a link! + */ + } else { + errno = EINVAL; + return NULL; + } + } + } + + /* + * If we are here it's really a link - now find out + * where it points to. + */ + err = FSMakeFSSpecCompat(fileSpec.vRefNum, dirID, (StringPtr) fileName, + &fileSpec); + if (err == noErr) { + err = ResolveAliasFile(&fileSpec, true, &isDirectory, &wasAlias); + } + if ((err == fnfErr) || wasAlias) { + err = FSpPathFromLocation(&fileSpec, &pathSize, &theString); + if (err != noErr) { + DisposeHandle(theString); + errno = ENAMETOOLONG; + return NULL; + } + } else { + errno = EINVAL; + return NULL; + } + + Tcl_ExternalToUtfDString(NULL, *theString, pathSize, linkPtr); + DisposeHandle(theString); + + return Tcl_DStringValue(linkPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TclpStat -- + * + * This function replaces the library version of stat(). + * + * Results: + * See stat() documentation. + * + * Side effects: + * See stat() documentation. + * + *---------------------------------------------------------------------- + */ + +int +TclpStat( + CONST char *path, /* Path of file to stat (in UTF-8). */ + struct stat *bufPtr) /* Filled with results of stat call. */ +{ + HFileInfo fpb; + HVolumeParam vpb; + OSErr err; + FSSpec fileSpec; + Boolean isDirectory; + long dirID; + Tcl_DString ds; + + path = Tcl_UtfToExternalDString(NULL, path, -1, &ds); + err = FSpLocationFromPath(Tcl_DStringLength(&ds), path, &fileSpec); + Tcl_DStringFree(&ds); + + if (err != noErr) { + errno = TclMacOSErrorToPosixError(err); + return -1; + } + + /* + * Fill the fpb & vpb struct up with info about file or directory. + */ + + FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); + vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum; + vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name; + if (isDirectory) { + fpb.ioDirID = fileSpec.parID; + } else { + fpb.ioDirID = dirID; + } + + fpb.ioFDirIndex = 0; + err = PBGetCatInfoSync((CInfoPBPtr)&fpb); + if (err == noErr) { + vpb.ioVolIndex = 0; + err = PBHGetVInfoSync((HParmBlkPtr)&vpb); + if (err == noErr && bufPtr != NULL) { + /* + * Files are always readable by everyone. + */ + + bufPtr->st_mode = S_IRUSR | S_IRGRP | S_IROTH; + + /* + * Use the Volume Info & File Info to fill out stat buf. + */ + if (fpb.ioFlAttrib & 0x10) { + bufPtr->st_mode |= S_IFDIR; + bufPtr->st_nlink = 2; + } else { + bufPtr->st_nlink = 1; + if (fpb.ioFlFndrInfo.fdFlags & 0x8000) { + bufPtr->st_mode |= S_IFLNK; + } else { + bufPtr->st_mode |= S_IFREG; + } + } + if ((fpb.ioFlAttrib & 0x10) || (fpb.ioFlFndrInfo.fdType == 'APPL')) { + /* + * Directories and applications are executable by everyone. + */ + + bufPtr->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; + } + if ((fpb.ioFlAttrib & 0x01) == 0){ + /* + * If not locked, then everyone has write acces. + */ + + bufPtr->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; + } + bufPtr->st_ino = fpb.ioDirID; + bufPtr->st_dev = fpb.ioVRefNum; + bufPtr->st_uid = -1; + bufPtr->st_gid = -1; + bufPtr->st_rdev = 0; + bufPtr->st_size = fpb.ioFlLgLen; + bufPtr->st_blksize = vpb.ioVAlBlkSiz; + bufPtr->st_blocks = (bufPtr->st_size + bufPtr->st_blksize - 1) + / bufPtr->st_blksize; + + /* + * The times returned by the Mac file system are in the + * local time zone. We convert them to GMT so that the + * epoch starts from GMT. This is also consistant with + * what is returned from "clock seconds". + */ + + Tcl_MutexLock(&gmtMutex); + if (initialized == false) { + MachineLocation loc; + + ReadLocation(&loc); + gmt_offset = loc.u.gmtDelta & 0x00ffffff; + if (gmt_offset & 0x00800000) { + gmt_offset = gmt_offset | 0xff000000; + } + initialized = true; + } + Tcl_MutexUnlock(&gmtMutex); + + bufPtr->st_atime = bufPtr->st_mtime = fpb.ioFlMdDat - gmt_offset; + bufPtr->st_ctime = fpb.ioFlCrDat - gmt_offset; + } + } + + if (err != noErr) { + errno = TclMacOSErrorToPosixError(err); + } + + return (err == noErr ? 0 : -1); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_WaitPid -- + * + * Fakes a call to wait pid. + * + * Results: + * Always returns -1. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tcl_Pid +Tcl_WaitPid( + Tcl_Pid pid, + int *statPtr, + int options) +{ + return (Tcl_Pid) -1; +} + +/* + *---------------------------------------------------------------------- + * * TclMacFOpenHack -- * * This function replaces fopen. It supports paths with alises. * Note, remember to undefine the fopen macro! * @@ -757,12 +749,12 @@ */ #undef fopen FILE * TclMacFOpenHack( - const char *path, - const char *mode) + CONST char *path, + CONST char *mode) { OSErr err; FSSpec fileSpec; Handle pathString = NULL; int size; Index: mac/tclMacInit.c ================================================================== --- mac/tclMacInit.c +++ mac/tclMacInit.c @@ -1,63 +1,522 @@ /* * tclMacInit.c -- * * Contains the Mac-specific interpreter initialization functions. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclMacInit.c 1.39 97/09/23 13:17:30 + * RCS: @(#) $Id: tclMacInit.c,v 1.1.2.5 1999/04/14 00:34:52 surles Exp $ */ +#include +#include +#include +#include +#include #include +#include #include #include #include #include #include "tclInt.h" #include "tclMacInt.h" +#include "tclPort.h" + +/* + * The following string is the startup script executed in new + * interpreters. It looks on the library path and in the resource fork for + * a script "init.tcl" that is compatible with this version of Tcl. The + * init.tcl script does all of the real work of initialization. + */ + +static char initCmd[] = "\ +proc sourcePath {file} {\n\ + set dirs {}\n\ + foreach i $::auto_path {\n\ + set init [file join $i $file.tcl]\n\ + if {[catch {uplevel #0 [list source $init]}] == 0} {\n\ + return\n\ + }\n\ + }\n\ + if {[catch {uplevel #0 [list source -rsrc $file]}] == 0} {\n\ + return\n\ + }\n\ + rename sourcePath {}\n\ + set msg \"can't find $file resource or a usable $file.tcl file\n\"\n\ + append msg \"in the following directories:\n\"\n\ + append msg \" $::auto_path\n\"\n\ + append msg \" perhaps you need to install Tcl or set your \n\"\n\ + append msg \"TCL_LIBRARY environment variable?\"\n\ + error $msg\n\ +}\n\ +if {[info exists env(EXT_FOLDER)]} {\n\ + lappend tcl_pkgPath [file join $env(EXT_FOLDER) {:Tool Command Language}]\n\ +}\n\ +if {[info exists tcl_pkgPath] == 0} {\n\ + set tcl_pkgPath {no extension folder}\n\ +}\n\ +sourcePath Init\n\ +sourcePath Auto\n\ +sourcePath Package\n\ +sourcePath History\n\ +sourcePath Word\n\ +rename sourcePath {}"; + +/* + * The following structures are used to map the script/language codes of a + * font to the name that should be passed to Tcl_GetEncoding() to obtain + * the encoding for that font. The set of numeric constants is fixed and + * defined by Apple. + */ + +typedef struct Map { + int numKey; + char *strKey; +} Map; + +static Map scriptMap[] = { + {smRoman, "macRoman"}, + {smJapanese, "macJapan"}, + {smTradChinese, "macChinese"}, + {smKorean, "macKorean"}, + {smArabic, "macArabic"}, + {smHebrew, "macHebrew"}, + {smGreek, "macGreek"}, + {smCyrillic, "macCyrillic"}, + {smRSymbol, "macRSymbol"}, + {smDevanagari, "macDevanagari"}, + {smGurmukhi, "macGurmukhi"}, + {smGujarati, "macGujarati"}, + {smOriya, "macOriya"}, + {smBengali, "macBengali"}, + {smTamil, "macTamil"}, + {smTelugu, "macTelugu"}, + {smKannada, "macKannada"}, + {smMalayalam, "macMalayalam"}, + {smSinhalese, "macSinhalese"}, + {smBurmese, "macBurmese"}, + {smKhmer, "macKhmer"}, + {smThai, "macThailand"}, + {smLaotian, "macLaos"}, + {smGeorgian, "macGeorgia"}, + {smArmenian, "macArmenia"}, + {smSimpChinese, "macSimpChinese"}, + {smTibetan, "macTIbet"}, + {smMongolian, "macMongolia"}, + {smGeez, "macEthiopia"}, + {smEastEurRoman, "macCentEuro"}, + {smVietnamese, "macVietnam"}, + {smExtArabic, "macSindhi"}, + {NULL, NULL} +}; + +static Map romanMap[] = { + {langCroatian, "macCroatian"}, + {langSlovenian, "macCroatian"}, + {langIcelandic, "macIceland"}, + {langRomanian, "macRomania"}, + {langTurkish, "macTurkish"}, + {langGreek, "macGreek"}, + {NULL, NULL} +}; + +static Map cyrillicMap[] = { + {langUkrainian, "macUkraine"}, + {langBulgarian, "macBulgaria"}, + {NULL, NULL} +}; + +static int GetFinderFont(int *finderID); + + +/* + *---------------------------------------------------------------------- + * + * GetFinderFont -- + * + * Gets the "views" font of the Macintosh Finder + * + * Results: + * Standard Tcl result, and sets finderID to the font family + * id for the current finder font. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static int +GetFinderFont(int *finderID) +{ + OSErr err = noErr; + OSType finderPrefs, viewFont = 'vfnt'; + DescType returnType; + Size returnSize; + long result, sys8Mask = 0x0800; + static AppleEvent outgoingAevt = {typeNull, NULL}; + AppleEvent returnAevt; + AEAddressDesc fndrAddress; + AEDesc nullContainer = {typeNull, NULL}, + tempDesc = {typeNull, NULL}, + tempDesc2 = {typeNull, NULL}, + finalDesc = {typeNull, NULL}; + const OSType finderSignature = 'MACS'; + + + if (outgoingAevt.descriptorType == typeNull) { + if ((Gestalt(gestaltSystemVersion, &result) != noErr) + || (result >= sys8Mask)) { + finderPrefs = 'pfrp'; + } else { + finderPrefs = 'pvwp'; + } + + AECreateDesc(typeApplSignature, &finderSignature, + sizeof(finderSignature), &fndrAddress); + + err = AECreateAppleEvent(kAECoreSuite, kAEGetData, &fndrAddress, + kAutoGenerateReturnID, kAnyTransactionID, &outgoingAevt); + + AEDisposeDesc(&fndrAddress); + + /* + * The structure is: + * the property view font ('vfnt') + * of the property view preferences ('pvwp') + * of the Null Container (i.e. the Finder itself). + */ + + AECreateDesc(typeType, &finderPrefs, sizeof(finderPrefs), &tempDesc); + err = CreateObjSpecifier(typeType, &nullContainer, formPropertyID, + &tempDesc, true, &tempDesc2); + AECreateDesc(typeType, &viewFont, sizeof(viewFont), &tempDesc); + err = CreateObjSpecifier(typeType, &tempDesc2, formPropertyID, + &tempDesc, true, &finalDesc); + + AEPutKeyDesc(&outgoingAevt, keyDirectObject, &finalDesc); + AEDisposeDesc(&finalDesc); + } + + err = AESend(&outgoingAevt, &returnAevt, kAEWaitReply, kAEHighPriority, + kAEDefaultTimeout, NULL, NULL); + if (err == noErr) { + err = AEGetKeyPtr(&returnAevt, keyDirectObject, typeInteger, + &returnType, (void *) finderID, sizeof(int), &returnSize); + if (err == noErr) { + return TCL_OK; + } + } + return TCL_ERROR; +} + +/* + *--------------------------------------------------------------------------- + * + * TclMacGetFontEncoding -- + * + * Determine the encoding of the specified font. The encoding + * can be used to convert bytes from UTF-8 into the encoding of + * that font. + * + * Results: + * The return value is a string that specifies the font's encoding + * and that can be passed to Tcl_GetEncoding() to construct the + * encoding. If the font's encoding could not be identified, NULL + * is returned. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +char * +TclMacGetFontEncoding( + int fontId) +{ + int script, lang; + char *name; + Map *mapPtr; + + script = FontToScript(fontId); + lang = GetScriptVariable(script, smScriptLang); + name = NULL; + if (script == smRoman) { + for (mapPtr = romanMap; mapPtr->strKey != NULL; mapPtr++) { + if (mapPtr->numKey == lang) { + name = mapPtr->strKey; + break; + } + } + } else if (script == smCyrillic) { + for (mapPtr = cyrillicMap; mapPtr->strKey != NULL; mapPtr++) { + if (mapPtr->numKey == lang) { + name = mapPtr->strKey; + break; + } + } + } + if (name == NULL) { + for (mapPtr = scriptMap; mapPtr->strKey != NULL; mapPtr++) { + if (mapPtr->numKey == script) { + name = mapPtr->strKey; + break; + } + } + } + return name; +} + +/* + *--------------------------------------------------------------------------- + * + * TclpInitPlatform -- + * + * Initialize all the platform-dependant things like signals and + * floating-point error handling. + * + * Called at process initialization time. + * + * Results: + * None. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +void +TclpInitPlatform() +{ + tclPlatform = TCL_PLATFORM_MAC; +} + +/* + *--------------------------------------------------------------------------- + * + * TclpInitLibraryPath -- + * + * Initialize the library path at startup. We have a minor + * metacircular problem that we don't know the encoding of the + * operating system but we may need to talk to operating system + * to find the library directories so that we know how to talk to + * the operating system. + * + * We do not know the encoding of the operating system. + * We do know that the encoding is some multibyte encoding. + * In that multibyte encoding, the characters 0..127 are equivalent + * to ascii. + * + * So although we don't know the encoding, it's safe: + * to look for the last colon character in a path in the encoding. + * to append an ascii string to a path. + * to pass those strings back to the operating system. + * + * But any strings that we remembered before we knew the encoding of + * the operating system must be translated to UTF-8 once we know the + * encoding so that the rest of Tcl can use those strings. + * + * This call sets the library path to strings in the unknown native + * encoding. TclpSetInitialEncodings() will translate the library + * path from the native encoding to UTF-8 as soon as it determines + * what the native encoding actually is. + * + * Called at process initialization time. + * + * Results: + * None. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +void +TclpInitLibraryPath(argv0) + CONST char *argv0; /* Name of executable from argv[0] to main(). + * Not used because we can determine the name + * by querying the module handle. */ +{ + Tcl_Obj *objPtr, *pathPtr; + char *str; + Tcl_DString ds; + + TclMacCreateEnv(); + + pathPtr = Tcl_NewObj(); + + str = TclGetEnv("TCL_LIBRARY", &ds); + if ((str != NULL) && (str[0] != '\0')) { + /* + * If TCL_LIBRARY is set, search there. + */ + + objPtr = Tcl_NewStringObj(str, -1); + Tcl_ListObjAppendElement(NULL, pathPtr, objPtr); + Tcl_DStringFree(&ds); + } + + objPtr = TclGetLibraryPath(); + if (objPtr != NULL) { + Tcl_ListObjAppendList(NULL, pathPtr, objPtr); + } + + /* + * lappend path [file join $env(EXT_FOLDER) \ + * ":Tool Command Language:tcl[info version]" + */ + + str = TclGetEnv("EXT_FOLDER", &ds); + if ((str != NULL) && (str[0] != '\0')) { + objPtr = Tcl_NewStringObj(str, -1); + if (str[strlen(str) - 1] != ':') { + Tcl_AppendToObj(objPtr, ":", 1); + } + Tcl_AppendToObj(objPtr, "Tool Command Language:tcl" TCL_VERSION, -1); + Tcl_ListObjAppendElement(NULL, pathPtr, objPtr); + Tcl_DStringFree(&ds); + } + TclSetLibraryPath(pathPtr); +} + +/* + *--------------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * The Tcl library path is converted from native encoding to UTF-8. + * + *--------------------------------------------------------------------------- + */ + +void +TclpSetInitialEncodings() +{ + CONST char *encoding; + Tcl_Obj *pathPtr; + int fontId; + + fontId = 0; + GetFinderFont(&fontId); + encoding = TclMacGetFontEncoding(fontId); + if (encoding == NULL) { + encoding = "macRoman"; + } + + Tcl_SetSystemEncoding(NULL, encoding); + + /* + * Until the system encoding was actually set, the library path was + * actually in the native multi-byte encoding, and not really UTF-8 + * as advertised. We cheated as follows: + * + * 1. It was safe to allow the Tcl_SetSystemEncoding() call to + * append the ASCII chars that make up the encoding's filename to + * the names (in the native encoding) of directories in the library + * path, since all Unix multi-byte encodings have ASCII in the + * beginning. + * + * 2. To open the encoding file, the native bytes in the file name + * were passed to the OS, without translating from UTF-8 to native, + * because the name was already in the native encoding. + * + * Now that the system encoding was actually successfully set, + * translate all the names in the library path to UTF-8. That way, + * next time we search the library path, we'll translate the names + * from UTF-8 to the system encoding which will be the native + * encoding. + */ + + pathPtr = TclGetLibraryPath(); + if (pathPtr != NULL) { + int i, objc; + Tcl_Obj **objv; + + objc = 0; + Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv); + for (i = 0; i < objc; i++) { + int length; + char *string; + Tcl_DString ds; + + string = Tcl_GetStringFromObj(objv[i], &length); + Tcl_ExternalToUtfDString(NULL, string, length, &ds); + Tcl_SetStringObj(objv[i], Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + } + } + + /* + * Keep the iso8859-1 encoding preloaded. The IO package uses it for + * gets on a binary channel. + */ + + Tcl_GetEncoding(NULL, "iso8859-1"); +} /* - *---------------------------------------------------------------------- + *--------------------------------------------------------------------------- * - * TclPlatformInit -- + * TclpSetVariables -- * - * Performs Mac-specific interpreter initialization related to the - * tcl_platform and tcl_library variables. + * Performs platform-specific interpreter initialization related to + * the tcl_library and tcl_platform variables, and other platform- + * specific things. * * Results: * None. * * Side effects: - * Sets "tcl_library" & "tcl_platfrom" Tcl variable + * Sets "tcl_library" and "tcl_platform" Tcl variables. * *---------------------------------------------------------------------- */ void -TclPlatformInit( - Tcl_Interp *interp) /* Tcl interpreter to initialize. */ +TclpSetVariables(interp) + Tcl_Interp *interp; { - char *libDir; - Tcl_DString path, libPath; long int gestaltResult; - int minor, major; - char versStr[10]; - - /* - * Set runtime C variable that tells cross platform C functions - * what platform they are running on. This can change at - * runtime for testing purposes. - */ - tclPlatform = TCL_PLATFORM_MAC; - - /* - * Define the tcl_platfrom variable. - */ + int minor, major, objc; + Tcl_Obj **objv; + char versStr[2 * TCL_INTEGER_SPACE]; + char *str; + Tcl_Obj *pathPtr; + Tcl_DString ds; + + str = "no library"; + pathPtr = TclGetLibraryPath(); + if (pathPtr != NULL) { + objc = 0; + Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv); + if (objc > 0) { + str = Tcl_GetStringFromObj(objv[0], NULL); + } + } + Tcl_SetVar(interp, "tcl_library", str, TCL_GLOBAL_ONLY); + + if (pathPtr != NULL) { + Tcl_SetVar2Ex(interp, "tcl_pkgPath", NULL, pathPtr, TCL_GLOBAL_ONLY); + } + Tcl_SetVar2(interp, "tcl_platform", "platform", "macintosh", TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "tcl_platform", "os", "MacOS", TCL_GLOBAL_ONLY); Gestalt(gestaltSystemVersion, &gestaltResult); major = (gestaltResult & 0x0000FF00) >> 8; @@ -69,51 +528,24 @@ #else Tcl_SetVar2(interp, "tcl_platform", "machine", "68k", TCL_GLOBAL_ONLY); #endif /* - * The tcl_library path can be found in one of two places. As an element - * in the env array. Or the default which is to a folder in side the - * Extensions folder of your system. - */ - - Tcl_DStringInit(&path); - libDir = Tcl_GetVar2(interp, "env", "TCL_LIBRARY", TCL_GLOBAL_ONLY); - if (libDir != NULL) { - Tcl_SetVar(interp, "tcl_library", libDir, TCL_GLOBAL_ONLY); - } else { - libDir = Tcl_GetVar2(interp, "env", "EXT_FOLDER", TCL_GLOBAL_ONLY); - if (libDir != NULL) { - Tcl_JoinPath(1, &libDir, &path); - - Tcl_DStringInit(&libPath); - Tcl_DStringAppend(&libPath, ":Tool Command Language:tcl", -1); - Tcl_DStringAppend(&libPath, TCL_VERSION, -1); - Tcl_JoinPath(1, &libPath.string, &path); - Tcl_DStringFree(&libPath); - Tcl_SetVar(interp, "tcl_library", path.string, TCL_GLOBAL_ONLY); - } else { - Tcl_SetVar(interp, "tcl_library", "no library", TCL_GLOBAL_ONLY); - } - } - - /* - * Now create the tcl_pkgPath variable. - */ - Tcl_DStringSetLength(&path, 0); - libDir = Tcl_GetVar2(interp, "env", "EXT_FOLDER", TCL_GLOBAL_ONLY); - if (libDir != NULL) { - Tcl_JoinPath(1, &libDir, &path); - libDir = ":Tool Command Language:"; - Tcl_JoinPath(1, &libDir, &path); - Tcl_SetVar(interp, "tcl_pkgPath", path.string, - TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT); - } else { - Tcl_SetVar(interp, "tcl_pkgPath", "no extension folder", - TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT); - } - Tcl_DStringFree(&path); + * Copy USER or LOGIN environment variable into tcl_platform(user) + * These are set by SystemVariables in tclMacEnv.c + */ + + Tcl_DStringInit(&ds); + str = TclGetEnv("USER", &ds); + if (str == NULL) { + str = TclGetEnv("LOGIN", &ds); + if (str == NULL) { + str = ""; + } + } + Tcl_SetVar2(interp, "tcl_platform", "user", str, TCL_GLOBAL_ONLY); + Tcl_DStringFree(&ds); } /* *---------------------------------------------------------------------- * @@ -146,11 +578,11 @@ * This procedure is typically invoked by Tcl_AppInit procedures * to perform additional initialization for a Tcl interpreter, * such as sourcing the "init.tcl" script. * * Results: - * Returns a standard Tcl completion code and sets interp->result + * 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. * @@ -159,45 +591,23 @@ int Tcl_Init( Tcl_Interp *interp) /* Interpreter to initialize. */ { - static char initCmd[] = - "if {[catch {source -rsrc Init}] != 0} {\n\ - if [file exists [info library]:init.tcl] {\n\ - source [info library]:init.tcl\n\ - } else {\n\ - set msg \"can't find Init resource or [info library]:init.tcl;\"\n\ - append msg \" perhaps you need to\\ninstall Tcl or set your \"\n\ - append msg \"TCL_LIBRARY environment variable?\"\n\ - error $msg\n\ - }\n}\n\ - if {[catch {source -rsrc History}] != 0} {\n\ - if [file exists [info library]:history.tcl] {\n\ - source [info library]:history.tcl\n\ - } else {\n\ - set msg \"can't find History resource or [info library]:history.tcl;\"\n\ - append msg \" perhaps you need to\\ninstall Tcl or set your \"\n\ - append msg \"TCL_LIBRARY environment variable?\"\n\ - error $msg\n\ - }\n}\n\ - if {[catch {source -rsrc Word}] != 0} {\n\ - if [file exists [info library]:word.tcl] {\n\ - source [info library]:word.tcl\n\ - } else {\n\ - set msg \"can't find Word resource or [info library]:word.tcl;\"\n\ - append msg \" perhaps you need to\\ninstall Tcl or set your \"\n\ - append msg \"TCL_LIBRARY environment variable?\"\n\ - error $msg\n\ - }\n}"; + Tcl_Obj *pathPtr; /* * For Macintosh applications the Init function may be contained in * the application resources. If it exists we use it - otherwise we * look in the tcl_library directory. Ditto for the history command. */ - + + pathPtr = TclGetLibraryPath(); + if (pathPtr == NULL) { + pathPtr = Tcl_NewObj(); + } + Tcl_SetVar2Ex(interp, "auto_path", NULL, pathPtr, TCL_GLOBAL_ONLY); return Tcl_Eval(interp, initCmd); } /* *---------------------------------------------------------------------- @@ -252,12 +662,12 @@ if (c != (Tcl_Channel) NULL) { Tcl_Close(NULL, c); if (Tcl_EvalFile(interp, fullName) != TCL_OK) { errChannel = Tcl_GetStdChannel(TCL_STDERR); if (errChannel) { - Tcl_Write(errChannel, interp->result, -1); - Tcl_Write(errChannel, "\n", 1); + Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)); + Tcl_WriteChars(errChannel, "\n", 1); } } } } Tcl_DStringFree(&temp); @@ -271,14 +681,14 @@ p2cstr((StringPtr) fileName); if (h != NULL) { if (Tcl_MacEvalResource(interp, fileName, 0, NULL) != TCL_OK) { errChannel = Tcl_GetStdChannel(TCL_STDERR); if (errChannel) { - Tcl_Write(errChannel, interp->result, -1); - Tcl_Write(errChannel, "\n", 1); + Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)); + Tcl_WriteChars(errChannel, "\n", 1); } } Tcl_ResetResult(interp); ReleaseResource(h); } } } Index: mac/tclMacInt.h ================================================================== --- mac/tclMacInt.h +++ mac/tclMacInt.h @@ -1,16 +1,16 @@ /* * tclMacInt.h -- * * Declarations of Macintosh specific shared variables and procedures. * - * Copyright (c) 1996-1997 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclMacInt.h 1.24 97/09/09 16:22:01 + * RCS: @(#) $Id: tclMacInt.h,v 1.1.2.3 1999/03/10 06:49:25 stanton Exp $ */ #ifndef _TCLMACINT #define _TCLMACINT @@ -44,36 +44,17 @@ /* * Typedefs used by Macintosh parts of Tcl. */ typedef pascal void (*ExitToShellProcPtr)(void); -/* - * Prototypes for functions found in the tclMacUtil.c compatability library. - */ - -EXTERN int FSpGetDefaultDir _ANSI_ARGS_((FSSpecPtr theSpec)); -EXTERN int FSpSetDefaultDir _ANSI_ARGS_((FSSpecPtr theSpec)); -EXTERN OSErr FSpFindFolder _ANSI_ARGS_((short vRefNum, OSType folderType, - Boolean createFolder, FSSpec *spec)); -EXTERN void GetGlobalMouse _ANSI_ARGS_((Point *mouse)); - /* * Prototypes of Mac only internal functions. */ -EXTERN void TclCreateMacEventSource _ANSI_ARGS_((void)); -EXTERN int TclMacConsoleInit _ANSI_ARGS_((void)); -EXTERN void TclMacExitHandler _ANSI_ARGS_((void)); -EXTERN void TclMacInitExitToShell _ANSI_ARGS_((int usePatch)); -EXTERN OSErr TclMacInstallExitToShellPatch _ANSI_ARGS_(( - ExitToShellProcPtr newProc)); -EXTERN int TclMacOSErrorToPosixError _ANSI_ARGS_((int error)); -EXTERN void TclMacRemoveTimer _ANSI_ARGS_((void *timerToken)); -EXTERN void * TclMacStartTimer _ANSI_ARGS_((long ms)); -EXTERN int TclMacTimerExpired _ANSI_ARGS_((void *timerToken)); -EXTERN int TclMacRegisterResourceFork _ANSI_ARGS_((short fileRef, Tcl_Obj *tokenPtr, - int insert)); -EXTERN short TclMacUnRegisterResourceFork _ANSI_ARGS_((char *tokenPtr, Tcl_Obj *resultPtr)); - +EXTERN char * TclMacGetFontEncoding _ANSI_ARGS_((int fontId)); +EXTERN int TclMacHaveThreads(void); + +#include "tclIntPlatDecls.h" + #pragma export reset #endif /* _TCLMACINT */ Index: mac/tclMacInterupt.c ================================================================== --- mac/tclMacInterupt.c +++ mac/tclMacInterupt.c @@ -8,11 +8,11 @@ * 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. * - * SCCS: @(#) tclMacInterupt.c 1.16 96/12/12 19:22:01 + * RCS: @(#) $Id: tclMacInterupt.c,v 1.1.2.1 1998/09/24 23:59:13 stanton Exp $ */ #include "tclInt.h" #include "tclMacInt.h" #include Index: mac/tclMacLibrary.c ================================================================== --- mac/tclMacLibrary.c +++ mac/tclMacLibrary.c @@ -11,11 +11,11 @@ * 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. * - * SCCS: @(#) tclMacLibrary.c 1.6 97/11/20 19:29:42 + * RCS: @(#) $Id: tclMacLibrary.c,v 1.1.2.1 1998/09/24 23:59:13 stanton Exp $ */ /* * Here is another place that we are using the old routine names... */ Index: mac/tclMacLibrary.r ================================================================== --- mac/tclMacLibrary.r +++ mac/tclMacLibrary.r @@ -8,11 +8,11 @@ * 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. * - * SCCS: @(#) tclMacLibrary.r 1.5 97/09/23 12:53:28 + * RCS: @(#) $Id: tclMacLibrary.r,v 1.1.2.2 1998/09/24 23:59:13 stanton Exp $ */ #include #include @@ -139,13 +139,11 @@ * resource fork the source command has been modified to support * sourcing from resources. In the below case "source -rsrc {Init}" * will load the TEXT resource named "Init". */ -read 'TEXT' (TCL_LIBRARY_RESOURCES, "Init", purgeable) "::library:init.tcl"; -read 'TEXT' (TCL_LIBRARY_RESOURCES + 1, "History", purgeable) "::library:history.tcl"; -read 'TEXT' (TCL_LIBRARY_RESOURCES + 2, "Word", purgeable,preload) "::library:word.tcl"; +#include "tclMacTclCode.r" /* * The following are icons for the shared library. */ Index: mac/tclMacLoad.c ================================================================== --- mac/tclMacLoad.c +++ mac/tclMacLoad.c @@ -3,16 +3,16 @@ * * This procedure provides a version of the TclLoadFile for use * on the Macintosh. This procedure will only work with systems * that use the Code Fragment Manager. * - * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclMacLoad.c 1.20 97/11/20 18:39:20 + * RCS: @(#) $Id: tclMacLoad.c,v 1.1.2.2 1998/09/24 23:59:13 stanton Exp $ */ #include #include #include @@ -86,29 +86,32 @@ * code for the Macintosh. This implementation is based on the * Code Fragment Manager & will not work on other systems. * * Results: * The result is TCL_ERROR, and an error message is left in - * interp->result. + * the interp's result. * * Side effects: * New binary code is loaded. * *---------------------------------------------------------------------- */ int -TclLoadFile( +TclpLoadFile( Tcl_Interp *interp, /* Used for error reporting. */ char *fileName, /* Name of the file containing the desired * code. */ char *sym1, char *sym2, /* Names of two procedures to look up in * the file's symbol table. */ Tcl_PackageInitProc **proc1Ptr, - Tcl_PackageInitProc **proc2Ptr) + Tcl_PackageInitProc **proc2Ptr, /* Where to return the addresses corresponding * to sym1 and sym2. */ + ClientData *clientDataPtr) /* Filled with token for dynamically loaded + * file which will be passed back to + * TclpUnloadFile() to unload the file. */ { CFragConnectionID connID; Ptr dummy; OSErr err; CFragSymbolClass symClass; @@ -117,33 +120,39 @@ Handle fragResource; UInt32 offset = 0; UInt32 length = kCFragGoesToEOF; char packageName[255]; Str255 errName; + Tcl_DString ds; + char *native; /* * First thing we must do is infer the package name from the sym1 * variable. This is kind of dumb since the caller actually knows * this value, it just doesn't give it to us. */ strcpy(packageName, sym1); - *packageName = (char) tolower(*packageName); - packageName[strlen(packageName) - 5] = NULL; + Tcl_UtfToLower(packageName); + *(Tcl_UtfAtIndex(packageName, Tcl_NumUtfChars(packageName, -1) - 5)) = 0; + native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds); err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec); + Tcl_DStringFree(&ds); + if (err != noErr) { - interp->result = "could not locate shared library"; + Tcl_SetResult(interp, "could not locate shared library", TCL_STATIC); return TCL_ERROR; } /* - * See if this fragment has a 'cfrg' resource. It will tell us were + * See if this fragment has a 'cfrg' resource. It will tell us where * to look for the fragment in the file. If it doesn't exist we will * assume we have a ppc frag using the whole data fork. If it does * exist we find the frag that matches the one we are looking for and * get the offset and size from the resource. */ + saveFileRef = CurResFile(); SetResLoad(false); fragFileRef = FSpOpenResFile(&fileSpec, fsRdPerm); SetResLoad(true); if (fragFileRef != -1) { @@ -197,12 +206,13 @@ c2pstr(sym1); err = FindSymbol(connID, (StringPtr) sym1, (Ptr *) proc1Ptr, &symClass); p2cstr((StringPtr) sym1); if (err != fragNoErr || symClass == kDataCFragSymbol) { - interp->result = - "could not find Initialization routine in library"; + Tcl_SetResult(interp, + "could not find Initialization routine in library", + TCL_STATIC); return TCL_ERROR; } c2pstr(sym2); err = FindSymbol(connID, (StringPtr) sym2, (Ptr *) proc2Ptr, &symClass); @@ -209,11 +219,40 @@ p2cstr((StringPtr) sym2); if (err != fragNoErr || symClass == kDataCFragSymbol) { *proc2Ptr = NULL; } + *clientDataPtr = (ClientData) connID; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TclpUnloadFile -- + * + * 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: + * Does nothing. Can anything be done? + * + *---------------------------------------------------------------------- + */ + +void +TclpUnloadFile(clientData) + ClientData clientData; /* ClientData returned by a previous call + * to TclpLoadFile(). The clientData is + * a token that represents the loaded + * file. */ +{ } /* *---------------------------------------------------------------------- * Index: mac/tclMacMSLPrefix.h ================================================================== --- mac/tclMacMSLPrefix.h +++ mac/tclMacMSLPrefix.h @@ -9,11 +9,11 @@ * 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. * - * SCCS: @(#) tclMac.h 1.2 97/03/18 10:58:49 + * RCS: @(#) $Id: tclMacMSLPrefix.h,v 1.1.2.2 1998/09/24 23:59:13 stanton Exp $ */ #include /* * "export" is a MetroWerks specific pragma. It flags the linker that Index: mac/tclMacMath.h ================================================================== --- mac/tclMacMath.h +++ mac/tclMacMath.h @@ -10,11 +10,11 @@ * 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. * - * SCCS: @(#) tclMacMath.h 1.2 97/07/28 11:04:02 + * RCS: @(#) $Id: tclMacMath.h,v 1.1.2.1 1998/09/24 23:59:13 stanton Exp $ */ #ifndef _TCLMACMATH #define _TCLMACMATH Index: mac/tclMacNotify.c ================================================================== --- mac/tclMacNotify.c +++ mac/tclMacNotify.c @@ -3,16 +3,20 @@ * * This file contains Macintosh-specific procedures for the notifier, * which is the lowest-level part of the Tcl event loop. This file * works together with ../generic/tclNotify.c. * + * The Mac notifier only polls for system and OS events, so it is process + * wide, rather than thread specific. However, this means that the convert + * event proc will have to arbitrate which events go to which threads. + * * 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. * - * SCCS: @(#) tclMacNotify.c 1.36 97/05/07 19:09:29 + * RCS: @(#) $Id: tclMacNotify.c,v 1.1.2.4 1999/03/24 04:25:16 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclMac.h" @@ -20,10 +24,11 @@ #include #include #include #include #include +#include /* * This is necessary to work around a bug in Apple's Universal header files * for the CFM68K libraries. @@ -79,13 +84,109 @@ ClientData clientData)); /* *---------------------------------------------------------------------- * + * Tcl_InitNotifier -- + * + * Initializes the platform specific notifier state. There is no thread + * specific platform notifier on the Mac, so this really doesn't do + * anything. However, we need to return the ThreadID, since the generic + * notifier hands this back to us in AlertThread. + * + * Results: + * Returns the threadID for this thread. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +ClientData +Tcl_InitNotifier() +{ + +#ifdef TCL_THREADS + ThreadID curThread; + if (TclMacHaveThreads()) { + GetCurrentThread(&curThread); + return (ClientData) curThread; + } else { + return NULL; + } +#else + return NULL; +#endif + +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_FinalizeNotifier -- + * + * This function is called to cleanup the notifier state before + * a thread is terminated. There is no platform thread specific + * notifier, so this does nothing. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_FinalizeNotifier(clientData) + ClientData clientData; /* Pointer to notifier data. */ +{ + /* Nothing to do on the Mac */ +} + +/* + *---------------------------------------------------------------------- + * + * 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: + * Calls YieldToThread from this thread. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_AlertNotifier(clientData) + ClientData clientData; /* Pointer to thread data. */ +{ + +#ifdef TCL_THREADS + if (TclMacHaveThreads()) { + YieldToThread((ThreadID) clientData); + } +#endif + +} + +/* + *---------------------------------------------------------------------- + * * InitNotifier -- * - * Initializes the notifier structure. + * Initializes the notifier structure. Note - this function is never + * used. * * Results: * None. * * Side effects: @@ -106,11 +207,12 @@ *---------------------------------------------------------------------- * * NotifierExitHandler -- * * This function is called to cleanup the notifier state before - * Tcl is unloaded. + * Tcl is unloaded. This function is never used, since InitNotifier + * isn't either. * * Results: * None. * * Side effects: @@ -244,10 +346,33 @@ } /* *---------------------------------------------------------------------- * + * Tcl_ServiceModeHook -- + * + * This function is invoked whenever the service mode changes. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_ServiceModeHook(mode) + int mode; /* Either TCL_SERVICE_ALL, or + * TCL_SERVICE_NONE. */ +{ +} + +/* + *---------------------------------------------------------------------- + * * 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. @@ -344,10 +469,21 @@ } } } } TclMacRemoveTimer(timerToken); + + /* + * Yield time to nay other thread at this point. If we find that the + * apps thrash too switching between threads, we can put a timer here, + * and only yield when the timer fires. + */ + + if (TclMacHaveThreads()) { + YieldToAnyThread(); + } + return 0; } /* *---------------------------------------------------------------------- @@ -379,11 +515,13 @@ } timerToken = TclMacStartTimer((long) ms); while (1) { WaitNextEvent(0, &dummy, (ms / 16.66) + 1, NULL); - + if (TclMacHaveThreads()) { + YieldToAnyThread(); + } if (TclMacTimerExpired(timerToken)) { break; } } TclMacRemoveTimer(timerToken); Index: mac/tclMacOSA.c ================================================================== --- mac/tclMacOSA.c +++ mac/tclMacOSA.c @@ -10,11 +10,11 @@ * 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. * - * SCCS: @(#) tclMacOSA.c 1.7 97/06/18 14:29:58 + * RCS: @(#) $Id: tclMacOSA.c,v 1.1.2.2 1998/09/24 23:59:14 stanton Exp $ */ #define MAC_TCL #include @@ -1924,11 +1924,11 @@ tclOSAContext *contextStruct; Tcl_HashEntry *hashEntry; int newPtr; if (contextName == NULL) { - contextName = ckalloc(24 * sizeof(char)); + contextName = ckalloc(16 + TCL_INTEGER_SPACE); sprintf(contextName, "OSAContext%d", contextIndex++); } else if (*contextName == '\0') { sprintf(contextName, "OSAContext%d", contextIndex++); } @@ -2055,11 +2055,11 @@ { Handle resHandle; Str255 rezName; int result = TCL_OK; short saveRef, fileRef = -1; - char idStr[64]; + char idStr[16 + TCL_INTEGER_SPACE]; FSSpec fileSpec; Tcl_DString buffer; char *nativeName; OSErr myErr = noErr; OSAID scriptID; @@ -2274,11 +2274,11 @@ { Handle sourceData; Str255 rezName; int result = TCL_OK; short saveRef, fileRef = -1; - char idStr[64]; + char idStr[16 + TCL_INTEGER_SPACE]; FSSpec fileSpec; Tcl_DString buffer; char *nativeName; saveRef = CurResFile(); Index: mac/tclMacOSA.r ================================================================== --- mac/tclMacOSA.r +++ mac/tclMacOSA.r @@ -6,11 +6,11 @@ * 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. * - * SCCS: @(#) tclMacOSA.r 1.6 97/11/20 18:40:02 + * RCS: @(#) $Id: tclMacOSA.r,v 1.1.2.1 1998/09/24 23:59:14 stanton Exp $ */ #include #include Index: mac/tclMacPanic.c ================================================================== --- mac/tclMacPanic.c +++ mac/tclMacPanic.c @@ -9,11 +9,11 @@ * 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. * - * SCCS: @(#) tclMacPanic.c 1.14 97/11/20 18:41:06 + * RCS: @(#) $Id: tclMacPanic.c,v 1.1.2.1 1998/09/24 23:59:14 stanton Exp $ */ #include #include Index: mac/tclMacPort.h ================================================================== --- mac/tclMacPort.h +++ mac/tclMacPort.h @@ -8,24 +8,31 @@ * 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. * - * SCCS: @(#) tclMacPort.h 1.75 97/08/11 10:18:07 + * RCS: @(#) $Id: tclMacPort.h,v 1.1.2.5 1999/03/11 01:50:32 stanton Exp $ */ + #ifndef _MACPORT #define _MACPORT -#ifndef _TCL -#include "tcl.h" +#ifndef _TCLINT +# include "tclInt.h" #endif +/* + *--------------------------------------------------------------------------- + * The following sets of #includes and #ifdefs are required to get Tcl to + * compile on the macintosh. + *--------------------------------------------------------------------------- + */ + #include "tclErrno.h" #include -/* Includes */ #ifdef THINK_C /* * The Symantic C code has not been tested * and probably will not work. */ @@ -39,86 +46,120 @@ # include # include #elif defined(__MWERKS__) # include # include + /* * The following definitions are usually found if fcntl.h. * However, MetroWerks has screwed that file up a couple of times * and all we need are the defines. */ -#define O_RDWR 0x0 /* open the file in read/write mode */ -#define O_RDONLY 0x1 /* open the file in read only mode */ -#define O_WRONLY 0x2 /* open the file in write only mode */ -#define O_APPEND 0x0100 /* open the file in append mode */ -#define O_CREAT 0x0200 /* create the file if it doesn't exist */ -#define O_EXCL 0x0400 /* if the file exists don't create it again */ -#define O_TRUNC 0x0800 /* truncate the file after opening it */ + +# define O_RDWR 0x0 /* open the file in read/write mode */ +# define O_RDONLY 0x1 /* open the file in read only mode */ +# define O_WRONLY 0x2 /* open the file in write only mode */ +# define O_APPEND 0x0100 /* open the file in append mode */ +# define O_CREAT 0x0200 /* create the file if it doesn't exist */ +# define O_EXCL 0x0400 /* if the file exists don't create it again */ +# define O_TRUNC 0x0800 /* truncate the file after opening it */ /* * MetroWerks stat.h file is rather weak. The defines * after the include are needed to fill in the missing * defines. */ + # include # ifndef S_IFIFO -# define S_IFIFO 0x0100 +# define S_IFIFO 0x0100 # endif # ifndef S_IFBLK -# define S_IFBLK 0x0600 +# define S_IFBLK 0x0600 # endif # ifndef S_ISLNK -# define S_ISLNK(m) (((m)&(S_IFMT)) == (S_IFLNK)) +# define S_ISLNK(m) (((m)&(S_IFMT)) == (S_IFLNK)) # endif # ifndef S_ISSOCK -# define S_ISSOCK(m) (((m)&(S_IFMT)) == (S_IFSOCK)) +# define S_ISSOCK(m) (((m)&(S_IFMT)) == (S_IFSOCK)) # endif # ifndef S_IRWXU -# define S_IRWXU 00007 /* read, write, execute: owner */ -# define S_IRUSR 00004 /* read permission: owner */ -# define S_IWUSR 00002 /* write permission: owner */ -# define S_IXUSR 00001 /* execute permission: owner */ -# define S_IRWXG 00007 /* read, write, execute: group */ -# define S_IRGRP 00004 /* read permission: group */ -# define S_IWGRP 00002 /* write permission: group */ -# define S_IXGRP 00001 /* execute permission: group */ -# define S_IRWXO 00007 /* read, write, execute: other */ -# define S_IROTH 00004 /* read permission: other */ -# define S_IWOTH 00002 /* write permission: other */ -# define S_IXOTH 00001 /* execute permission: other */ +# define S_IRWXU 00007 /* read, write, execute: owner */ +# define S_IRUSR 00004 /* read permission: owner */ +# define S_IWUSR 00002 /* write permission: owner */ +# define S_IXUSR 00001 /* execute permission: owner */ +# define S_IRWXG 00007 /* read, write, execute: group */ +# define S_IRGRP 00004 /* read permission: group */ +# define S_IWGRP 00002 /* write permission: group */ +# define S_IXGRP 00001 /* execute permission: group */ +# define S_IRWXO 00007 /* read, write, execute: other */ +# define S_IROTH 00004 /* read permission: other */ +# define S_IWOTH 00002 /* write permission: other */ +# define S_IXOTH 00001 /* execute permission: other */ # endif -# define isatty(arg) 1 +# define isatty(arg) 1 /* * Defines used by access function. This function is provided - * by Mac Tcl as the function TclMacAccess. + * by Mac Tcl as the function TclpAccess. */ -# define F_OK 0 /* test for existence of file */ -# define X_OK 0x01 /* test for execute or search permission */ -# define W_OK 0x02 /* test for write permission */ -# define R_OK 0x04 /* test for read permission */ +# define F_OK 0 /* test for existence of file */ +# define X_OK 0x01 /* test for execute or search permission */ +# define W_OK 0x02 /* test for write permission */ +# define R_OK 0x04 /* test for read permission */ + +#endif /* __MWERKS__ */ + +/* + * Many signals are not supported on the Mac and are thus not defined in + * . They are defined here so that Tcl will compile with less + * modification. + */ + +#ifndef SIGQUIT +#define SIGQUIT 300 +#endif + +#ifndef SIGPIPE +#define SIGPIPE 13 +#endif +#ifndef SIGHUP +#define SIGHUP 100 #endif /* * waitpid doesn't work on a Mac - the following makes * Tcl compile without errors. These would normally * be defined in sys/wait.h on UNIX systems. */ -#define WNOHANG 1 -#define WIFSTOPPED(stat) (1) -#define WIFSIGNALED(stat) (1) -#define WIFEXITED(stat) (1) -#define WIFSTOPSIG(stat) (1) -#define WIFTERMSIG(stat) (1) -#define WIFEXITSTATUS(stat) (1) -#define WEXITSTATUS(stat) (1) -#define WTERMSIG(status) (1) -#define WSTOPSIG(status) (1) +#define WAIT_STATUS_TYPE int +#define WNOHANG 1 +#define WIFSTOPPED(stat) (1) +#define WIFSIGNALED(stat) (1) +#define WIFEXITED(stat) (1) +#define WIFSTOPSIG(stat) (1) +#define WIFTERMSIG(stat) (1) +#define WIFEXITSTATUS(stat) (1) +#define WEXITSTATUS(stat) (1) +#define WTERMSIG(status) (1) +#define WSTOPSIG(status) (1) + +/* + * Make sure that MAXPATHLEN is defined. + */ + +#ifndef MAXPATHLEN +# ifdef PATH_MAX +# define MAXPATHLEN PATH_MAX +# else +# define MAXPATHLEN 2048 +# endif +#endif /* * Define "NBBY" (number of bits per byte) if it's not already defined. */ @@ -134,100 +175,82 @@ #endif #ifndef getpid # define getpid() -1 #endif -#define NO_SYS_ERRLIST -#define WAIT_STATUS_TYPE int - -/* - * Make sure that MAXPATHLEN is defined. - */ - -#ifndef MAXPATHLEN -# ifdef PATH_MAX -# define MAXPATHLEN PATH_MAX -# else -# define MAXPATHLEN 2048 -# endif -#endif - -/* - * The following functions are declared in tclInt.h but don't do anything - * on Macintosh systems. - */ - -#define TclSetSystemEnv(a,b) - -/* - * Many signals are not supported on the Mac and are thus not defined in - * . They are defined here so that Tcl will compile with less - * modification. - */ - -#ifndef SIGQUIT -#define SIGQUIT 300 -#endif - -#ifndef SIGPIPE -#define SIGPIPE 13 -#endif - -#ifndef SIGHUP -#define SIGHUP 100 -#endif - -extern char **environ; +/* + * Variables provided by the C library. + */ + +extern char **environ; + +/* + *--------------------------------------------------------------------------- + * The following macros and declarations represent the interface between + * generic and mac-specific parts of Tcl. Some of the macros may override + * functions declared in tclInt.h. + *--------------------------------------------------------------------------- + */ + +/* + * The default platform eol translation on Mac is TCL_TRANSLATE_CR: + */ + +#define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_CR + +/* + * Declare dynamic loading extension macro. + */ + +#define TCL_SHLIB_EXT ".shlb" + +/* + * The following define is bogus and needs to be fixed. It claims that + * struct tm has the timezone string in it, which is not true. However, + * the code that works around this fact does not compile on the Mac, since + * it relies on the fact that time.h has a "timezone" variable, which the + * Metrowerks time.h does not have... + * + * The Mac timezone stuff never worked (clock format 0 -format %Z returns "Z") + * so this just keeps the status quo. The real answer is to not use the + * MSL strftime, and provide the needed compat functions... + * + */ + +#define HAVE_TM_ZONE + +/* + * The following macros have trivial definitions, allowing generic code to + * address platform-specific issues. + */ + +#define TclpAsyncMark(async) +#define TclpGetPid(pid) ((unsigned long) (pid)) +#define TclpGetUserHome(n, b) (NULL) +#define TclSetSystemEnv(a,b) +#define tzset() + +/* + * The following defines replace the Macintosh version of the POSIX + * functions "stat" and "access". The various compilier vendors + * don't implement this function well nor consistantly. + */ +#define lstat(path, bufPtr) TclStat(path, bufPtr) + +#define fopen(path, mode) TclMacFOpenHack(path, mode) +#define readlink(fileName, buffer, size) TclMacReadlink(fileName, buffer, size) +#ifdef TCL_TEST +#define chmod(path, mode) TclMacChmod(path, mode) +#endif /* * Prototypes needed for compatability */ -EXTERN int TclMacCreateEnv _ANSI_ARGS_((void)); EXTERN int strncasecmp _ANSI_ARGS_((CONST char *s1, CONST char *s2, size_t n)); -/* - * The following declarations belong in tclInt.h, but depend on platform - * specific types (e.g. struct tm). - */ - -EXTERN struct tm * TclpGetDate _ANSI_ARGS_((const time_t *tp, - int useGMT)); -EXTERN size_t TclStrftime _ANSI_ARGS_((char *s, size_t maxsize, - const char *format, const struct tm *t)); - -#define tzset() -#define TclpGetPid(pid) ((unsigned long) (pid)) - -/* - * The following prototypes and defines replace the Macintosh version - * of the POSIX functions "stat" and "access". The various compilier - * vendors don't implement this function well nor consistantly. - */ -EXTERN int TclMacStat _ANSI_ARGS_((char *path, struct stat *buf)); -#define stat(path, bufPtr) TclMacStat(path, bufPtr) -#define lstat(path, bufPtr) TclMacStat(path, bufPtr) -EXTERN int TclMacAccess _ANSI_ARGS_((const char *filename, int mode)); -#define access(path, mode) TclMacAccess(path, mode) -EXTERN FILE * TclMacFOpenHack _ANSI_ARGS_((const char *path, - const char *mode)); -#define fopen(path, mode) TclMacFOpenHack(path, mode) -EXTERN int TclMacReadlink _ANSI_ARGS_((char *path, char *buf, int size)); -#define readlink(fileName, buffer, size) TclMacReadlink(fileName, buffer, size) -#ifdef TCL_TEST -#define chmod(path, mode) TclMacChmod(path, mode) -EXTERN int TclMacChmod(char *path, int mode); -#endif - -/* - * Defines for Tcl internal commands that aren't really needed on - * the Macintosh. They all act as no-ops. - */ -#define TclCreateCommandChannel(out, in, err, num, pidPtr) NULL -#define TclClosePipeFile(x) - /* * These definitions force putenv & company to use the version * supplied with Tcl. */ #ifndef putenv @@ -238,26 +261,23 @@ int Tcl_PutEnv(CONST char *string); void TclUnsetEnv(CONST char *name); #endif /* - * The default platform eol translation on Mac is TCL_TRANSLATE_CR: - */ - -#define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_CR - -/* - * Declare dynamic loading extension macro. - */ - -#define TCL_SHLIB_EXT ".shlb" - -/* - * The following define should really be in tclInt.h, but tclInt.h does - * not include tclPort.h, which includes the "struct stat" definition. - */ - -EXTERN int TclpSameFile _ANSI_ARGS_((char *file1, char *file2, - struct stat *sourceStatBufPtr, - struct stat *destStatBufPtr)) ; + * Platform specific mutex definition used by memory allocators. + * These are all no-ops on the Macintosh, since the threads are + * all cooperative. + */ + +#ifdef TCL_THREADS +typedef int TclpMutex; +#define TclpMutexInit(a) +#define TclpMutexLock(a) +#define TclpMutexUnlock(a) +#else +typedef int TclpMutex; +#define TclpMutexInit(a) +#define TclpMutexLock(a) +#define TclpMutexUnlock(a) +#endif /* TCL_THREADS */ #endif /* _MACPORT */ DELETED mac/tclMacProjects.sit.hqx Index: mac/tclMacProjects.sit.hqx ================================================================== --- mac/tclMacProjects.sit.hqx +++ /dev/null @@ -1,3157 +0,0 @@ -(This file must be converted with BinHex 4.0) -:%R4ME%eKBe"bEfTPBh4c,R0TG!"6594%8dP8)3#3!`*39!#3"(@,8dP8)3!"!!* -39(*-BA8#!*!%&J!!)#!1G'0X6@&M8(*[DQ9MG(-!N"'MU!#3!p%"J!*L!hF!N!- -(!*!2KJ!!!J$rN!3$!+df8!b`K1qP!*!&$&1Y!*!&!Nr1rpIrq`#3"Tfh!!d23Np -"Ae4ME&0SC@aXFbkj!*!3IPF!N"%@!!![#`#3!aErN!4069"b3eG*43%!VllJ3l# -%lG3!N!8"UPS!N!BZ&3!!BV3!N!CrmJB!kh(#A3JIG)6GpKBPYieXKYrQ8hkaMLE -2)i``3VPN(l19QGqQFLURPpb,r$jfDiCR+Y1h[AU8HjYe2GZ%fbAKC*maF[YXB%F -fiB4h$Q+EeE(YNAeq4RKQ6ik6jdrB(K#fb6EGK'GQN[fkMr#1l)'%Aa6Sm!Hd!Uc -(,MplhDIbmcBMqmKY`XNQ[mNQQp`QYmPqm6`+X(jR$I)kXr20JH`FYFpciANj@0J -qHrCjA@cKTPY[DfFPffaV(5[GCPSA[r)k[Nc-M"I2kc+rXc-[-ehXq"@rHXqV-c1 -q[#i$hR@m%H6,HjhIQBfd33-6!![JV-[VE0LJAfZcVENK)pbHl$MCj"D6,3#Fi$X -!,pp"&AbrC)a*ihr%T$kb!IprEXa,,d6mQK31`CGT409+r&q&#hr%Q*-8VhcFQ)j -ZM3YTI2[ZD-qhqQ2K-hFm)5TG$R*qFQTGkT!!p,P2pDBMCFE(kfPI'8ra)p3E(rP -Hmf&MhM$1RdjK8X*Cf0Zec*pZfI@Pc%(Qd!5!+Pc(I!*cG2rd+(2)P+aIb4Im[6h -U""C06pf@AQ22j5BUmil8pe1E$cV"c%3EEM6Q*pPNLNQM8iUK%$-+Z1KhQ+!ATkj -2E8NrXQf#JYi8F#iGYF@fa[I3Y6Bc$ImMD6CS5G3Ph`#L9A%PAlcq&QSkq%lKE%M -Xl(TjqVXBrqf+DCE80N@a0q)rUpM[4"fhh`Ia2dfa[m1r)*!!BMdc&&Z%`dc&(Sr -$BBTY`Q'@BXr$BECLeq"`Z'+rUVNKp[Xic&(XicJFUGKri6"A)%L2Me,X1"b19Q` -0$[-8Z`L(qBVp)!i,&(Xe$Pf+rCVQKGJIip#Yf0rLd#0SB6Ck&9Z-3jpLMm8KTpL -j10"rBXr&JAZ)r4J1rBUp!BF"aAiEKd(&rKm13iVp-`l$JQ(,H@f-[La4M*PqK'* -2aZ'4LJ&Gd&eLe(fXBY5p9,&hik"a`m3qM!1c3qaIF(K8('[Rh"k['$@IS0LT1$a -DXA0`1&%a-1dNaDl'i@6&IPli3qbG1(bRBTUrYl8VpSmi2#D1G4"(Q#PLc!2e%L2 -RFBTY`!&X)FCm'mc8X4IKX&bakh"BSGJ[il"5XIILF*TLp'#9BTr!BE9LAm,Kp$L -@*6DGS4Kcm%6&U"qF)FEmICGLcm,K6-9q'!I"j5cajLc&IJ@(GBVp(JkMLYf&`j- -8q`GK0I!,"UaA$!bJrm5B@fSR4YqC4f+F0bU'EJ)Z%32rcP2XTh%!NiQ"IqFV"[i -p4E(2i2$GF@`D-IkTLS'*Qa9McTqQ',hBSYJ1(*kZf%Y`Z%!akYkUf+rMF+&LIiE -$-a3$KjiCakD65fa6$%aNhSR4EfD0'2A$CBKGL3-p*rB+(*kYQ1C)E4A&k,&3[1Q -FqdX9qdmF`'hpc5!IZ%`am)jq%Q2QKEr0B"rK-X5q(iIR+rCD(%4YQR%M$PFS"Yl -3(f+I`Z%&F@`Q1CZ`ZjQXqi@+JF9J'M&`iIX8SpI85`b-%3Bk%ebflCf+86Ic6Za -2F2JKaIiD"qiNGMF1m$lp(8BqKTj'$&laSiU"PF`[-I!#6N'-hVe8-@Ekaa9l"`l -J2l'2i[!baIi0Kjq)Bl2)cH"pa*LYPbX'EPfV',-(KK2M,QDCf!di[&+a2mAK*aA -l0!k[LQ1cb@Pr5M%i'0K,$*l!M"!$"jP6BX`E256f1Kaq4V(I`S%iXBrKm,1+I4Q -(RiYMKj02[Piaq"*mKaMi$ZFL"JE"UBNa*lqJ',cN6BVp!3krU0MIi2$Q1(B%XH' -A&!2lhk)BFh1pBY4+,F6!bVFU"Ll!0BJa$r"VBMIK`"`4qd-F`%CLIiA$fa6lGac -J"IUE3ll0RF6JC$FV"KplZf*J2hK1M(lrKQ,d!#`LaLb"$m6)J3m5!rY[83c1F@X -F1j+Fqef+dA[QN4MF&Hj-$-i'Rb8'2d'[)!B@[dFa-1*h&D1rF%"LGq!!rb)'hlS -YMXfPaS(q3!bZcQ`5!`ZC&f,8qMl&`26E&@21rNJaCJ1Z3BamF*JB@!9fkHmSFM[ -k3!apiIf+`DXrS"Lib)`3Jfr!)iL"JhFUaMbMca#MYJmTKNi$apHIN8FqSKJm!h` -Q"SF$hiM"-p%LL-&ji+6%`1Lr8!bmq%[&k#Qi3Hc[F8#VdGmmkNG`+f,S&r!1B[" -`m)dB(2+6LX&Yi%6%`!PQK"KBJ`j$M0QJRm5B9l"#Ir1T3e%l-I$qXiSaVpa$$+k -'cN!-r[02LS(Gk#h%`!ki*c&Qi&m9JbGp,SiYS"j!R"MDbZF9JaGq36(`liZ+`Ar -3%iJa0r!JB[35M#9'cIm4alTB(cb8'"J2eb#'&S$f43b1+VTQ&hL4NrbkJ$G1fH` -#"LMTIehSYC,qYa!DR0(VL'Np5%Rr@`KG3dRr@`LHV+6r,33I8p,r&Q)@PI5rKF! -M*Ie[)AUYT2pe3ip6d[qkS8mSkArGi#K+qPmhZ,H5rYF0EUHNrh8$`j6d[fjJU*, -qeiej9Y,rHP#cN[lA!ce!5IrV!DiSkAmpQ(8PrDm(2&P*rqX"ae25rhV!2C6d[aj -JST,qe`-X80,rHY%l*If[&pU2N[lA#mkKT2reJJFSkAqpi$T'rb5QF89*rqX&2e( -5rhU"+dVkAbpQ@dRrkd12P25r2Xk0k(ppd*+8p,mqD"p+qPmIZ,U5rYF(VULNrr@ -"cbMTIhh!8bAp,iFj9p,rFZL&N[kA!bG@d[pbd'Z8p,mFm&K*rmYaEN6rbi'R+HP -r1A!'*Id["ha8d[m@BBD9p,p&a"M4raDaPk,r,B,ZSk6r,B+qS+6r,3+r9G,r&S& -I+HPrLm!(P25raF!JSbd6dr1MT2mY4Vk5rVFBHTD5rVFBr%a*reX-IUDNrbeQ,dA -r@mbj&2f289A5rrSa`dVkAcma4[5rIZKC5[TI2rXRqPmrCe(d[hj`5#ApVapF48R -r'b#ZL2ihJ0P@d[m'L-'Lr`e`eNAr'i$1SU6r$8!M80,r"SL4S[m0%,G%raX%2LV -TIi1B95ApEa#DKj,q0`K0bQMba$5290,r"SRaS[m0JPXUkAq$i$C+qYm3F&P*raX -#lLMTId1B'5ApE`KR*Ie[#&U4N[ih"%e(5ImE)Yk,rMF%lUfNr`f"CbVTId2J5dV -khc$l+[VI-,&Ip,pKBTMSIm2SYC,q0`bHT+6r$82R8Y,rKU(&+1Pr`p!4P25rBH+ -Ck(r$a$24rdE!6j6d[a(@,IVI#$$,H"Q)kIP8d[p'8(r$EHBlq-!,qNhYm"2`!*` -"JjJ*CSFHd60`(Vi"$f!'dI1B$l4+F"01!1D!4q!(H!,@J!(-1l-0AX,Mi$0`+AJ -+Fi8H!Jiccr"#H!4m"Vi)Ii3AJBAJ*"J+4i3(JHp`9VJ'(!$-KNI!(q!+i$Di$pl -$#q!5m!Ei#,`)MJXIJ4I"0H&dm%#i)p`%rL0BDc4dH"*F$ii(Gi4$J5R-0p`6[JI -f``8J"I"DZ"ki#Hq%4m1h`94i(c`@VJQRJ#H!Sq!NQ!L1JQ0J(eS[I-(jEm"'H#R -B!aD"1q!0A"JH$Ym&Rq(RF('`8AKGr+&MDJkDK8CL+,[Sb-926`QZ*bdK'`dKIp* -q+I[PAC3FXM49@@P"rq[5TPa-Zlr(ieZHbj%2AV9NPhrUSAU#B0NY4Gq5+UI*N68 -lZhMTSN+Tfmd2Zl9F6M4ar"-,QIRd2-jHQ$mRRbRPJm!0@PGlBK,KYkNRjbcX1)Y -SU1qGPR9V)kl6pmrC#HD'*Q6QphBY+Bak`lQD[f,a!&VRr&jfc&2bp-9Z3`I"`,+ -$,b$)@Eq!8-S!2i!Hi"dS"GU!DC&f2!DIUjXHZGl`d40k3mrS&IfMPr5$[SMmj%( -iQ)@4JpN@5!B!IH`80Q3K'M5-rb(m$q*r%IiAilmIrchicq)IVEFArdIMIcVqCq0 -r&[ke69$6P`GK1E4Y&J$kQp!@fbIc-"I$LQKiYJ26"h-pVG@DZpb6aD@%PR+5XNb -h+-FB)lrfKIG55pi0jcj'8Im[`EmH6#0dCI(IMrm"r!rLIaMr2IM[aIpdr2GC"f5 -a8EkIEr25)-cArN8,I3#IqJ1-1P0`IZ!M8Z&)%13$%J)"J@"!,"cjJ3a"1"`'qK8 -qqN4rc2R'Y3p"Iqq6PbRm()[c[(hhU4)G)SlLM3p3-L5A2J6GiTZFdRK8,&%9!Ua -MN!"arCr#re(iRiGrc0XCr-r(rdcm(iEr,[bhilm$reRm6m2r,2`IBDE)0[Brhrm -a)FhDeqB,RDZmX$YI'5kj%U+rrL@E%&!3Ll`jT[J(ek!m)(aj"0BHq!-@0&Kec+' -HrCaZ-QHEEV*b3AE@E*Nl'PmXC34kKA4qkP2QUY4A8SqPYfjIjB#P$LXG&MUXFpM -4X0aKRF-bKe81bak@2+ab@15`aQ'*``U("3lV'jBhV'jBh,#CB@R$bSD&69[lX!4 -K"F)#K28(5a'@)D`r@(k`qQ!j`P+%e3H,$pBH,$eBHE$`B0h"XS09"iX1eK`X18` -!&KaM68,kaRk![)lXM68!'4YE!TB&V!IB%*!!bV%[B#r!QS`P'ANF1c)fC14dl!F -!!*L$C1lNF[!&H4ej(SX$9JGNFf4ij(HX#eMZX0TKXF0DKf825al@1K%*M+92@rE --)1[CaMU(C3kV("BjV(&BiV$#BB($qSEP$DZEXEKKKp1f!Da#@)5`"Q%j`P+%03K -,%&BJ,%PBMV!#B3(#qS2P"kX2&KqX29KkX2*JiF'kJf8(U`i@(@0G`P+024Tl*YC -T,0PB$V&1BjR')STP'dXf0PJXdPK8X83M(f#"a[U-j4RE*4CRV-hB)V%bBf('XSa -p'GXbGQ9Xb[3C134T""A8kE$B*V"E3$L3!%kJD0JVN!"8X)9J-d&D!G@a*cMC"6X -&&JcX'PJSX%0J+A&,EV"bB09)C"Xi)VCGl,VBG,(R`Yq`p@,2aAD,(4GV*lCIl,K -B9V()BV[&KSR0&RXYYPVXY0KSXFpLQm8ZLde@fiHa(@)ha'D)[4$E)VC%l)AB#V% -6BQ[%YSLG%"XKpN&XJpJ&X3PL$m3@L"d3'b$f2farf2f`q4Rl)lB8l"hB9E$RS$5 -$S9KbX1eJTm(ZSZmfpKGp[eN6J)9@ef&@!m"jG)h'QS1G"SX-eKKX--j5!b(%iS+ -0"RX0PL(X,9KCX1KJ)mFqMQdFHc%fG'cQf&La8@-2akD1$4el1&CG,-rB`,&rBr( -'lSh0'hXhYQlXh0LiX@pMfmEZKqd31aff6@b"@#UaMfQ1J!d-qaFf0'aQf,q`I@( -h`ZD&[3YE&hBZE&cBYl"YBGI#TS8p#eZ@XDYK0B,*B6Z#Bf(Y`DD$&3QE&0BJV$i -)j9KkX"Za6S%e#Q!Y+a5`$X2XX%KKMF*bK8d+1a(f+#aAf++`,f'C`MU&93PVNl- -ZlIN15Z3H")&'UM3R`j&eDd!+3p6G'!4H$6F233+$F4kZl$eBE0Y0KVdKj1,lqUe -["Cm19"mPQ1TeX#pUKkp'-p@cGH5!9kk@A!G55'jHAmF*F*!!L2RBIYrM"FABa-@ -5Nc38#+-db6)'Vm'RQRD[De2hT9-(4Afj#GaQRT0)X9l00p%4ej8CrAep-K,EVlf -VIl$ZMP5(F1VA&pd5"CVXJTlH6[TTj,a%jhkG"h8HdIN42'0XbPH8QTVe3lrQPr* -1VcG8bpHS"U4i%8+XA(K8mm,diGR&ZZSLPr*1TkUEVXZ1eZ@cG$j#qEh+0hNkhU2 -il'CaQCH`[fHlJ6p@+d69TA9E6QIAmq(QVGR$H'[B[S`U-a9$++36-a9IR"MLPEb -2MR,AD1cjmX(BUZDfC2VQGlBi,I-l&RAJ10U6@D69$Vk8Va1DQ5@5QN-#Rb1aSKj -6b9fI[[A-1Y(d!p$,23J)QBdFBaJipE&,%#K@bq"6+@dqd[R'P"VHipBZ5N*i$`, -UmMhh"-A"@[6ae!2h)+$11(!2)LZQdpBpL,Cc*[UG[`F"m6`U+dB5+Y3MZmJN9`Y -[B6ee-U'c%"r0`V[GG5-!BDTYhB-)1Zh!2BLTPqqj*qS2BZZ1!rF!mYX1h)-)qm` -$pi#AfrIGil(q[ZP`a)ZifDYiSCF[HDZe+qHqc`2JbYiFZV@b9mQ(rbMr`%II-@m -P6N8NHX6q*!p1MX'VQ(GTYA"P,$PSj3$e3)6-NJ!C#iajD5m(df9H(,`mFQ-ZVeC -l-)K,#ia[F!0&G'BB*,*ZD!@#flfK-XTG1ZcE@&Y2"C2dM(c"4CPY!cepJdYDSDN -[CA4Y2La'jifCrV&+k*AG+'hj'3-p6XEHSPYd,'1k)#RG0@PTc36&CY0(#hkjkT8 -mGpL*EBbQ[hB-)JdcE(,NH9aD,44jc5QYEDe"X93[9Nr!GUq3!!mp[i*kG64UeGV -&LK)FVEP20-$9QM[HQ69le-Ri`kjT@Ja')P&)CaCRPh[dP@'RQ!*pMCN#hC9e!e( -%cT1Z)4LFeIN66[0QcKiq-@26C-ad1'Hc6H+bEBd`4JHGPHXT9reDk#$H0LpI+[P -q"FhFAL9ZV*bCQ6%MbY6"dAa3b*HLk0RZDS2cmU"XPQ6k&LcB9X0SjrC`A211iXQ -!V5@QhF*9$Y0AZ---5,i[1Yk@c5hH(RDGND"dKQLqHT1m[KI)%Nc#j[SNf$a3jV6 -HhLKDQ+``hd@,5+Bc%QM3+4)[iPfpI,NVUMKr2@fa%Q)H+'41BRfad!QE&438`C9 -0&F#6H`cX-B`@-b[P9DIAPN#Ac2e`!jfZkeek%h-$XU($BDi&!dK,rMil*-%9p'F -C@jkr!Y6M9SIPG#ZJ"q"SR1J3NaY0@`hX&4Y'K8Pb-K!"+6")C6%j`HF#VE,Pk-! -@%)J,Jd,0UiEa3136`TUM@ebKq4c6MiYhhK4eUC!!DDDVP&,N06#l&9hJEIUL&9h -ac%IBZk)VCJ8Aq*A!,lQY36Jf&*!!mef-qmrSl6c(VB44R1[AjVd+BZlq&9f2Jd4 -!e&Cd%EUN"kX@GB*8*AF@1C'p85ia`4#2BNb-5JXDiX)aNb9MAFIZ&,Ndl*D4lm- -1VH[B`9b5a+4hmIf*'D$3[8+TX3'0!9hA8AFQeEq1jldU2T@[!d2Krp#5[!*[kbL -A*QYF[6kI,f)$e1'4+J5YeMcdNY'rE8r"jHFiaJ@PhIHlaE9qYip0)#bk#%hS1Q& -QhH#qci3H*"6YeJ'TcRrN&Hc@-*ecNarXeKi!Y*fp3f(`e+'Y6q,c8k`AD$YU3T5 -6,h,3KUXD0L4(F!GX!2r0(Bjm8MD-krI!F3FmBPZHA&$RQrRFZMlqCfIGX1D[G'Z -MJF-YIlQ"BrUG%e0Y'kp*Y5fI1pMRp(FAcE(1!%mV@UE2`6Bc[HCTd4e6Tbmd)mj -Jr,)"B8QTkGr50SR8T[5F$IHBLbkkU2k[lVpkQGQbCF[frpGJHfX8[hlpqPeh(2b -[pV4f9e+lrq(rPTY[6NLSdhhqL,k$$meF,`%qh&-l1f(dM%cYJ0$h&(C!G$bp!d, -I`ik&drEF%a5Rlf((!RYQ@[H``'fe[5Ilp#i'I3p'KkRG$V*NDfTRJlk((3Y61a[ -d25bMQpVCS1pK&m28cJCp$cX@TRBLk([`"drYBY$hS%e-lAD3!0A[8lXLj*k,%Va -h0[J+2NF#f!MK#"8,6aeCJi-iEaV,1TeIK"eNEP8K#h$GqmaBU1[HCmELA2Fq-aC -91SfCjE$ZJ3`XIR@2H'#CUlc2aLc`G&XU@0BTll-a5e6PI6CQ'DUmcmBX)CEhfCJ -PZZjpC[44hQGMhQ-Mll-alk@4ppQBKF$b2K[cIKKjRiejIiZmcmDmI8AHCf2HK5, -[Xc([,C(hf5JZjT6hf5JZYCAhf5JZ+CAhf5JZ(49MRf)[jAdfLXZ8jAdfLJZ6jAd -fLXYrjAdf+IC5hQH6BLrNI6BT,P59*9iT,JD9r4-T1Rj%FdpaNE'mcbE&jFEb2TX -8Ppl+qfc-BQTjadH+#ilPI6EQE@Vb2TX8&kc+qfa5l+@mcbE&aEEb2TX8&4ajRdf -+LjrPI6BT,MU@ppQNL4(b2TXdje$HCj0QIq9p0ZRkQdU)X5K9a2-dPbI,qfc5A0i -Xll0*FqQX[-mQ6Bb4ppQNZ5aB92mdHbC,6p0FZL[[XdPcXE@mcbE0KG6b1SN-F8h -HCj2Kh-VlE$,XPlc2*X1PVI)qQ`bG9[)qQ`aa3YjRNq'LBAQIMAN(Qkc`cR!"XVc -2*N2mNrICC,Lm9YjRNq%LBAQI6BD,J'ArAiBi)HqcbI"p4r)qQhELYEc2TTeB+@X -9fiP0mMkEGQ+"[-qQRA-Pll0TCarPI6EYh(dLll0Tjh*XHCp01aIkb[YXfVRF@Gj -RdmjHb[YXfSN6mMkEGZ+h[-qQR8Z1jAdflF4XHCq0S4,b2TX1iVLmckD$IC,hfCJ -hYiP4Yi0pN[ICG,!AmMkE$Z+"[-qQJrjDHCp0"r&-hQI6`BA5mMkE$Li6&Sp'"rX -Nll2TB*rNI6BGA(iZ'pilb#e%Zmq5fmMlE,,N$')AbE*RmMkE,2&)$+KCcVDmcbE -,1C(hf@4jP[ICC,NB@pE`C,N!@pjRPL8Hb2[-XX3$m3kE0lV9hp@bji022!qNch% -k5r5H[h(YMp$0Br4D+NrEp`+Tbb%UA!P8d$chU)Bklf2lAXKh5m5Sm,dEcpq!0H4 -RL8Ali$k0%+L)Bki+jcE4pm!qae`DqAX!QM(h4IiH@#c2f'RGBjlVdp`iQVm(rM1 -e19AIJ`S`YX%dI`mUja&ll[Q"jMhQf3TIl52Uk'2fE8ie,`M45YKAld%aRA,Ak(Y -38*ZZP+JH&0@Qbb@k"q@Nk9k*lN(aE,TVSRY3CTXE6$haPKG2`QII4S6M*3X#1bX -4c[P[elHVp[B4Yq,@[%*L'b!BB89[E9R@AXiRYf'!`3(lR$L0!m[#85`apEI"JD, -!2E1*!eGJ,DkA$3J-$Kc@a!&[QdaJheIIPQk2Gj'Y(kYb4rSbEDhhUD'"+[(0BL8 -F#$DCqp13!%"aAB&qlFkbjXD`p5&H",'P0Par0m1bk"8%bqCjPAEcaa[mA6LJp3( -$#kG``*bH8bllPIEFf"$H5*(VU44+Bm-*BD6"i%$f,cLJfD1A$!3F$ZMA,#eVjp0 -'YS6*E9B5G64`3$m98Z['DrfDZm$$Uc*bTl5HeRTUdKSL'$i`23&U[h#ZQmp4*', -h#hpP2(iC[6kErF,jH2#Ia&YjZr1V2CfUZ4U2[XNqY(V9V+@9Pp4eS)llqrH0qTV -phhYIYHlQ2II2cB'C(Dr$,rGU1V[0`$ab@l2-f5pk(lBCq14Fl&kiV4Ek-fj&lpX -fJlX5ilBCJ!2hE$0`lQAlTVpPjXqhq,0`J-1d&l82@bfZ6icEDR&AY0A#[VLBEHV -6AJ3[q)qeBK"SL2Q3!(QipFCmVHEjYEql6raC1)"qb'XVr(0EpAec2[4(RC+i"J5 -bPq*KqmC@IIefGAR6ZAl3qE*Fc9rK&N)Rk`8&mhMU4Ur5Rk&+F#N!il)Gb9I-RK@ -Cd%jh+lXcjF(Tj83TYjJjQJm+qG*%UC+Yl@kAH*@4B%IfUQ%[p(GHZGU[l+c4,-0 -[P#mcX'T9@-[[V'rP@"$kCHH0lPYAqVAKRGR,#`8h#*aF2LcZ6&dajT@'Rkk*0lR -AKiI-dl`J(`4ZHHL*8FJrjVfF@'rZbTQC'6-Q4XXQ0bE,[[mpQC943N+eG@41Y)l -d@ZY)(1eFm'4@I9T(-ae"'50hL9[DNAUfZhULda[bY4%hG!EF-0cGDLL4eN%ZV8D -j1iS6!"PR&[%acShJXC3SBe$+FrdZe&r%aQTb--"aXL"MR'1!-Fk)FE(@HB'`1$G -"a6Jj"X8i-mE%1$1#a&*L$#ZPl1Si4AKBD&`"$LZjp@%5-#`-5"i,5iRM2FXMB5N -2)#`ReDBcJX%i-dE"1$-"`3)da"LS-pBAhG)1r!ZbLYJAj%@i&bG*`q-FepH`eL, -@*BR"D!D*JR&"h1"E%)faVG44JD%J,m'd)$('Xb!VaV)J+m+a1#R'JcJc'Bd)Zm, -Q&(#VQ&FH$-'VX1PjV)U6kRh*Be5F!ci9%NV6&H&5N!!9Be+3!*AJ86M'-4DG0(Y -dJT!!&9+,U&4)MU#TR#R0,LHk"KHE8%5U@RB`PB9X`Da#NJ'Z3NU-A[8C%23T*#F -i9XL1`Db3!"SM@L%eJV9bCS`KjI6DE%8S9qaI!HUUbBh*%Y!VcNSHqFUC%kh,Bf! -j%5#XC0@R0B,%3QU-LiA8""b,H"%MT--$Nh@Q&qc86*lBlr493krXVGiPM"L8@6F -@9XHH8Xc1bHl)XPl$Y5kD8b@IFD9PS8%+,5IU1Z1NFTN"1BK,,(!p+Dq3!+4,#a, -+C4A'+UkY!XG5B#969eR)+TGUi@N#U8XAa'"GbNi3SR4"!54+k6(HPl)Mb+mPap" -CZd(3XjEVS,)m&!AiEq3($+#FEdP!+5mHl9*f00hej,''ZI%[*Ai9!4)HfEaJ[0d -4[DNPlaV62-QTjF*ckSR0FBMC6LNl*MbPl#+",q9((,k@h'aP8@jDdI9lbFHP*U+ -2bkYS&LkeT+#ja%3UFRP&X5K+5f5C+$F8CU+XDRY,SP%K-j+0JXa!1()C#GpbH8A -'&DG9QT(RBLkP4[*FFN8-,+C@feI8ZD+djNJ9Y+iS5p5Z1+AFf%6aFRPe(AC&ek4 -qEY2V#VV0(40aEAV$bQ#6krUlcDdTm'&UAFm1ma0&1m`XbGFb!JdP2XSZDr'5A96 -ME9CGHl#j0I8KRpTS8NQEX'N6)SLpB-be%DFhfeXc&S5TNk0B04H%QE'p)*p@Ehl -GBQ"c'm*9(Gf5r)B'@FHh*,qT$9F3,NQZUjJ0M+YH8*)$bbKAQS@QQPR$Z9*kSQK -@N!!Z5Di,94@XUbA(1PB6lC)EaZA`1Yk9mQXDE32aUKFd"V1Xe*C"Vj*E9@XVX"H -V$(ANUe`aVZR9mDpbaB5Z9d("5[kBYYI!`XBG9E@PM)M9-CR3q'Ui@,fKS[09d,' -52kEe96#bQCrSI8fNV&bb8r1VifAeLUEZed$0aKhM)ea6rmV`@8p[+)!9%!ejjEU -1Cj84Qpq3!%CXmVJfB[1EiSM0EUJM0VNZMi5j$9)HAP"Lj@&UQAr,,$3PNLLp)L* -)HL+5f,5'5Q+6kc**2VICUV*3B[-QP4*l`lK8%ZH2YENZPS5j1`Hc*TH%U3@p**r -AQ)+'BQ+6Qj**(IG+&c4&NcVbP5iBNddUf&I+EJJR$I5Vh9"Qk'Am+`r&Q(K53m" -bINNqU@"J+EXKS&43X*jGN!"3QMKBZQ*#4+NMBIQ#ZSc5`-,D$FdaV5JTC6LX*YH -dP!SJ&RKL(41VGdc)+A9NV0ia+DK8m,&k`ELNdN$*jL8e4Pl'bYUm6-SU0F5XA9% -99LUi@EeJA&UTS1IB"59aTBQKe9Yfb5Ye*+hG-5D`02#dHFR%30FePM+`0[+E+NX -&AR@#6KYh2ERFNZh**9Cp6bkhE(abQ5ARNdY-V%p4AXQS%bARR6T4@Z6,#ITFYMm -98Q-$8C!!'KUJA%V*!H85%`Y8R&GY5@5#FMPe&j6,VYUJLVQe0LC'U#K[E-#+9UJ -ScAQKiTa+KdYZ+*FB`j(Iq8ZC`kE'R#-2pm@[Ub1AkhfKd+IKIhQe@NS'U'0YYRI -H[R[dDXYF6jNlN!$TE2f1YERH"3N"G@c-c%m'k1[C!rel+Vb[MJfG5aDe$K90)3M -D61UhDmhKrF2fJXlZpr1i)PmUqAl&kAC,pN@ekTF24c&ea5@AmfcUZ1$CHYFZGQ, -q2$BGVSj(cNJ+U'0A3ljHakk(j2lr1RB@XVq1#eG9cFc9Fq0j[H(Hi[L[jkBCRhX -hhRY`j3B$bQcRpr4SPVF%S`lblEaqGM1@q8NGfricViIAkpJe(Y3KLX0iBfdG@Zc -a"04a`@4R@hfpUPR(*",YVf1hEZ('GI)cGH``aEdiE5@8YJLSA@U#dqGQq[Ec'1j -Br4b6fHSAa[BhEIF(rlJXU$h('ZkTBdHa0,6[(Le&6I'c(H&B3N!GI%Xa*0rUkbM -qKA(R&FcLjrpJh'LQYHmJiak[`a[!Z0I0@qMXZfGYE[(qIRJqQ2YB9`mbpkNkpM( -hU6Vf-IFpGGc$h&YeY*LlHd1e2i#j0rVa)(-IEqapc,e9aclQhLMM!HEHUQ-hFpG -e6*&hbp`[((PKlVdIM&Zlq1Th('6FBhA`H3)BYeiQGF,VR1C@U1)hlDq-5GHa%aR -ZC8a6GHaM1R[UZ)ITY1Ui&mNEG6b!j+dkGS1HVX-X%@XKa&)mR@Bb2kp)6%b)VZ- -j3b[feV&ZD-Aq1UCP*f`BmR9QXjRZjq&[l2XDiQRI'*1iTilYch*&AFGff-bDTUp -JSVHkba-#qRU)-`4FHMFRhep(#cPhceN`(jG2MYRA[KQ4lh!#BfC&kZ10apm&9@P --KDTqS3VefXZYqZJ&U'0P+3J-)%B$b&JG'Z[TDpYHRGbSKPk!IKLec`Y3Ke2l*Z[ -BVrCY#mXPdlXZVZ2&Qf$YbUDA)(ld@pV5dpkdbI`i2HZ#hr6HQRBfhiXVj`1E2SA -mGkGRREFf2HfGEED1Ch'+a[ZaGmj%CEQSqXbm)V%B)*USBe02cM'YUbIVf0X2Sl* -i!HE9U#aHJ$Vi,*berEZ[TJip(QhrRBqcr)Sl54P80TY,!2$TkRITf)QIT,G(*%m -i(eEf[IXCEFTqEXBQ2m0K[!"eV&P4@pk+rfre&9EUVr!X6Rj9,T4m)4IkpRb%A1M -EmqS2m)SC,R3)2d$J69je[`0REerp%mSeRh#UrqfVU301G@Jq@KD[YU16hcaHNpp -qTZ0AmRJGqMa,(Up,Uj2XY09A(i(,@h[&$RdH%+pB!d!Hm)U0)E8[`#Z@Am&8[b5 -E2-(F24A-e!Z!R(i&T0VlY4EPH%!d(Br,TTc*cd1JaIL"0Z8FqMa,Qh,fDc(e3V` -%'hGfIV*aCqIRhpUidl,rYde0U[$rlf0`rSdp![FbVdBG$c+[mBEFalaDGAJRpL2 -XCele3[`#HaCX(4G1cKP&k0F)@P)`FBmIJ"'B1V`5HarmDCXiec5!VA0p&+Xjr&p -e@446!j[AmHaKdKI[Z'(0YVe1L[&S%fF[hQ8ZHjh8TKZR)[r'e+DEPU8Z1H)d@iI -RDa0R'DGVQcL,11dhhm6T4@$ZIL#ApL4cja2QVLiiFPN#!(2h5fhL2$6h$fXC0R& -ZUG`#9@P-KDTqS3VeLA9@II3#e&(Ha&QZSlCaX+L+'GA3#p!2SrCj!HS)0R&1e,& -Il62Ejpk@DfcL9"HQ[SfihX5TeYe@0HY6epjpifIAT#irR@#L0h(1VL$rUY5eAjq -I@[G$h"GYRa[[apij+frL,0G4fm4CV+1mLI1KIKL9a3X`VdCPm3,8`9IBa2P3Add -Gm5E1KqTiH+@cLI2KD-qE1!r@mA#)C"1Rf3F6IACjM1rRfl`d#216@1*"q*6j2jb -fl2-8qQ!q(+jV1XlUi2rXV"[@r*9ZE65)V*DjJ@2kR406E4Z[5E8YRc[Bjr4h&mf -acJ"2+eUQcc'T-fibjY9h6*fqd)`iJhfD221PR1k0LYb4RV2K(M-q2Kk&p9RGIr@ -bEI(J2iQhmRER9hXk9A-e(Rf6I@MeUPP,+bqTkd!GprI['r8eqlrh[QVGcA[ZRjX -$-cYH4dIb#dHSI5N3HU@Ipq@Efj,TQprCiV6-leM8JH0S6fC45k*+rc0Ecm),&fr -rZ6%RQA)30RAHc0BPf(R6IU`a,f0QhPf9fAVf*i`jrQH%9jejbDkLMXIr#$)[fRE -RfDMJFDeBXb*eTKqdeGaXc*ZrUQVd,IP-,DM03`G5UY0P5Rih$Y1V0@c!5Yhf'X3 -#0&1[af%JcVb&cS58[I3,M6Z2(83XEHp%fESZcVck+TBAC0k0`jSimq6I)GCZ1i! -fG9bFq9+D+6TY*[Y'j-iE[S6BY(TQ1mABZA(QJL-4Qe(26&-,PGjm%P2C0Yefl5@ -0ITji-Q+K2hp6imjVIS$BSRTLkSj'2ppr&f+,lCeX@T6HA2)BBXb1l3!#T[6cQQX -3'l+C+!*bjafh)"D!C2U44Mq[B'a*K"hDY6Bi"p(jj6!JGXJ%kTR@[6`*GAE-,BH -4Cbr)h)4SpmF4dTRErHe65ciGQ)8l3C8i8h&@C!D1Z3qa8fdUfheNEYjq2Q,JJUe -Q9Z21mcq'f12VQFG44jDjH384K58JpXlE'M2`[LX3@fjRMETNEYl)rJ5H[4648Hl -md0X3@f8cIl-a0fqP%RbklGT)ScGhpL"fIMeaN!#EGD5IXlL*k#Pf#N&ZZI-kS'c -EQf`rhpASjq9%SUIDDXL8hR36"cEEL6)Afm`q6RZJqJj4Qj-lAd5m#A6PSHmfq[R -aKBKT-l"Q&hT2ePCLqqTb1,)Gfmr&QqB!Up4*j@U!QFPRDPar&"3TjH9kJp#NMq" -dA9Q[F`(iJ'-AHDC`0FbN60$VJ4"SjJ'UR!1d1r8"K-i3%JPkDlc4H([ZfLB5"CR -RI4(9I,TC6B$iI0h[DL*4F1G'90*,4[*SS9Gmjp!0GR,6Fbj'6$-SQ8*d,CRF'i' -GE9I@-dGjMjhFp0R%0&L*qFiJcj!!+A`('FfEkjR([SFA2cYi!L@ANQHic(!'G#@ -pC$S1Td8ad91SqF2&Vi"jZe26%@5H"hNi4pIZcCU1@'AT[V3j(F'GQfj&qipTBRY -mTpkk&[DQ8!dBda9eZR2DKi!*X#Ich3"eZ(Y0R(N5J%40UfHZ[3bYhaTPCMrj+$, -Re$1r#*jl`XAaRCRr4qD4&YY"Z8amjqI14LE-c(B!C*`IhrRNcb06hfZr(NEXj(D -q%M1NAQicB@kciX`Rh)c-HIA-iiRkYm9eI[$6b03F@qk%ejd5hrR)Eb"cJFh%9Mm -c[[2,$b066k@&kHXZ`H'MmChU8iJYY(FqYh(RYH$MLXKN[Rj1iG,icUGr"TNpp@T -H#6c-a+L5hB)T9+qbdr'HaR6FfSr-J*RfRdGfB+[C#)44PTRfIkr4cp@()M0JTMh -N3BI&QG213@E!6)I1Y"`Lqm#Gb!bBD3qCTFcD@8!Q44CJ[Y2*YGiECmi!qe2(eI[ -jkZXiNlDDflq-@-"QRm4TH'HFH42BRl*XpKLS'M)Gf8I"i4@jQ+RQ0EF$9Ha%GID -FL`5`fRbjecB`UK2)ULclZ`bGl9S9Cji#VUBXqh[5jJC'I36SUZVZ5,8851)`UKH -9+-X,-m3+QF+2JD)TZp@dRbU!aDMXJjJZ4GCS-d0Hf(NbBSV-c(`$4#["U&AX@V! -PiX3[@)cU2!SST+a$IiK)*$0p-QGJV@8al%18k9Mf8@5HCEN+H'%a+[Y"SV(e'R$ -RKJC'h3NqVHSfSlEMhY[!U$QS@4%Ac(FeX&d`U[0dSTHZ6UB$eFNKZ'DrDX"b)K$ -1BP6fDq"8LR@Ell&J*DkI@iNh+%+fdkpVB03MhSI-Ff`eGeQ-kP`$VU-@fcZ[Emc -DQ8"-YF6@q5@,8GRV`"i9')Ep9S1V#dCeRJN'V6M*PK1aGG*L9'F*h%CC&H#%YcH -QihLS0-UU!#qr[i&4XmNl!K9J!@IBBP6f6XbhXLV!GH"%`U1b[`*l9&B&@!1Q)"M -9H43QAGAAKUNCd,S%Sl+hI`i*`@S[44b3!#Rmm%05e@`(8-3%Sfkp(TQ"FT!!CLp -NEVDKYmVZC&c!6JY'c5FV#aD-,!$IGaLe"Ja0fIeqA83%QHNP`&YPpmKNL2mb(DH -#Mb[V2H`&mML-HJZkV+abf881,KMeQ@mL-r#YGAfJ`46H"!9+fDf('pSE21Vc[d" -QS*fQbCEXG(3H6FBBZ+DlS*%i(RAq6j%CU+Spl)$YCrC5GKVfE,k&l+I&U1`Q6+5 -bIUQ&TcCie"Y3Xb)EY0A!j'6@MZ-8"SV[!,XN'28"U+,+1JqA!RNF4Qe$Pj@eKhd -(ka)HGIGhN!!CZ#GlU$l+G,`-+Sd#ca2ddUcABG4dG&QY01Cr!*!$)#!03eFa-5" -3FQpUC@0dF`#3%[IA!*!$i3'3!!*b!iF!N!-4!*!$KJ!"U18!N!-@!!![H`!!!J$ -rN!3$!,#$ZID`JlX)!*!&!r1h!*!&!APUrr$rq!#3"[bX$C!$0MKVT8aTBR*KFRN -ZZ5kj!*!3G0B!N"![#`!!3hN!!#m,rj!%68e38N0A588"!+YZchk`'-Mj!!""!J! -!)e`!!!ZT!!!(jCKeMGB!N!D&K3l!VCPCfU#Adq`k(mr0SZAPZP"1[iZfF[HTVFc -M0$Q98cFG*-pc%hTikXNmfDe[I,AMjaA,h#c+Ml$ERN8jZAhQGA3IXb+FE!Ql1LP -2XXNqNr"1`[B4(YYNRfQAq8Qf%8iii4hKQE&Y%Nliff3&[VUqHZXm0l0EQDeXRad -l`Vrc#+IEc&mNr!$)"ZJ%!Y"[3J!B!(ciL`#cmCqKa'*6XUlr#6l"%iYCXqk`al% -Tr*ilXh,*jI@qMV!FAQDreS3[A#jhSl0eIMA$',(B(r%GCf2`jK8!4b`%U$*9dS2 -$!6j*F3ia!Sb1a5SY$cr$X3c%XZkkJ'-fa+#pPQ1()'CGG4r(LLP'f`-F'dA[6LM -M@!(&qfSAamBJaR)QF'`XaEMQ&a`EKhm6@2!f!X`$)NhQY[M,XB!*!f8JdS1h[mG --(41b'#%!B"%rGD4)TQaASj%p8HE3KBZ2&q2H`RTBYZN6fm-8c%Bf$()3BQ`T+J@ -CYI0QP*EZ*,AKSV1HR$Z2BT8rQZd0KAh"b#+ljfdG@IPMk`qr[U5jqZ4QPlY*-[, -+b1HMC'KK*-M!5TcaIc0U0)j,j'K528Z8L!-$1**DC--9F)@m+"63Sd-ac)+2343 -q#eqbZEYN6C(+T&28S2+L)Q-Dj@95RGS9e06Jcc6**AZ3!*5UkFN'6mSD131a$aM -!b+1-RIkDll+#5X6EmBlVL-2Mkh-IZ@lBGm8[q#kZK3M&G@&PUH,jVqZfAIDpqRX -&!Dk,Db(QF0drDJbVaN9rehDXr)Pefcjkb,$VaVlJZU3@BJlIVAM0GhQ'ePV%ke2 -rj6j@rQ6IjL-['2EGa&fq5fJKjR$ImYIFCc-8MhK#rmjmV2bTGG[UcaPfhrKGlM1 -d%+Ki,qTpahY2L`HmCfJK32&HEPc[L-rrP[PBq60p0lN1(IEHK%([k9S)85VYCCT -IlIcr5MYf@GA8kD+!5MZKK3$&GpPB@(AkSmUlAG3+k,ZZV&F3d%90DL&#m9ddk&[ -UplhE4f89$20GK5$!GdNY4"bq+`8,cB3NAc%k"%h3Vh3Z[46Jq"Kpr!P0-'4EA'T -3pUJTLPDB!L2B*Y2+a(f(#HP#ibS!-m'frG&"&q-ref#3!(J6J8`qB('Q,r4fFK# -QR&2QZk@kUJ99p-ph+C'`HSB5AU**GI,TXY3dU9%kLTAfAm&+&meTDC!!'QZlB,, -84,Hj*40al15NDh&+k-F&%qZJ8fTT3$U&D-FfNpP8R6'Hf&Rk!3)6%4K(ScL83J$ -1jSPQqbhc-"aX#G#)$GX+,0[4U359X-rMZ09,#96@PNKi2bcKlDh04@aVLaRrL6F -!kbG"hZ1##SG4@E&+Rq8Cd+qhN!$dLfZSiqYUmEkD,35@k3M)(NIl3PEfK4#-(Vf -3!!mIBD*MCEdp-'V93c"qkS0GXFIQi2Z9-,V!#N8rH!SHDUp%["p'AGR0bYC2jVc -+HLp1m#lVVHI[-3i8MD5D)K[a'iK2l,C2pm,$V)dldR69R8Cmc+'ShqEIqM(1rAV -mhS*D-*QK+(FeXL"1"9b2S[aZeJ8MEPi1Rb,m&Rb*SIR-8ZbQMEq%"fjGE@K!4V$ -"eXG@`pC(!EBq83Zr(iYCBM+1RI(hI9K!hF#k`66'JH923j28&!f&e($%8D[)AL@ -X15"hA3AVRN"m'0[8A-V12`)p8V13!&eidKc%h@a6'fPRaEm*mAE)[E5(G8X5BRI -L2k6M8apK&jli)1%82hEEQXq`YAqi"2&%JF)fY4b0H!m(4khGM2KXa2XS[Skh68D -mAqG6I)N4r`ELJhH+4r%IdZ1[Z4raj4cRmFqrciLI`(8p@l#B36iKp()hX&%1KdX -0+c8q[k**apJVl181dBS(-"GD(4ie%*)M$Q&,,X3jbK["8U!R`jQ9*dVe[Z!5*Eb -Mc-Jd)VMGcMp(5*pa9@jhr3I96M[qUd)K[aL!KmY92cFG*`p(AUAj!DS352UABVM -Fp6@#!"kY6QSp#3"dE@aUh%R`G4l8Z-U`Gh4j0+d8f,CZX08PadQY'cKQQb[lrDS -DP'S9Il`9`Llq2)GBdqdmXa-2dliZQXh9+MRrccPYfU!lG"jQZfID0#%!M`blCkm -JVr,Bf`&k9GG3LXJV2*5PS5hIA+RlpDTlH19#H1&G5',CPG#SR-REEYB6U2X"E-Z -h#["p2pYbE6ZlF(4&dUq*TZ"EHK3NH!`eb(+4Ke[@2,*rYl#kVL&C%`A`m+586HY -+T5[aX"#22CRS)!q6IDL1XL!2XQcUk$bd[ARDJM*8D3'HTq02Gq6TNjd0qqZB!JT -5-e6*H&920-dMIDMq#221Z!L!KpEPldM(bA0Ale-9H85LJJ!HG-afG-PlZVV*LqQ -D2Ad%)"8j5[p5M$FUmN%H`S#+['&Z(I@BKr4`Z9[6HSJq+[YGUVj4f3raH+@bhmr -M3'@rApF$PAfDall+RSj4fE0c#pY&!*Ap6Mf'+rY"B9q[l0-m$P6f1fQm@GN2m4! -(92CQZkCd[Zplm8G&MVZ(ASVa4N@qL`FG38"&hZS,PTG*5bYR[Pf4CrqcSN+LHc2 -(`BTUL-FVPG"q23j83QNH"c2p6Kj[C[SK(KRfSDaS44kB'2DAlQBl6RLQ-YP!af+ -h3iL(fV%iaD1KBh'D4lEV2f-H#G&G6RePer[RjBaS4E@i8rIa`!cN6p@D)iQ(ApB -dbBNc36J9pEckFFGMVD!X%J,SqN(0NDc&KfVkJcc5Q6AYXf4'M+4XpVH6`dG%hmY -"HEbl+3HrJefV`5lALbICjEUh*p(G&!,`F2Se$6!$BAiCj*'&Y3)AINqIRRFPK3" -km'kL%)"([*ZBiR'`QjKTliS%r&HlG4lREF(Ajl%l%#mkVC6eE!V"*,BKY2RUPDc -[1%Sfa3$j3AbrNQh`hXCkISAaiM`@SiYfkr'bci`ZMLqdakmCf-**mk!CD+"4mIG -pclXi3J#rmLk1%)!((BX3)*r4-3X"r%&ba%Il6DIrGFKrH+A"FiDJ(ej-c2&@K5) -31@3%mBX(%UF)-VNIk%mhRSKi-X+jB[dP4r-J5`q4H(mM[XM)DIEiTf1MFPmcD2! -FEaaaJ*c2FJQ`ZpRGTPX)ZJBE4f0f6E98iQ5a,QZqUl80&G@RkhG21!`F'be8*C2 -Sbd(BAFmZD)hR'`(3D@[6)R)iY4p@J($)aS@dZB1RaHIH8Uj-*X[[Jf@6%%4a9X4 -A$SYTcVFTbkGA&P-YSXmX-Zcqd*m@Rjb-1`c%"mBGU),qY#)Cl(a"N!$Tq69"Hil -*KV'`bf9m`TG6@1*XQ&GG)TA-UfUZ`UYl[V1j4,4L!CZq!54qRP[1ETVLKU-Sfah -'ESH-d!,H%Cm8#Z-3`J5`ec490f2%bjUD'ir!qpHfmc$hmqBqVcUFa8"EN`S*#ed -#4q0e0Q'0,9L[!r#*fEDI!ifTi'JCCQ-[I"aR)[K!3+J+F&r!b&l#ZXcJ3ia[A6P -V)bc$e5Y6HHbeX!Dai`JEQ3Qi$@Ad0B5&li(,%IX4BE11K'mJpKZ1M3)XkXCQ%hE -5lq#(!-ImP,!9Tm,YL0e0@&5&H`!U@JNEf`%2)RBDB611JDF41j[crLl$6639&a' -fH$P$I@HF5YLCKc2d`ic2%AEfPfP,bSb[%2DKm@`@`,(R%MDpL&8MKLj$99D`"BK -Y*'cQVjQ-E3`qaA$FeaRU2@XYB92'-*bNFr!faV((Xe@)RF@0YTN@R-hQ-6jb$Z# -Z+XEhjKqkNYk0j%[UmpeKGE(LL8MSAmfR"Qeah1A62(Pm3LJaGj*$-f41eDZFS!4 -(*1I*q$-MV,%,FhVBT`6NS+ADkiZSBA10'ScN'r15F6*a[&81"hh"6Xh'1kN'MEb -i#Y9,)f&CbhG'YBJDN!"19*DGSBDpQUh+ie&`)-BY4lSd5l-FlP3LYVP4RppV"-a -Hi-3P5NSN'XUK5A4$X`,#j[Ndl!dVJ3l8B%4b6*h(LE2A"kcL5KP`A#L,XmD&`A* -Sk8bF''(2%NYZT-NL#-IpH$b$S%eII)$k"4@r$E[e#Dlr!`!!$3$VX9lc'QeDjQh -fDGmCjE5hD#FrQqQeCJ2#k8$#2(j'f%@1%caI6rTiTQm%Rr6)bXL)(4R`)jb-'6P -1MK01KS`FLa`R$"mCm#182#I(Rl!MM($##6pbP$$b,)m`bI(c#2H58-)*Hm+12#1 --X#2(J!!DZ'D%%NkHPRLf!P$m@FF*NMJ!%`qm!JdkMm9908N)#H([1N)fh54Nmf, --B[Ml"2lqL+qA5*M8emBd1DkQ-NT5N40eRE+8N!!emMSK(hr3mJPj!dM1#`12N!$ -kK6e5['iJRL5K#kICEaIChpA6F$CH6BHFPMA&`R6HF[Yla5`Hp&MGSfTbAEZ5P,2 -EkL)34Y,VYJ!mXip8QBcX&`UEQY36X[i,U"`LBH0mD2JQeCHqUQRP(2f)UK2bQk* -fN3@%e$D3!(EmS`kK(Q'8)%l2rJmKPQ@&aNamq'mUpR[CrVCB@1#8U-PRL4j2GUY -5SPG0biha4a6`9JN@-&aV-UR'jeQm`PNXYPK%KUAd2!QbDBj&b'*4Bl&SkphRN5# -YA!ZE463pjV1Sj9VBLVC(8JQ2aZk+,qLbm9KJJ`BXZY++lV&iKV0BlV$3C@dd8f+ -bTD*&0#HdD1!XPPSXHP9G'6c-H@bSl+kBP&DmhI9La4Ilj+`kUX9,2RfYiSYq06l -LqH+&#SX"*HA[LfFV,0j0+cQ2KA-GcE23PD6(iRmc,($j&&P8DI+3!*c,q+[B4#k -aU)B@VGR$DFrQ&'k1KEh664E"SB-A&9VXPE,qbX&cF1HdS&I+AL8YDI2V$fm[ei* -k0$)LP69elQ&Ad3JSq*X,Kh$!)T9Sl43XD$SJ@(4e#aC29PMd("!XRJVFC5BArMC -'Q['B"Ee5+)YS,U20dpM$@5`#LcC*piA!fmaC9)&&q6$'@bEF&4f6dri&5%LcF&F -d*mG(KDK14Z6kSRbNildU2%U2p&l*2lc@#(Geb)%V#&NS&1f8XX-"$5H"FYh9U@4 -e94`B6V,QqU)VRC!!FhdI(CURdF*Cd&[(M"h%'EL5XeK)@I59c8Aq,hCA9epPBD` -0&1dVRmEN1H(dEL8GR&dXpA5GhJfR#iZ50`-YN!!Q"PSm,9Md5)SI!Z)K9IAF9Bk -'m&E2XCLqX1NqciUYdmDeS$XpF"CpEiQY%j1dE(#qe3JYBL0$C5hU1!Zkdf0U9XR -ekpipqRc!3T1cXMEQLET4l)ZB9JjN#'d@Z#aSQJJaPI53!1r8YrQqS"kP`CYR#Vb -)8,4b&m"!`ZR[5B%5N!"qKS@6V$J88fJk$0+L3f0#j94f2@4K1cfVDqQiP*AM+@q -6ETeMBEYV@CZ#'JJp4b0UKZreE9b,DRUNq`6-YjfcU'R[ceM&$jp'SkI&D"*,A3m -1p4fFaA,D4QQ6Xb1kQZNC+MRHDDBm9*5b-#XY[KK0rhM8r+b'd`Ie)(Zfd&fRVf" -D4(1k*Me@C+H$Dk@f)LNfMRep+A4d)2Vq!*d!dd39b6#`,M28bpLc$*9RZ2R`cYm -Y9$U"`Jb9*jc!QQ5SNdJSLkKZSTPI-2UYMBS*%XNLUTYJ'RrqX-I@&4-N5TD(r!6 -+1(laTSf+#4)N%e8N6R$1GHDKkdL-6&54-)(K,FEe&M)-aT9R(Q$SS'+#HjLjJGr -2B(LEFEf0Dj&ajGHPFHlF1cBU*VM)'#Uri)al8adf+LDi`*Mcq-8'EjpL,Mq&I*@ -KmMc@q2,XpcCA6*!!iM2RmG3IcVR#2(3&,3rcZK5Y%12Bq(i(GA`r@KdcU)m-N3m -hMcNlVhN-R5S69A5``2!JihS3ZCqTUmJ*iEFmFeiH594KSj55+qcL+ED9Tp#'-e& -&Hmii2KPb0XTN#-fUSK[F*KBmN!"JENJJRf+kmMc,Q1KU#"daZ@+#M*NTa$0Tk,, -%4X8%UDH*+P*5E*pa#j91N!"bX[h+8e%ijbmE&41deBTZF0YYaVPIepS+BB,f51' -b+E90M&pqEV94-8(6UFM9E8BC&cipDD0LJYkBL5TkCXC%kSEM[030j'CX+r1F$Aj -EbTbh&!NAmbY2a)aMhfb`86&"%l+SUpZFa%DBB,YK!Zd1Y[0i'`3-9c'ZUj!!3KI -fDbQe"YC'KVS4q9p"ee*H#+ae$(8GfS1QVU*YL,drk+#1$k)99h5$fk,$9Y@F2G5 -X)89QEZ#T-h4Cca4DMcDJb9@d"k(,!DE3!I3CL`Ujr8GJ(@+SKmM@&M-G%4NDX0B -`e$9N@i[*9@4Q*mr@G&LSG%+f@kJL)jY&EE4345BfLlV$iHTPB,1S,eQS)[1D4@f -b&I)cVPR8R4DU5+0Q8AICZm&26Sd6AqQfAc&"ciPG0V`ACC`iFYj"2A)Hl@lE$9i -E2"rHIFICHE[[S)GGh&jZR4(l8@@E8N9,HHCLHh6T'5H1jKf&MZE4Q@,lPAHXN!# -jh(2ZSB[hd*-YAJ"ZVpDiIqN2'a86G1J+f8DTFiIlmbkl41qL'mC3HCF-@0FBkM8 -dB4JUEmiB2ehrcPB)%c3mf(A)H`E)icTY9%c316"448F"ZYaR#Ye(&j!!h9km1`K -GcM#&cU#&a9"jD`YA8"1lKjV3TLpQ0Qll(TG*MYdS1I45f8h*Hkcjm#lLk)UD3D5 -`+ARA![[a+YZ89p(3+H3ST8D2-IAC'cBU*QMa&K,L8N-@ZS5C3Q(56Lqfe1IrCZ% -@+Tf%kf-*c0(+VQf)G@Ia[d#B[m%UApN*ljq1Y5HcdlLdl4q1pFY$$ak`(q%h)8* -r3j[3r`%!!!d0$cBiDk96D@e`E'98Bf`ZZ3#3%!E$!*!3,hX!!&&h!!![#rq3"%e -08&*$9dP&!3#VEXprX!1PB!!!-k-!!!I`!!!+Y3!!!YN"qhUm!*!'L-m0`+hAQEh --NjQYl19'`fq@C02M0&[CZQQhfDClhB`FmeUCPmQTR%US9alKCi5H'Cl6NpfDcr& -Aj@qfbDCF3VH%pHPHb@h@a3CZBj&pNLhKX51FFX)PYpRAJ"&+'1'a66E,cCj`XMh -###HFF,,2kpKQ(D'FENBifICNNld#Ar8eF,000VZYlmPAYXq,59MN0M[#pT-Y18k -HK5FEH$f"!23kH`!'!*CQJ*RiVl9&)S9Thpq26c!L%AhD#qBB9XLrXqH8,R[-kHd -)qN5AafIHUF%h$VF8FLjbI8,*G!Vp5r41U,)Sb+a[PY)RCVSRJYrMS`R'45+PZQ0 -riTJ@XE6$AqDB!6&SVZ,BH-6dDelPf%6+dA58BcRdEQ%*aib8EeXlabBJaM,c16D -*FMcp%XIbm&m$1[c+J"5UK'K-ifAapp#""K0T%3RMecpc$SF'@@5S!,#)468TNZS -f"cT$&l+8d8G+p#2kAFr#,&hcqC0jc+#2)U-k'iBb@8$(X*2%i%L%84#8Vha5E0` -)-#p#2rk%0%cAf30qYbF`c&82KC!!`ISdAI([SH"XU&d"#d%UViY9hU#+3+fTP-4 -YLaa#GIRLF[V2YSXK+A#h+#f6K@VhFVIJR&SRh-`X[BmcbjePpE9#A98l6"1Fp$@ -rB-TFB,IZa1DqccLP'YU%qPUNNiY&Z%T6`3jUJl!+Y$GX`$H6m$q21LM92F!AHAF -imD8[a(iNB)C8Z!-BXmkHaZTbYc,TU`13!2I,PhLra0*QdN0'',pT0daqjR[YNEI -,Q,3HHIeL,BcIfS2jeL*Z!92RGLCYr"E[!G*$TRKRN!$@lk2hP!GbIdfUT#0H4R` -LchqP"ika*Uk'jXNASrQaIf$rf[Zk$r1d4r1(Ud#6!VQ[l8!@a#R-pFMpeAE@$KR -eqf!0i6rZBP+Xh8DHqml,V1JR[+YL[Yh8-CRjf#[-XVq4@CiVCM0cd#P0H6LUP`$ -Ta@@X(eLkY8hdLj,ABch8LNqeERQCJ0q6ihVfZdbX[ci&rq0[!"kG#PQr8kRS-K' --0BS01DlI*KIT&p03`4pjLrAhk0N5B+R@$VI(fV#DP@`1`VKa5q*pS+3R$$PV"Z$ -'SMGi(bMCh!AMM(S`rHL2-0$3L(J[j'cYCL@26Z1m5RTiI8@a'[iHmi"T,$R(G-4 -h%jr6I8$*2pJ(5MBI8I,h'(NI-)eCLbb)Nj(VBFVZTMl`dp9`2q%(mH@*2J"($f( -Ai2QS%!c3rrCDr#q'rYm#[$QT&bhTNZMl,C!!$VYC0fJQ@1eZ6ke6F(B'J`%TC+d -5hDfL*&YKc$GQXqjmiX0BRm[#(VJ*Dk4b#9YhDaRL$YEA40T4hp%JhJaM0SCCYb! -JpL,q"a@mk#ffEY(MK&2qb22hV@F2rQB$iR&RaIVULa%2Fc$R`Ef)cd9m#q9Am+C -TL2FUI#CZL1EI6Ac`Qr*4rJ%Prhe(%&r0FClrJ9HMqH1iSQFpF$l"jP+UJ8P$09$ -MEC(FNPH8V@SU0C!!0e3$L-CDJ9T+$D![e&XpJBkJ1f49Er'&hF"bV&Cl3")V[6j -4&MjPRQfH&EF%+LPp!%H"ci,1U$6$1D@h#$9Hrc+4bZTNT%Bc1"bf[f9)4Pkj`e( -cXH[&F5Z8"i-qG3!HGR[0r'5H,,4'`U)1FJJNrCNFGNG0T8S!M`EE!R8!AHZFG@F -*AZ(KUQKdDFdYl4jCYJ$lI6FBUJFRS[SR1'DBlrEj!J'r8#AkBQ0"p[!Q$M(RchK -A)aiDXfH%Vm(H)0KQfUC22eFG#Sm8XfIkG&8!(PUcCd53!!piM%a$2p!e1%cN-Jp -a4I$!GlZ8HRhb&HlH#-mpM#4@EZ@*D'kXAdK6-'!(GKMaI5mlX,1CV4XhHl"HP4@ -!$r8`aRNNKX9MN!#(`belh,lc`LUk"Yfb@J!2cl#b59h*YK%2(I'id)P'H@M-#4q -P3ajeiUU4(!S2HD42ke#'FVQ$pqRBdcrhk8CEl88IBk3NP3NRdaV`G#Cj*)2mKb4 -,#G0`LBIFlQY*jXPb9,bV+[))GDS%m+")-@19I+5VJfSakGQ6S3,Lb&(k-cQZ1[* -c2&3$((RYr'VD08MSBAFd*293qh$flkKkeGNRH&afpKGjA(,f&h@pj1b62#ilHrD -Ph'Be!'Gr9Spr1rYc`PjapNNHPjcp@4VAR(f#4p,CDj1f2UkV,,CGVh[e$dH1kl0 -RFPaej1r`S&!*F130A[qX%Q&&kCcr1I,dIcNU*$V518BG9B,(C5Gd8Bp,6LM*Bl6 -6Rq9aVG-RH'M0LDkS4alB'#jDpa5ccc[FcNj-,-jA#2%)Y#`GjP(EXM6*)phqiCT -(A(5l6GNk[al[G83pUX8Vp9dHf)&m`ejc,2(`Z@9CX1&H&'i%$DNIUhMd#Z+GUJ# -kIZ`j"Vei`Y12mNKfeQ5G$AE%d(#C[4qCI&hkSak8aDHEE[m2F'TeEXVeeaLFF[d -m(*pZUJ,`X2PN'E!$BAmjab-0[3)ArX+FRNmP93(di00%93!HX@RL-)r4D@+UZ6h -8iA[+SI#ip`#q[THpJ,MT,JX,p`@KL'dV+(fULfhj($@ELAKE`ir[ZpLfr$dXr"V -QLr&BLP9dASrhkL`kaI%',p3V6A'521JH!0$CK1YeckFiUJ$ebUFiUJ!m+(5U!2f --)N89S$j)MYMY$-hbIpcEb+acVa5U!qeq1H$rMm0!KS`q0-ckAiHL)K*8#1S[04! -2%k6bHU"rqZ+0L$FMh+e@AR)d#p)31Ci$RS8dp1,+R5!"$`8*K6KL[[N+IFUVl29 -NlQJmIFrP@Xc$L0Gj'1V`B-mA#(XD"dF6q&D,pXMTT+9iE8'40G[Hd)55+#[9jcF -FMSF"Y,`SP-)!GPMClalU0bT!dG3NKr$SP,U$"&6'ZA6&KPIlUEI8+`HEj4l3pDQ -#+-j-r'U@1NhXSLkI[,T&AN6a0JbG$Ih6!Ca'Z[@JHP#iaeh3f5YIG#0,`lrH$id -"Fq'8+rT6IBRF!P[YJSS#S@""ZDXF2af,E+i#YC85-2#T36a1h4GNU`H#-mKP6fC -pS!NZjK2a[+#%5`Mjm%QRUqiQc,MT"*f8AMl8jfjM@6IF5%9'Q2dJ&12RA-)qZ`9 -p1J$IP(@*31XTZ&+'bf4@`,YMM*mZ$1d([0E#EL0Xc'1!aq3BAbeCkS6PL$e#@1S -m`'l)MK&feal!LbPDRX2iGIJDBQX)#ab&Eb1fKE#UJl!GTa2l#2-e`$0iTBPICCP -q#2BLaR1BASG$!!9dD4#Nfq&Pa2JQ@r8Gm#CLI%YibJ$m!6%AB@0h-G5kN!$I+Ta -Db[!UBL(A,(mZ`bXYK9b26rq3!1(L3K(I5PPi$rX-BRb-fANr`cG&I!4B8mHFU!4 -ILTQhLpd18%b,AC!!pJ4V!jL44CLY&QrK`3cPp0CHZX`hNqHiSBX`pJCKf3iTX&6 -dK!5X9GNEm"YLZ0dVHl,i0P"mab56pX9XJ9CaSHM2'0`GimqLDE1M'j!!XC3a[-% -YqEhq0PPAdHS0"D58bS!rC1"cdQMLV"M[LK8Kb5eRfcVP8+"$Z%9FHAG!DT80j4k -2L1XZ$RHSAGDjh&+E'$,-lr6k@U-*daIEm%55'1S-CY+HH93P)f%,[$*1IX@1&Y3 -MBh!*RHH*X9I@Tf+U4H'iD,C+1bE,T*-b-@+%R53fH'mQM5"FjZ2jSJ30bPN$e-m -[qJ`iLipcr6m!#J!plGD6HZb-8-+HV13CH6alFSbXl!R&Xb1-8%)**60kC'9+EL9 -XPATNY50--Q2V5I'%VE,$8ra&9LpfK"%DBB3H18CSj"JC8h+-c0L6!C-F*EFQqC@ -`)d0fC-D1(#1h4ZD-M#Jj4LKj4SiG'6"bM"`ME!9Zd"&+D**RbXM+E'@2ChEN'8% -1!b$i!`lV5J$0YNf%%!II)`L&EX2h2Xbbm1f$lcdNS,1)4h%aVjQ5@YC0m`-`f1( -C[q$I3$a2H3Fa,f&2kp)*+DFlGUfUk3jBpVAJaq05"m+,+KHPY&'U&UZ'lV6'lR! -29Pq-,5C[[@*RdrN[MfZ@%6VpNM(rm*Ef!qqjad-Ifp5Cmr,qG)1,FK`rq$DfN4i -lcF*!bR*02fJCh$qIjF9R6mQ@d510`Fid#q'*DlVPIX&pT4jPe,4pAG&RrP'28@T -r`VEFUQefEEHSabNeT1K@E5FJ5J@5%%B4P#40iM[`C#+kQTRA(9I@ZJlXp,2rMN@ -8@@4+9hk+L)'&8Y4fipMEXaLJ&Z195XSbHL+i3BQ&m"SFr0DM&K&Sb+'4dDZbDC4 -ql)A(T9PX@4bJ@AM0)eHl&RXfXr!EQqU)S*!!8AmR3Gm*faENhMieP5P-b51M&f5 -SfZm@(VGMFAKm8NdPLr&KimcSp-R%MNkSCa&6LQiCX%#AI*PYMh$(JU-@JiUDPR) -ebc9QG,bUhf+0H&cFQV[l9&prr*kE9l,T**l!%T)e$"UK)FcHT93m33*e$EDZVKS -*jJS6k#655N'(0IKKMC[26dcPm36DJe#$YPPTT9Dj18c&%fK43JeDGf9TITP4BB* -#00HJ"qUUZ-$0d9c&"45Qe'$[kqY2+S`+%hJY%'V`ZPKjG1S35`JQm&+K@rlVCG2 -Jcke4+TkJ#%dSk*6kQiFePK#Hc-E@S01Jqi9`0ZfiT'4Z[VX%K6i*ph,CT1PX2"A -1ijqXUPpZYre,m+lRirJ1EZrr!!d!#8*eD@aN)&4ME'98Bf`ZZ3#3%#8F!*!33hN -!!)3!N!-[#rq3"%&38%aKF'ad)3#[M5YCVkGYX!!!BLm!N!Bb'3#3"0ZT!*!)9Z` -1`)qRR'Ei#i"qD&MCjqARf6IbXh0NqINHGj!!Smj@jRGHCckRJ`C0[0lY`!BfY*R -A'h,-CQPR#,#hJBeYCZm"(""!VPpfCCqRQh8,Ej!!4@BJHC!!c##CE!,a"-#"66` -m%424JFZ)*Z2PKA2QAIc4R"j,DH"JH$Yl42f1T%L2!iN(NpGMrL&8Zhp98A&qG(4 -HX5"[EUbmFY53!0'Yi8TqIikTqDj[0,LEmdcT#S`(`K((fGKLYlKYM--X$mjR'ML -D-RXG1Sqb1VJmdIQ`1b02[b1SrU1YU8FL*qcYVArH3er1kE'FKbIL$Xe[0QGqc0A -8BNaLZY#@S@RIRdYP[cQKPEBPb1#$Z3[HlDdr@NST5bCEDfQ(*@e(9!dBA4SYVbU -*9KB@983VmXU,bLUMXE+biU+m@'94D8RRk0c5UZM-USV+k05LFPK&*4@9XH,LD$r -N+"J9jXXLNPNMUdSU!++mY'TDB63@V5JS,bUSL*C1MHBAaBT,Tb'f0&T3NKqY+S[ -1,UUd+DD%l9P@(#Z*6LdYYhfD&Bf1,L`SL4E-+FLVUN6kbX+#-%'@8L1bqQG&ak- -@HE'5NY,+RfSfYEadCTM2e55DR9p8#95E5JPd0RpB5jZpD&25388Pq3APJ!RmdG) -bQkiL'LX[k+@Lbk*M#f198E4*1%pk48F9&K3A9h51$LZD8Kjc95k2pLqY,,5jqTA -R&4C9&Z499L&j0,GdGN&jlS$1dGekc+M*-US3f2*Ya+K+e#D[1KEIL0,+JQLAk1b -#D(jTe*BkVkUm[+#NXRKZ['8'$"Uq@ippE'P4KBV5**S5C!MVE6ZR0!(HiKf%!J, -LL0+5,R$9S"b3!-$@fI8"%XdU++p!r@h[SLHMD,&B!NZd`N'0T`M4frN`Zl4NKmV -SY),+X#9$I$@IDkKS98Pa389&Q$#[X,5d!VdD`SNhCU`BD!TMX`TXm9bPE8PXU8Y -3Z+NS6B9Y24Z1cV")-AQSBEJ@%+@66jQ`)mR4CmFq8@1m(H)4GMC'kC)q[BQ[@!I -IahKja(jQI9G[&RAeZ[9HHXePJpUhkM,B4R6VIIQ&eK[0-ZY[@$iYfY@,pXiV+kR -XpkRCd'E`dQ[D(0ZqeG#q8p1'AQXf6*0CR1Qecc*IM6KJ40@)rBLk4XB[kYTl4-l -S)8!lrr*@(5C()e26bV`qG-@M"hES'VRLe1MSD0T6Pe2MeRfTFGcA(,lQBaCeV4q -G[15![HD2cZP3BMC8)aTaTaNpP+CeXXKLCF@9AAYAj*99PV@q[*0&0kdZiL*GHpZ -DPY(PRDliDP`1-PBQ-##ZZFeUi`H0c"i8GX6m)30'Y!dpCpSikkM9,cGh@"J#Yif -3!2P%+GJmjN5*&Q355aU*T&"+LP"D'P0QICSIE80pqrDMk,Vjmc12SljT4e-dC3& -&T5pPFT3b*C-b8p)S-bf&STP#ID0-mr[+%63rj8LQY)(!-6L&dXDP88Tq*RNVJ*2 -YTJ2F&Vm(ZpCbSRPVX-kX)cEVb6-EU*E4P)(PTT8amrXBXhbH-@Z`l+c$Zal["V` -D-3Da'MNf)0Ik@SMhN!#(N3rfI2L"`H,BJ(FpeAT[(AN2!#F$Vm8I(b,i-RlFYYE -C!9,pC@a1N!#"1Y'Q"1Y@[P'$))-L+fX5V+196m#C5'$$N5qC)"kH5"#'Kr%ZJ3h -Iq&Sb34MqQJ0J%aL$m0A,N`MdkJd)Md35#6DZA)A`jFN%'eCQ2)&`LQad#6*Sq8U -%NdXB@8AV)[L)(%,8%3PXH"L2F+5diF[$H&YQQ`$K6fb)KiG93IM+H(KB-S5[6)6 -6aR8fI(Nbr,80@m*AVkS*Ya@X#EF9I'0$G6KP,&qe,Q0P-YbfK%hbB`0AKbHk,[R -ejIRTIHY%@fIf6eZEX[M)Nr[eE4eYNcQ`mE(Y-YY(@r5Pq6`rBhQV0Ah@c9Z2ZD1 -0Q@Ikk&BE@Uh[Xkl2QKE,`d&Lh`b(bD#RV$H5%B*FYhb9lFZ-5#5F#@EGUR"BE(a -MBcJN0QDXYUA,X'f'(JhlliPeb*@"&N4US(TLJdfpF9ASTJfV3MH'8,+Qm9UDq(* -XPrIi9Uc8Ie,Ch"p$#p5YRZKB,P)TYGjam2MMeT!!KlA$[N6eZB3fb#hH&D'pfV[ -#TGZ[cD"B4IkBIU1LhE1kGl0[1U*5l!l#319KU5"5m2'-1%"X5#Q)h)j5&3bC(JE -9`Ej4+i$4Z"[jPE&bV-h&44@9#Gm`q"69)YiRc*C*DDRB@cfcN@U6(m$dZe&UFG% -8R"3XfYV%-m05#J84#UJH+@c-bpaaBQl@(EEFU9L0lFB8)4A!c(3!bXVb3MXA0`+ -%KM!me#XpJPdD-"$r"aJ+-(l!h-N-B0E[4QN9KA%Jm#"A##A$38(4U8k%kP"p5VG -3-#9'f4`*,&Mdc2GSahS"c'Jh5XGG#DH3!($&Yl@0qm0V#r`+U8*FYG!0p50!eB! -bE+9(&Fh%*FV1S$L`HJ$f(D)E"M"r"'C,93-X,&J$"`cY4BdLe-J#X`Al#9K$!&Z -2Hd+6!'B),$aIE!)@qUZ"0AE!!R4A8cbf%bS+riLV#A"p5mh-0`&-fe8iGB5J3Nm -)4e%cKd@K0jY(U$RDa`ml#X&a(1BEZkfQiQe",48-+ADccRaY[Q,c0BD%qFUQD)Q -h&889M(!NeD8'jNYU(F#`9FdV,-LE89CDK+Z3!"e,cTpVr@idY5BH'QDYEli3mi9 -&&-AEKYSU'#'LKY6BI%lE"c#DGk-)'UkmXUbmG$VZBR&[V[-U(#A$ZMDN4RBcahB -[e"CSfP&l"81+%0X%jGk"1LJBhT!!H%Nr-jqD6hcc'6A1LKA-ULc&YP"5KBi*ekb -6U4-q0TqL0ZB6fc3G%M-jPcS+G35)6V5MJL(PBCL2)fdA"3-pXeei+-Sb(b[+5J" -1-ap49r1K$l0a9XAFLY,LdPLq"CPB*@,S&89G5HbK&B2II%$GI"JTrY5LiJ*&h9b -CX593p`Ke4rG%HVRlp*M+SZ)+#e,-KlC&FC05e)@i0,kb[4qBpkPf0pUZ+Nb%6$[ -LhFQmTfJRNTa`[Z65cV5,JK&@1B0bD&HKAC&Q0pTG`8LC%)CeT4l8dlaVeLSiC%r -8)J-cUKIYS@")-@iY'@M%hZBG4Ee*5X+F$@P2fN["i1jf-k+'jQhI[)fk&KH86&1 -dPbY8"SE"@i&jkem$K-dlYX*l92IpQjjjdiEdG0hB$!AZ3hd9$(5IpEFcDkLIH51 -!fDBEC4a899!q&iYRI0Z,"``U,Fpa!8,p82VqjR9&r9ejQP0VmeTJAYZfFSPjhEB -J0Qp&IDZlEh9J9[qVU',HYEfleVERlRJ(d%!&)kaR0c460Je5--*kGU0HjPADfl` -5`,6M-9bRA58UiYl4cLZd0m!-0LmV%!E#QR5RhFa,JARThc9jf9Ed&9[43G89I6% -`,e,$EP3Efh0j!Hl8*D&VC1J5'JM!3m`,LSDiUE%RKXP3fXFmEjj6F-KHQ"*lSN1 -'dA!&)i5&#@'H$Fbc@f%T'ZlDI5rUBjlac$1f*[ZipKJ!a`M+86$#[@)!CCZRa6a -Y8q48PqfT`$celk)rEa[a19[j&bb%A4`%l'"Q9@"@ECkNjMhEVqhajTSR&DCSFQ0 -k`UaNmi4&JL19Q#IYH4Q4'9KDb6H2dlidNNDChp0S'Q-H-iqD4aK"f-RfaDE`X(R -)2'JH-#[-r@DjZ5m`$fmE1i&jk&p9$Fb$[be5[RPJfbS8Q"8eK3r-r9YEP3dZRfc -ZXi[T5#bQpk*epJYJeT`G8QNrK0k$TKJE`2cM35'9aL,"hGMqa`8`rh)U5+9a5() -APSVa!FarhJ"5D6`5hSN9I8)!mjqlI5T03-)lX(T2$'$qFfG2TBP)H$Xe0lF&-2q -bM+HDfq`m'%@5BQieYhMQ9YXaYq"kJSR!k4J+Y6,0cG6"h'4ZT%Qd[lR"KrZA4I8 -Q1f4ZY!0NNMAfaa5jRVUEkmbejKTcYER+A1NM`1f5[VPZf`iDQ'YV1Ydhem4AYF" -FrHrP+6"ArED8"1E+VG1MMVQ"pZfdjXfZdb-NfFrQ2&#AqNqa&l&h1Nr(4D*"*qZ -N'6[5GYPj0JcpA*J6"M'#8V0Ic(PN1VFJ0Ae@GIbBM(3DBmpX9p!"'-+6'3i-pJ1 -Ucf`(#Kf)b"K086$#Qi%pCH94[S)4,PefU&p1"HDb!'E,EU5Ub[*MP3@*@DV'K1l -i-"8U!*bTjP*&8kXhN!"PJ9N@6S6#dTN&CE(+3ZI*K8I-TED$,l0eb8r8TC!!TJP -0!j!!3LT5-1+R"SqQ%kjCdpe#C#I(*CkjK&M4M'UX&`IQiV$*A)I0LK8RA2[&3'F -V!UTLQUPJK"H!&"5XK%S9$'rIm(b46f9d%*8VQ')C(`%1,4@%HdZ&+ir#PD9+U!T -!CY&X"51mG#LXiaI4(,28KaQI@2QPHG86+c0qkCMM,Kf+kTNP00H(NH+lb,RZKT+ -"%mI"jN*&"j2NK4H#ZR3)(DTJa#m'QHD#`&c`eij5G+KVN!"-h%[2pmhj`*GA13I -A!a$Ka#beLpYX[)I4i3T'@,c'e-+FCmiejrMQ2"4[q2$FNF0M-`UbbmZ(ii52Srp -mXS9NFkk&F)k&F$MHHHCX4I-FK*E8eL`fCjNcIE-i$Q&!F8@ZUlrP$53JR'8KJ$) -MjQcE"CA*5jmjSjBj!`h*Ndp@k%"[C,bM6kIjjM3I*VS+Kqq#m[*SpHafHi"#Kb8 -R`+Q"169FV*!!D@E&Y0!HAM&0c'N@ElRViXlSmb1%MN$PMU5M&)b`LTeTQ$Q&&Y$ -[I*KZ9mM(*6p@-F10)(`1l`+5+5'-2HKS1NE"L2YldV&dR))4pqp1#qPi"52Zhj9 -1S"-9M,KrCcU*&LNBFAphP238"52ZldURdQN+4YJQZ,A4k4%kh9jDlGRHm3R!1!# -0#&ZfSY0F(h6"&HlN`*bmG8DFi["da8hPM!LGB8qXED,PXD)+F03X13!p8eVHbei -R!@T4iS+bNeRNQd8B+*LSZ)+Hk1*`36-R"HDN2c@GSZ0GMPeaI6R40bFQFarRiRD -R(ZB%hjb3!)`laJl"fQLMAR5Q3H1Fk3TPr@G&k#`-ijDM#NZV828Ki-)P9[q`CQ% -cp,%PBh1mAE9rKleb)5fQXhfB+Ik8bK*-fFAZ@0)EFqdFSA13!1jF1Nr"#((faNR -Qr!LGMa*ii`[FGC(1`hZ"39GIi*,JDN-A4ZK#E!XbSM6-BF#&5+@c!IKB@Q+1m@' -Qq2P6Ll%h,(&*"q#8Y$4#5cFK5cA(@(K(iEh)(+hS)RFi'SlCG$&GBRj(ba3FiEP -a1$Eq5qNb"5-m0`l(VRbj@D$SFRGZY2iVk%S&)c`hjY*SFj4[MV*P"ke5dC@*[,P -dP6P5d98Z$rcQ#0mFBIZ[SKK,`T'fHaEBVVr-e@dd$K*A4qMU6A96G)REb5CLPlb -'VP8``P`6DC+Clf(8)m@ee40jAQ$Qr@dR3jf4ETP$&%2YVk2V&B`3%6C6FlKR$MG -'dIA9L!i,c'(E%"eY%C8k"#PBU@l)S"ZNC9TL'5&q`fjNra(J'c"f5$Ci+H&U&`* -EE[[$mJZkMTi4lC%9*d&[qUiE'JcU2p#HbP1[Ec#J0,pJE+bm[!LXR5%$Xm'1f6h -,RF(rcjIkqE8I"DQ@GQJV%@FXerXa5F2K"CAPPSBkSb+k#6'Z"'"eTPk2&pX*pDm -Z@UrUK*YF0EPlrD9bY6'1,Sp0,A2lZBHpXLF16eAB,bk)j"E'`&[G+6UKY+6Jck9 --(eSdFiF+ajFG(V1,ljE[PkEbN6XkT'4DBF`KrhIVN!#I0@T!eb%j`l2hlQIl4QJ -QhKX00ZdEL5f2FbTZ$cFTZXR0RDNdc4`5Q%1fcCe$,BSTH'qQ@a5-j&AdB$1AcF& -fY-ke+@l"Hb[GTQ#%0jF8F(0ZTcX8M160CBkCE@B&CNji8l,ASj!!ij9I9"jk(H0 -VB&'jQ0PfrCKP*alB,2DQB8pXGp*G#NBi8e-3HMIGBih``*!!JQhlAP1Pk&kh%eM -rI3Bl`ReZPl$qjA5rJK'Rp`5Q`MF9i5'K"*H4qa0jDp-+!rq+"+lDp)!j50%$ETQ -'hj64JkE8KpNiUb"@AM&eDRjjpI)HT4MmLKkdc491DM(S0$B(@31PBi-,$"X3F"A -G8chp5`*6XR@c[5Yj(U+(-ZJKI[dr%ScpiId'M0SmpZIE2UmeT+*`CUc!BIh$f+p -Bm36'[XfeIkTMh[eIr(,q0Dfqk$YSa-#4YK,aX9rRab4Ue0b+bS+Cd8'Pa5&D4S- -"25V92&kSATXcp)UAj6mE$2&I@Z6r(q*ZE0q'pf&k4-&)$YbC"UFQi'!$V%+2i(f -8(P-``S'EKK(hHhTF`8J1h"QddN`2B2kG@E)5B*i`Z%`q86f5#J06q#Y("UM&J1' -Pk2(U-qH63Nm#c#Tk5X%!ppap6`XpM@c6c06!62Z0[L!'Se2S+Ec2d,-+4[aD@TZ -HSqF9M$JaUaDpB%#RHX%G&Dhr4AT*`BJh`(BQhq5C+B(*rmI'!3"LF*j5p&+5X@K -L[SNP6idB$SUHVfk2!`0ci-mAB(S@YAZCAP%``YVjb2dUVEC'#-$(rM%CccmBFDZ -V!4m3Q!0#`$J-jC9@P95'RJ(@)r3+!,p')$QpjJ#Rim$q"Ue4--)&+"h-U6IT,3A -$fjdC&pGQCRpkQplaBD,%T91Q+lK$X29!!C`8Q%Rr+-ilVK%EiY5feNa8Y0BY8GE -rVTQJk&f(hIVISrF9M2"!djLDQ['q'CrNMEh[F&ZL)"JLilB0(6Di*V'CD([a,CF -e(G4Q%%r'rXUJA92G4Z#[l%G0Ze&33l'"XjSe4+qMQ6kJ$a8-EaabYX60jL-cKN! -#r-K0ZLa`-ci4qJ5*2UA2&)b`kl*!T9Y(RbXBi3M+`SP`0(eK4J8`rdNdq!*`[M3 -M&AhT6U9G3HVlLVj@--,biE4TpJh-[PXAaDpGRQkJLq3'*MI"c(#G%,VFa"H$5l3 -B,(b+2UpZMCc!j'aMJhf'mRaM4LMkaKheHU)*[UAep"epVq!)MhSpF@lmJ6BS'1% -XX%I1M3EXX)d1*[aQ@'#'ED-Fi6k[D)1E`U!MQRdm!rDc!Y#`pIU!1UH&0)TK''( -'Y9iIkXr-SM$E3U!J$CUKJ4RkeiQT3#e0eRe)B)EmI5G",B8p-eLajbiTS+CaLQ) -FppdTG+$Cfc0lflD#A)qJ+B5hie6&S(VEaKK-qh!Y6P---VI&24M%ZN'"'I3hQKb -R1@K$D+M*pJa1BF)Jp(*Y-e!aQ0kf'8E3D2D&IB3&(&%FZ'BB3IZbiR3&(NN)!C3 -k-m!c!d!X!58T@IIqJHRrMlU$Zm-CTTpL8,PYh8F#FUCL5(pBC*EjeYFcI9%Fdmm -@(`F"4Gql-SbP59b(kbUZ3i+4$Im%VXIe&GGc04K,idbI`26CfU2e(FKa00lXj4R -35a@$q*dShjk"fI2RKFL-X-bf-9XRS),F5`LN0E8a[326qlH9i%0d330ZU,L"+qd -8+Z"'h&Ka)eHL+C4Rp[!-L+b+`I41P+KAB(VpSm-D!PX6de0aNq50MTXUEZU3!0N -EA3r2p!!Cf[5dNq8aT'['c48hUli0l'jfBl1lABefXh1U1Gi@h&+"24AH"L+8`Dd -iUVK9p@eJ9fjYGJR-V[r,SZA@J06'l+bi6A9eG`V-6Z(D"3fSa'("qK*R"E1cR3L -irLVS[VJ,JGc,EB9"kZEYZChLlDY,f0edBi2eN!!0MU(#S(YcHpj"-4LCa8k,aR6 -P$Q`J[KAK$U#V0iRfUjJ4M8dTVDU-cVED$JQP)0#A,B)Gm(EN6SSl*SMEbQ6aMYc -C0eQr%'%BP'V,ed!TZ)[TSKMmkrMjME-LR!A'H0Y35b,H`"9@J#J82STCeNDm#(( -54KGFCENc1"5GZ5Z$"0ij3GTJd-1,F3F3UXAGcBi+Qh&)iV$qRB6"jZDGH4I&S(( -(ZH+mDi4h45ZR1XdT9q4Gm1l'Zb[H,DRC`$dLh!-,IZfN*T9,"5Sbpc5SEmmNLi" -l4EJALT!!B[@Q`L`'Gd`f1pUUG8291[)HTS0[1LDB(aaRDUG4EHiGiGieZ9-0P*@ -%3D2R2AN[aAXQ,K(eZ!rh9Bb1X"YK1YAKIJD0$9kfZdc8iIim3$(SfIBkN!!"MPG -lhl42d$`B@iZ0XhYq1pqd5p)kGV"cC4-l'`S$fiG6h!k$bY+`#jecG'R)VKIH#l8 -Cb0Q+3@bfFkFqQ1TY64Xf8$eLdmD@,a[[)0jEm5!hGfb+eMbB$B6K)P"fDdh00Xd -Gbp'*E9,jFTd'RMB2iD'+KlM*8aq-mbM[`m0m%reemS!&E5F2j#aiZ'QP1%k8Y[i -4%4k"Hd+(F2*JNFL$HKD)#RmH29D(*6jq@YP'(SC'EXNjR1ZEPXRaNq2'6d0Ua[Z -D&SVhGH2(qNF+Md3&4r&SaD15c(`H%q%af1eUaH@rA+P(ipf2abVHcb9U4)ejA)6 -(@@U0*Hf'5FEL(@q`XBah5D#D`4-L2'(,j'PZ#pE#&L`A"@['%de6hc4,6Tk*,RG -cDX'6)MaTbq4TDQ'#N!$1qr-"bKk%E@1eS4ei-KqSH,+E2'fS(FG-%m@JKGV*Bre -61%ma++Gf`V5&YN"Mhc416Kk`6QdFa#a-)pmd5NkH*REb31F[-ANJ,Y+3!0+k8BS -G"EB5S+Cb2KFScRGcTJ2i[`e-I6B0E)hVfa3B&6b9TbQHkZD-69'2#pQ!kK,K`Kr -RM'-b@pNf4e&fI38q+4IaG-9&lL$6JBlM'9aXk[*-KA9,F)e!6%mZi9)&pCV`$Y' -"ZR!C(k4`Q3hVei%kQMU"UE1TISS2FVh@N6TcHB6,IqakKF3KPQkd+eF`'J8mdX6 -G#@S`8+RCK#A1KZa1Zh"9K+YUqPCaX5YFEcU#Cr&XNm&c&-pbi(T62jl,"bZHkm# -"aQE5!j2qkiKAI(##cpDA$iR`)6rY3BTRZe9d)-Ai81&$d81(mH'+ilc4J664+*l -(mhh3XhkCeI2FV"j)Hr-4"UFAm#i6rL00S2K)9`MV2bV#4d&iSp[!2`rVDY'rZ(4 -IXPca'4jB!aTDUD"NH-ER"3`U*lSS2XK"fl5$I$#0iU00EF9(Zd&ZrFF)Jh[)ar* -aLSpejE"RU)84AKMZN5&b0dU1`hXmRk!Bj%DE"c)-I'+%6h6lC[A)!FQ66c)iBjf -8Z#cYbiXL['M,+!F*L`dfk&5fI-9DI,**p8fYj#Jr18R$ie-LI-U@8CjUBB++bkH -Dl45IkNEj*$6VDAbkiY2F+*m%j[FC"ZHh-p`SYricq5c&i&EDNEdr66DHEl!0adI -j@5l1%[$&0b$ba%Fjq#1+6kmHj4cJU'K[5[QPm8N,MfX!-H!FL)%iPq)jESD!F-Z -,K4HM@QIc1BT"PV3c**m1J3V8ZAbH$c,(,c2NA$FcmQNDRkmaGXk[pPqJYH)i1G2 -k,ic`K6KUp[crCNLdI9bLdJd6VDf"UU6bHH6TMEb%PrTkBh+B,(($T*!!+[JL[8( -a4@kB@2r&`L"ZmL@m6$%BkVBZK65$,ih`TAmB*L!qmQ9mZH)ihh)'PI!9%ElL$m- -%4%qq8[qJq%UATi31iUXLI0AQBD*rX#@$A&`U,dA*[ZHVpAHqrMij6+jfZ5YT0Pm -6i@Xf$a2pRB8*3LaIUpFV[YB0Nd24YGIapBU[Fm2N8*V(0qK[&GrJKSRehmJh+3C -RcJk0`fLHrXEAZ(V(K`RBFcEZ8$T-IqhVVa2$4(pV4d-eT90r&HL[IKiQHVdG*R9 -Y4R$dE&N@B(ZlQ@p4I,1Vk!)kKQq0m+eEZN[a,G8![`cdPcm$j1NSqfemZf+3!)R -X%VU3!"EU,r6RV+(5a2TcfaQhilf$le3-QTeG3Qf+GA`ADdM%4ILZ(ipX@i4$A3Z -$MmGhmcf+lhDEh%*kMqrPqr4R[&`ab(K@@()KhFIhm`V&)0NjrfAm!$qSq!%hE4E -5)Rj)IkVi)FFRXIk(p5H+3AkbQk$e2m+2+Rl%94lXFreaS$rH['BqkTVQH$U*(i[ -`Bc9MJ$9NReK$!%VaJ`lbUA3arejrT2Mh$V,e2kir92bifjUYIb8rS4M%+&Z#8qN -XIT*A+Al5P3!%G[e"S$riE4N&!FS@j63kNjq+m&0EMRH+Rh$JcU%,q@Pq4[(6$Y` -jG+jq2p$[r`EZ'3IZA,U!Rih`XeXUEY@Mp%F@C*c*H#AGaFrTpa5$2@8VE2h2m`Z -+RhG&Z*+ZiaIj*F8[ZL*F59ITG`2plPr(Lq)i6qSUZTCIM[$,@fDlBT!!XLbX'qN -fIS9I9Ib+Jh8MhD6A"RVY9PJJ5&PB0p'Y[$V#UlG8&4)pLZpcZpF+HS0I%`EIL9r -R0a5rlRD[&I5bISIAm*ZqIZIAh@Z0fl9@J%rjPRjE-HK%&VMe[ahKYlIZkjY8F80 -Ka&#XX'E&HYZZ+U"CkEIi(9lVklH5feA)Pr,"kAZDhp9[+RlAE9I@rjl`HkMNqrb -"BY#KE#8HTXIi``KrD%pTbARl!Gk2q'2&)#,C*)r45[iN`TrB%mhQ`I`ahNre'X@ -IZN3VD49r&Z(2YZa@9Ya83fmVPGHLB'r`1[fkVpp)lPC3B,1jRk(RqI-)IljPYl) -5@3ak'AqKAe--lT*YX&I3P9rb9iT"BE+le5[d'RqY9b[qfZe@e[m0BpIkaZe3Vp* -VqP9I[jVFVEjeFDr3UrS9Alq5h+e@fpD2mk$Xk[0bS&qQG)MEj*G#LXHD+,hSefa -92l1j3&Zh"AN,#mPkrNiak%1fPQr4@[iq`Yrrf$#+[k['pP+JArSM0Vi(YIk"X49 -EEK15[Nr[kaIe#kaIY&d%J5RK$AJh-MEhMG8TRYI2XEC#90S+86')5i`$K',M"YE -lA+bI&4EapE1r$#``N!"#8YMl2&%m59(L*IcMC6Y*93+LNI12N9U5TU4@`Vq[e"C -I5Hf%IlJ%%P%#VT!!m`m4*HP+9-+I,4Q5U53MiHmRGD5Z%T!!H*ar6kNRpCA85rK -l5J0TU!6-'1II94T*Bb@0%[lZdN5D+QQ5m(H4CY*F#HJVcYp4@NK,*H#U12m1dNU -L5L")k2aYTE@d83)'L[1hNVDb[4+3!%LF[jQdNrC+`"KarLDbJh43![k(mcH3!)k -#rS(3Rr2AN4fPXa,32*aI54I*JT(`"p*9ZLN"3F2jDdPhf8P*pi6INjeP&b8lare -NC&IC63NNpTcr"pPGHLJ"hm,j[j@HdNX*&1fFrd[C3hSVf52KrdcfP,d8eU9`3,e -2(dQIL23"BE2"b)*BrYcUeD1USUKNQK-`NEM@hNIdUAl'emmNa%B%@RefarL-[T! -![[TT"G(P-!rmqLPI2aA2`pT+UNN["rP,qNEk4D5I&IUd%Yd*BNY)T&%#kT%GbGr -5phU9VeF"3Q9X#U##FQ,MIL#YRr6eNmNiU+cC1-1LRr$e%mQiRF)ipMK9Vr6ebQ3 -Fj""YA#hfpH0iNR&CBHNXX8hr2Y#rrqpe@%+j4KrdUdcTVap6iY6qV&mrkZY(Ni@ -(lUZ56Q(K38kV,`-L-J#-K,Ufm#!m9A-ViY@(@U5Y6J0ZV"rap52*kV4hq*T`8re -`S"qZ18C)5'[b`G*U+32e3dS'ZPc`k`Gpr@#b&JrCC#"8f9UdiMD5(C(X4#f'&CA --X1dq%l)8aI&DJ%9PDp'@fqX(I2e!XKBY(EiGZ)0H%HJ92brA!PkBV8Y(lLb$p2d -+ejJ`,rakZDqA*qYb[`AVq'IFKE[*hK(F$0)T,Hb4@'@m'Z#jf@TdjehdIEkq,eN -0L,$EZ&fjKllAerFQim$QXh%pZEHqapIh*10!kE0aHh*IIEH[F8L+ai&LD12km8" -pPkr[5XD"`@MMXRQ`[Y2AGbEM)&YViiE`-(f(Vqp)a[NZEMMRkYYpIAXb$[a+'lF -[MpDhqIUfC&bULa[$ir5Y[Vie'3IeAYXpihQ#$0Dh+(%UM0D[E`ldc6pYM+`K!jF -US'lTQf5)$2Ae6BP6J'$cXeJQFElXSfp8XNpi#JMp`d5'390pZ)a3iJK!#*XX14% -SBH$)-L"@NJHe!EZqb`LmZIS'*ENZcf5H)[Y'"-+$N!$0!*R),X-hf-d6FR+T-K5 -&Z&j'kZYmEIAM`K9I4VV-"9`SSb)bUMTcUVl13V6[D"QMC(4ii11CI,MX*f2eYIS -D*IZ&4al%9-Si'DpNA,Md`emQ%r695LD%5hrSRbL6&%LJB@H9F*QqbYGA*CCqQH6 -LCR+*[Y,A9bDArU[YQ('N)C!!9LTNriMX[k8(P)`05C-mQ`q@!j4!#-lfd@bHUkm -3$@didGID"VM'eR%-hXPbS"*,#-)D2SrRkF[eCD`[YbNJf#B#k6L*b43Pi!KCJBP -jI*6N#8BRZ%!@f$`q3PmU'JT[5L$ZPVJB,![dXT!!DcTcES))#9H#"iNp6k4!TLS -"k`Gh9P!i&ZK,C"VV5h"RP@R3YQd9(BA*#e9YHdk+#bdR&+bcXV,#T8m%A#%TP#) -PKDiC&q"Z-&eQk)[e43TDZrD`"faR5,(-9,E#YMNAm(&5)U8+R4L1+p"(p0*!,re -YRA*53r`l2PE+)P,f4ak0i'aYmCh!TmK"8Ui%T#',l`3q85m*p*,Im%'Vaq)lN8q -@LSL!0lU*&L33[m1*MaIc4UN850D*9-NX*9@ZkS[j$TNYFr5&qJ)Pd(fc99r-9mK -F19J*&1GX94EcqA+)(+V%+Fc"IlBq2p$REel6R+SFU"[Rb@%41H`20#H"@Th&XS5 -AbH%b6mRK$JXi%rUm3*qh'FXmKf8TAb,c)rK*JXheK%#H(5CAmbebK"bTm,-$G[@ -(rbBj5KBS1FS"ZjU[dHF'qYbYNd3*f$jfSPl$0mV[j'JP[h1CVq8Ep6Q"2ZI2FYi -#4T!!cA%05""R"rVXEBaG*@!Y*@EDiN![rYY-dj!!hQ0pJCe+)'c*-A+XNQ0FIpl -*VmTaXP#ITFp8!Q+4lFmlqA%jANj3FVcVU6[j2MP46P,L"0IJ[dZI%HJc0[H8iaL -"Mh#[,)V)SNfF3L8J)PNF+rJ419P183*1NF@aJKr3T`Ikp-diR$)F1!F2bkN41A9 -,Ed)Sb[EQNrbLR#DR+`($b2EQNrbmR#%Si"N1'+lrqV4!RlDY0mpd[EQ+Rj1cC,% -5F)jXjUG`Gcmed)"GSp8Z%'fcdD[i+Ae+S#(0YkdVU`P+qZ4!RlbY+b&&b0T+%3V -NqZ4X[8M*fDiV9f1BRL2RkT2dL8T!LE&GZCSrNI2NI#@3!)1chE5Dhj3,j%)P)"l -CiUcQer3*J6jKkd(K3YGCVr%D@4+4*6q5!!4m*J[V(Ij!PJT@P+81&XlLq[K!(lm -9&QK(&YCDIPmZMXM&@aS@T#REX1[i1lP%PLQ"F*YYf(AmV9`UPbQje)&FajrVKB& -HZ+eK,h-0qcPr)jI,&8SZGjQri'rdFB%qlQG4Hi%JRFhc15lIa`Ekf&pEGePekai -6k'1fYHj*YR92Y"[V)QYFE0dAf8k'`+GF+9FTXB*hN!!"`+H2PUYC3a-Z)PH(,*e -0ff0)4SM'LIYZEl`+lc9bV4))`')@!-!GFTeFVhqRXAb!"@9P+`4Ah4X%T`L`S0# -dm0H5Qq4Q*8iV$(j2(aASShlEkaaj#4IU9,NP)VIm5(Q4'adi(bIQ@q8f*EFkF,i -%qNJm[i'lcB%,*&eZMmMY@qB#L&FBV0*3EN&e"B`QZ92Z8S,lN!!YH8-FCHq@Hr3 -4HVi5U)ECNMI%SIKHZ8m*L%Uf+JeaQ&iZZ)Y"*Fa@TD%dd[-#2@rc-R'rUd%MD5S -V)J)Tj8e,#G6',)k@1&!r)!mUHF$KD#QYp1'"2R`cMJFGMPE54Kk+b%0EDJQU!@D -FG-+Pq@&j4!QB8*Kam(HA4`A(6E#G,,"1XU-q,0"10r![-`jU%CKaZ(KhNpr,idS -J5Q`cGjCZqY"!(rSr2eXJN!"hXMPa0GH("2U3!&rRACbMCHIG`B%qH0Zm1m)11+L -ALGb&Gk8mS34X+e`YT)Idd(2e(0C3PQ102jN4!99+RY5cPH$-E0Zj"lTmP6bPCqN -U*DYF1rI!NHeTH8B*P+CX'rE!AIeCH8l*Xkjq2D5RVJ`dC%)fYH&cVJel5Qpj2L, -2rh3$J2L8aG*AXZ8&H9(*#`j,AqQR+`*GX4N,U&-@5cmC+#p&j+8Y,If8'dr$-'4 -I&S%ZP,`LVbS"`mA@FjM-P0AbQLlA"bPClHSj62DAeq80*G!MXM8B*[[+'RP6L9- -cJRqi,JYdfGBekNeAMq'5+fp&j+drE'IJlPKBSf@m[#h[+((b6r#2dD@",Yd+kad -(D`aZIQXMXRC,QChqP"`S4I+Z[+F%'P"fFKdSdq4pq8#*dhU#2kC,!PfbEA+"kQ3 -R9dbQbSIbNC)2AHBT-PA2$26-rrRT"J&,bZE%48mA"lViemN&GDV%j*S4k"RE*TG -G2c8%r84HaIZaI+,NBpI'*E*)2TA2p(50)ae%S@`EPmJm@5HI+eRRqUe%+Z3,q9, -*&kii1-lT`N!AEZfh,efrP8UjI"@4VhlNJmVR$YBXh,ZqPQq81"%Sq'IVDB'HYK8 -@'&J@eQ`j@,k0b,GEfKKD6lD0Mm64CVemTf5pDq-MFGMjARj3mVd$HD3FTDF'HZU -f0JCCbVEa8A+XE*!!M8UJl'3c,j!!Bh9"S![qjkFXa)P(!F-#R4rSr&rEH"12+br -3HG[D'0*eV+f)R8$(5l6'e9Hl0MiC3aVNF4h61"C$B-UfmFQbe!2e4hRJBGPq1eR -1m$`[4AR3Jl,&`49+6`ldj*pS!-Tc'P&bLTcZE4IaYYY%k&1H1$5,jA`[eDZP2*! -!$bbDaEMG("$S!rk%"J*5&XhCFTkA&[(50[FYIM!Tl0Y,j"U[YZFVcj'qi,r+#lb -)mJ)($iF6[AqJprpEhhV3IE*pZdbZp*5AVMa)5GR-PmU9HP+J*rhmEaUHdjG#hN[ -ea%"2r+9A26!c%Vdk)G!6Y[9Uc2BUrSP*Y#fRKMBSDfKSLVC5S4TbZkbKm#X#LVH -Ai@8U$q`eZdVH+AIUmASFkr%f"F6Fa-[%@mHVUl`k)A-!+HlfkLR2D9,"HjFH'qL -aIkZ&Klp'mHVVrC4Ahf'm"fH&-ASdkc%@ifKE%2bKMc"qVF0VS%FT$mbiZ-U4(UR -hC3ha0GD3!'BA$3@f6*S-VN@Zep"Vj$AfQRK0@HFLbQY)+6T(Mp$$pE"!jra$25l -3)hi613cdm,q,qHYKreD$5[FDiDm'p$k8ViIU)9icVlNH(-$ppaUPDdLdT1Lp[4D -HhKXr4q#e!1GF$`VdS*q&&$A8UM+pCL#ZC1Z"HN#JXrqD+G!$YiVB"RV!Rh5m-lh -Q8+Zj3IIArA4Ih8I[TII8[I8H%#)r3d1B@rH%B[D&ZJFYeE[VhI5ZHKHkZTEZlm6 -FIGd[,R([kljaK8KIppNQNZrV[EDTd2Ykcfd#mi(ZrDIk#@T&2NVP5&Xq#ZE)46k -+jYJpRYiG(VhE0PUTVhH0Xfem90MaFHVS`93d)rZ'R$9ekB$ke2,0NNj[,AQl[If -0Jj5F6V#f#kh8dV(8Cjcp"CF2PV6lX0hMl5l#qhLlMpYpmZPRaE0LP"QM1M'U'k& -k1C1TIS`DG)j"4kJ&T8h2[Q%mE9H8IF1BR+8C'HPHBcY-GUBlp%kkZpI5Dk@l"A$ -rTYLTGl,c%kbK6!rX0pded&hr1KSb2DLHd8-k5hIaY9AqqPQeepGGiRV!G65Q)+S -IG%5GqDh1fGIM[a1m*VC1RHPa[D2Zj%@peVTM!2GrMp4d$CTTLZlJYI%dQ)6T(YK -qT(F)p!kr5+YUe#86[jq6UY[VGRTlh9DhdDd$hAjEcN#hfcSDYrqV5PkJfriUHaI -S0PX&p!,GHUYdBDEAQY*d9,I5,A8,h9`hddeeNd"(IqYTAlH+cp*!Yrcl,flS&R( -C8PmhM`Z*qYUU4FdScF-mEBSqcbXY,mJVU5bSl[0-p`-FZXNr9T8kZL-9GCS1)E3 -hff-5VXLq-@I*a,FR6Cb`BY+%*HpdhLRlTTa'e2rLL@[I,XBNR&%)j*f@AY)1rbe -4+rZ@R'AfrbD#Ll+IbCQH-CiD,LZblKP`&m&Gkk)C,E0[R*JchUc-X6%cl!aXDQG -,BilU4VUKepEEAMF)G12rAFBdL0BTZVlAcY0J@+CllHb%U4ISHVp)mqQ'GX+daB5 -TUq[S6*fKdl8+G0eY130GjpIcI+"VK*m#MGq!qDr,8k$6IlTU"&TYAEJc[HdTPl- -de1qi"rI5!ILM[UkYdh3Y(Q&CQM`""-PbVY+TI!JIa3Y"+P[%Tr#&I#PI`9H"ph3 -V2`B@cV2m-JJYEr1(r!Pr"[,'pp*(EiFcESS-`(&hEmR"HA886UjPZ-mG*[1eKe[ -HU9TNL9bX'HIQff@&2!6fr[2bNV`PDcFDq8UqhDLplEbdM4YpMH8S[Ri&bIA,UM6 -TfVqZArM0VIMkCI@4l2VPke6V+5h&')-#HAbl`bpfK6683(Yr)RN&8%5YS4F&fUN -BrC'p%N!"k*mhrf#MqGGp0GLSrh@q#cCZr1ZaU)jZ)2HYHI1YYpqC1@[YZqp&+#h -RX3mlBpaqp1E(Rhb+Q-q5-6IQA)50dZSQ`iC+1G9Yhi+',Sf"XYk#fX5SrTYB-,& -IaUJ4mXDSF6,c6H1T9BbD),jTM*V&U(NBhk)Q[PD-@Q+J!eNVh1BD!9A8)SAG1N4 -UAm4G()-8(1*JYdh'KHLh"lTf-8,!$L'k$NPd0iIS1QEIR"1M6T0TahEfM9&Rf&e -qHTI'Sl0#ld9aEpI3Hh(Ffqfr-[rj[D3GUY)p4MX9fj,XR#K*$(p"BjI`@9K&m,m -Pq,Q5@h*3k9hM&GmYhP[6d3flarZY4c`QIGQ5'2AXh#llPM!e)UeiT-f`4df'hXN --k*3piafc9df'2SN-B4DJlKY(hbqHj4*JkKr(0U!Qmm!Dp0Ra$)-50321[H0i"pG -N(9*6ND(a$2[8C"L@c("*$(m3J3b`4p4Nb+QT@CKT@8C1ESCR(J1KecaU&FmH`95 -hrr1""8aprrVVi"a[q8P"r&G'MdEi'`PU$PpQ49i&ITq!&YVIJS0pT[ep0pJAMFi -H0aU*VkfSR'[23!pAP&9JRk*R"Z3-c%EFkre($,3UXGqihhGMFEr[aZRZjpfiD9& -H-54AZ6dQX[A["0[kpbV%L32fd&&$*Z!((hLrXEQP82U(q''S14rrjK[)4N2`1Zk -$j[SmcQrH2+8`c)(I*)%mq((@PaEqID#,`b%dU9h[fGq`#he4mYb22q"AZ1U6Pm[ -jM3Bk62Eri4,j8Zb2$XDaTMJ"rM0$Re11$hhEfEk)qfV036ekaheh`lI,"m[$1Je -`L%)IMVh*qNfcV[m($3!,3R9TE'3J9A4TE(0ME#kj!*!3Uq8!N""4G`!!XKN!!#m -,rj!%39"36'&`E(3K!+q0'8#[Thr$!!"AC!#3"LfT!*!%6+X!N!M[k3l!6ir6j+X -"d'qBSj9pARkH@@rRCqI)FZ4cch,8fFVmcZ[-jr6lE1*P0[#b0j[Bc-[[c-j"0V1 -*fG6,%1"eCK1EfFcH!cJJJ&`rlXQcKr*cBCXYE1&3XT!!#5JjN!!m*#KB#-36!!G -fGSBRBL)Dr#940PkH0'r(*%5-AA&H[fYKeeNalkHVB6GE-HrRJf!I[-,V2V'J-$F -dZ,bJX%b3!$NVA&SqU%pfBlJLhpmM+Vq9YAZhFjiKZ3jY&1A&L!P3A0[T4&8q*4* -E'9,P1B9Ca@8&T`iU,dh0q5HJ3%rI(,lL[,ir`CkpV-[bEi!QIpPYlei1ZcAmhm& -1AGCPa81`TklB9@0mGE[q@5VlRHTELC9""Kr-)r!HE2fKBSUI2mTD#eV-EjSaX8G -fFDKdBP'S2,qJ,&5@8eT38Ki+Pj38&Z5%b`Z+LeU(TK42$%fB@&BH'P03#UZJU+` -mA&JBkSBFHB2mI+P%!j*kKFYb"hFE&'UAfLl0[NR!'Tm-l%a#F@b,S1$MmC'ka![ -&)r)!5P!`T-!2LU-UP+KJa2@*9%r6J@DR"l0K'UQ**ERKmVb5dZ*aH6RPT!EllLc -R&MS3F!*QKd*MFR%Nr5qHqB9UT&&LI['%[**`HElcC-%MCJFDeqbdG8Q-eL@I2#% -23)+N&!`TMG3PLC)9$*lJqpRm('Gq*PD8A)(e*mrm4,A5k-$5[2+*T8@6`S94e`R -K3J&+S45UUQ")TQd!bU0U9&h"L$[HlpYFUN%eUCD#+H@)m0#aYDQ1JZ'A4e&61NM -S)!#T5r88$,5*"9EEE+IkjXF!c$UTiEa*jF@ja6P&%`X,LDBKE`U&#`[+&08RX65 -JU,VjJ4S%B-3(A'3$NN*dB6*UdG"mVkJKLH8[kfp%)3A$Vh)bTCM[222G(afP+13 -D"'8fh`E-Ym#A8hjU1C[[EDIp#)2Ui@e-643-[hKeU)(jaRaYYJA-0bMHJ!&C!`H -%aqHPPjB1)1S+pTT'YT!!E,kf%,CC#%h`0M9If@l`)65%pd[cKINmB,k-31K4@*E -PkQm*-!VK#`[KFfYmCEZJMLZ@4d(c@4Ac'4U54me4k-#iJC'1rT310Tm%B++V3)e -jTD@K9[KFp"bb2S8HM6(!9XpXTC3d5N#Q#@9MIAY!f9JaReLmY9`AYdDI0a0UKXS -eTd-8$,q+VDQrqCKD8-X!c$UTC92+LR-,LmH'bmBl#X,Rm,BJ'Hh$1*TDdD%+4X6 -I%@mE"52L2iT5UDf#%I'hTc4UTf"%r)I6BA5iJK(aYm13!0"H`BMifp+4G*5#iEF -*X&'()(9!Ib4RjqH&4[[$9I'B8-Mf)mTlP1Z$0T4U2[,-4hXiSVh$daD&k"K%dHT -5M5DKdR""@9iZKT!![""kTVLd8mL"1Yb"DNH(Q3m$jN-3#KJ9K061a4e14jJ2222 -"2jT1!D'IScdGDGi2Q2GMZGZiZ+1SJpN5-&YLFBGD%M`3&HP%RFal#UCI+1Xr1SK -Z1jJD$XS[RSLUp`RPj1IPM#mT,LJUpf[Q0d-A@c)fla%P8%Z+-jZT-ad6J"NI'&e -H"*EY60`AJ$U$eii91KETZP"A"F2(L@68,8MG8)+iBAPP&S`JNe"hmkkLlLl*-8M -E)dJp-#e)4V'I`laV!4m$`1p36l-T!$-qN!!lTV"F88qAY!IeS[3JTIq+,-&XX[! -1`G[,E&4)%$mFQ3D!QikMhZCYkU2J%+"#c&$U5rd8$#R%R$Z!XN&9EbRU6e,Njmc -'Qk&JX*f@XbME["N`EpUbjaHJ#KR4[&Q8DGj3P1Rb`'pH$jMAEIq9&@*)H-0fceZ -fkrZjZQA6%-S+)Qe&h46eGM2C#$U*MUH"#SDID`500+r&QGGXLS%9M2bUCelppjN --G8BkX+p&&%EY"e'fJZ%M#Y0SmdUFHF8BK8V%%,hXQCIh)YVSceF136a'UX(*0&J -D*ND(%H*hTpQ4-f&Pc4l&ZAP$`U@P"F@PS6ipdc%i(j9k"'CAM%qFrFM*rKJejq@ -j2$MTD,VKb8[p5DA$#a[KEmf$JpIe'0)RRDLU2pVj`0EBrJKNja5fc4iIkT!!Q[E -lHQ"&AkpApjkSbEqMrrqqK+qAIqBPG-[+kQmV%GNb92mY5Dd"HH@PaC2c5XHAKAj -&M$d!YK3*+r(1XJ4A8E41&3PrGHh+hHRI+RFJ,D%Pi6%PEMk2`h$ANBE44,U#EJK -QjBI,mN+(KBBA&qApXj4*I3XQ(&)@bV*J"i6r[VMj9e-&N!!le+GSE(lB)Ir[eU& -!kU!HEIYN$NJrVT[Y'd%I#jeJAP*d!R&rT"L$6F33"IlcH@F-M68[HZE&[EccNN@ -4J(FS$9-`--VBR4HC&m`'0LpBDYeJ8`c$1ja'+"MqcL8HbjD4G++#%GZj2'r@Qh@ -HHClUTe&`E&kjf`VP&T6kAVIck9P3+QDp(6r@@FBl-ET!D83R#DKCD"5GV'"`5D6 -SB3'MLRR121ZCjrcKF%aaD8kH4H8m2U*REBe1aMZDFK3-P0&IVCPR+*GKB#@6L`' -L6kKA*'8)@kY`+$qF-cj89SaC,&`HQPL@9eTQ*e0rT99B-,SdA$SPP"-Z#[NirB% -0X,%c+LkGiXDX(,aj0%E"L#&qQXBb$#!HLe'S@kLm1$3k$b!Rj!&AdGK3-A#8@X4 -fGiE!heGRS*3Bc048M1%@k4Lmq95JB2KE(m[bifLmH8V"p([)lX#`,V,p1i'+&!b -fV"@(9Le@91`B!9lcT'HHr,14U!MT5m`6LNSFS4`!9+FS1X@PapE021kCarIdi41 -fUFGAE%)H-f[0S`(cf0j0#*ZePJiHY96cP#ee!Gj5XdC4U9Yi938jP"%'3NabGZ# -ULFh04*UNB2METjTB8%dfMbLDl!C'kcr92+b`er3(6HZI3UFT'2ji94FlViF#jL& -rbe48UZLdD0kkG,Tj80(T89aek3ccJ+)ch+B&IV1DcM6h"f$@5Fd,PjD0'C0E@P( -2%)AK9h5QC9k,TjDBqfeC(l$'JpCif"U2f#E"IMBk'YlRQI[fV$h+AG'UBU9f9M+ -GaHp8cS5B![M%K&i&4EPjTFhiqe%c#)XHqr,J!qHEap1f1$qq+lG13mb$j[(MCN@ -S0C%cFckali"Z23EYRJQR@G+TdUFXId)icf(pfdaBYRBpCN+E+iVqr`b"[hebrE* -'hh6YPG&cS+e%C#DXqPX50@K+@ARH"$"iSBq@3@a!MdV9Ma5Udqi-R5*PqCm0*Va -rYFMrRI$mQFkXX53i!Zp8QUCJa%DbHmdpE1ke$(+26@'Ep'bDVQ$i)eNL"[ecD)D -#%4[*lUCcc9dH6$Z5qGZQmR#T(FdLhQcR&6SAB-icGbSkVi+A9RPQ&G9*Si$,#A) -SMrVk`bIQ6PZZZbbEcDKBK*m[G$l!A%!c&BcB($G,#$1lZF1Xp-`GIMQJ"bJYMbl -PR6HkNcFBmB9QiVf3!'BV'*&pqS&d%9fXB2J%MIkM5m`+4CHiYE2eck&,&Ba)!aa -JPTYPjRE2,2pV*PeQDhQlVH@PMR(YV(0E`0`@@dD[X-%A9l6(8XmXr9-M3,04ZlP -dQB,Kebk!h*I6&GE`!36)-lILfGm*#M39!lc%-dYm`*JEFiSR&TAlRKl@)h3C!&p -*9bNB2Z!N,1IRdG8+KMm&*@'&IJeGUf$%(F@-RA`pF`YG4pF(B+,%aD2(+EKpX0@ -TTVRC-cIr9CcVA52@`U4dJeQXk!Bh59RrM@D4SKXGGZZI6`X8$(q&9`H6e-+!@3M -FKAP&@,NZF,KV84ecNfGZfNXkE"CC!PaXHa(b(CX9%JZc`$-,pQC9"2&0Y)hQHfB -qe8dM,l+*pC2"Q@@G2V(49@LQQfLKJK%h&$NEBJHab0a)+2%Lah5T@(cF,(3c%Ye -#5a3-[qY5XHLqPCBU'$i&T@+*I!2GCUlhB2j[+FTYJ(1lZ8l4l@kChKCEpQ@dA-( -`biIPYlR@-pIZQ4DAZcaBf*YV2(10[rJ"4lK1m&f1mF9FCrRZHYY'5bYDifV2A"h -0kCC%[QZJla)-8N)Vc$a&+pcDYb1DB#AG3DX)Jm0+YrEYL)AdAA5hJZ&cJ9f$hf2 -!5rFiQ2#E+cecj4kBE+kb9EREX6"fk1D+1(1&$ER$Y9iAE+6[&ESAaEL2lPF`r0E -VJPhhDX+i[YS"aBlFA1kCbrpJ6%82906p-XpFpTmc#Gd2`!qDZBSHG+Z4(UM$3iS -JZ(,,mTlQdML$IDZBZACk@BAhBF*DiQ(A',faRPj$MbSB2ZlHe-I-mFbF2BfJk&% -(V3re0CI%Q8Z-%AS%U0BDc%"VA60NB-ImQ0"M#(ZFX,Cjh$9$"[EE6a+@3dmk#"P -BS9m8CbkbdU1R+ZSqfc1crkVl%m$fY,P3dG1ZlJ-"q4P&ccKN!fQ3!*N9CfDK11C -#@ha)h"6GkFS`"!6a,$fRB-J)hcqFeY&k"F1[`4!DDQCkCZDH(Ph[3')jD5k)-aJ -R&6eA8Elc2A2qR`14QBI&0bMl6`C8Y0J"JDV)R1HCmrD2"![4"Fr6"JA$,qeSl2a -HS"F9$,p%@$bDFq2-ZEC%,eD8D)CRC[c9B4Z!l59cMU+A+VDi,bYkf5'c@pcTF@B -kXCKc,,0-arX+[DTJa(B$CjYTE-kfSa'8@d+[iRf0APF`r0e!%22H'r5QJK(E$8b -PYmaC(X`QDC4mbX5mdLRBia@Af"9N@53!fp*-&b$d&L#pEFj8p(C&GFr`c"Rqf!9 -PAh5aB(h4YB,"+Nc-@CB4hSaX#14KfLLd%@!fd6X+4Ub%Tj[6f*aZ5hLD,H%lH0q -Pc3T'E,FkKGjM'#MRHeJ+(K6U9MBq&"jG2,%m00PZF1fUe@ie1VQGk@Dm@qKp"F0 -Ii+%-jP6kJ+!)1R@I91S$TqLa1kD2c'4&(mAdHr4aN!!qKNURk4#,0p,!f0F@qh, -(b@'VkiN8)5,VQ@chpKp#C61*YK*%BC0LXTkY&Q8!@DV3TfDLSNqGc-Ik2a2k$)l -2k3X&``F2-54p'D3[8IZ%3IPjKB84TFmAH,qLE3U'RmIZHlm1dYGSq!2lqc[XJUJ -SD"[HE`bB$pV4U-lNfb"pLb,%GmGDfXpLS#"N-p&@l408VBbq-k8"Q&&Y%(5Q0RF -LqZ2l)(fr+hH#34m*[Brh"rT4`BKX)UV6G[T*`I!R`L5XpRif@#Vr(0e-9+9I#2V -,Apaf)"NU`*+!+BN*JADi1$[R&`F-&+J4iFmTPPGqUQ#M)Xm8q5aZbD#mf1p#jm` -ZpM@p3MqL0MY*+aJqlp5J'QD#JFB20@@$2Ck3!-CV'-L-iafEBM`c'p"A%)Z6aP6 -[9pka+ra`D3lU"#+B@!SGJ&2e#J[(+8EA@ZDT3Bh01)lR!`*Qh,qBKb&YYF`$25F -RQ!,&#DlEV,p+N!#VB*r3`QFH$")jH@9PN!#br*0kV'!K3MmJr`3q!)fFciPmB-$ -N4qQ(S35cp&1,kR(!M&8-pDZP(q[hK+&Pj5!Va8&AJ9T8Qj1#R)5qU1+[3l0kZ&* -$RXV*R+)BLPDE#-*6VKVNUPCmG@5(m5i*T+YFcBa4A-dPU8-(FI8J9kpN(Lc0fBb -e"80ZNmFe6'l!j%@CKfZih2@T!GF-FXe+jXQe-12`eZ,DLQXjjQP#Kh!G2NKa(FF -m6DJCec8jLZXkjV(qHPaIF6h(-%fTQ4NG-+1Mc-2eA9`6+%A$!411-3qfMBUK&Sm -bcmQH1CN5dbMH8S'Y4'fm$ELKBPmK+pM"Yc#Mc%PX4YNDRf463#[,M6LNZ*(M'C[ -L4'l-jN6,-ieriaN-M18&15%dI&PqZ$3[er89e)lFK*XUEZ)@-LeS*Kr-cFa)EUl -iB*,Mr*L1I!Lh8!c4RYe$Y+!fh*,"05eGr5!G05-m-q,AqLPZjAUY*EAQ3i0mk'p -GVaKL8SXPMGTcDfkMZ(A&hQQiCiE[aJ,GT-8#Q5LR"MPe9pmUEZB+ejR1jVDFCSC -a1m9Y(EM1e)d2im-9(qE!3HKSKRTQk$k+9`cTTe-mGZ8MJRc%lh13!1)d0iVfT$# -h&fk2(MU5Me*mT12URM6#$1%1h$&JKZcMkJk1Uh[5FGc*R+!B8fI8Il3CV2KS9`M -VlacNcK$%T[Am*eN2LVAf),qe3l&b46KmX$91X,cB%EbBcFI`X3'6(52bBab4pkC -"h-8-8JaGU#9bkqmU$#8SGq2ZLVZjFQ!0a6f#h-1I)hhNMNUkiqh*kBSMiXpqP-' -pJYc,cCX9P*11pcJc82&adFh5mG`lb,dVU4ck(cE3P#6`X5MCmGc(C!A-m6%Ula- -6DR,I)+UeQmUc,-bMm2BcQBVl15SIL@EYc`-8pL-qPBqN8CaK-K4$*@UTh2Sc18Y -a4#9k)Sdb!`*Q3)c+Xe`F0'ZQIm$dMe&jKQ8%5&#M90l2-rhmR9*ZFB4TiA%0)!C -b*$($E%B)L5f(j)+hMKFq(Y8Db1LpJBj$FL%NkX[C2$KJqZlMN!"XaaQjd)bGB2S -S2U(#2m6d9J`KRfd8kamDj+&BDREmrcNNe"`KGPd3)C2HeX!++)%(Sc12if%m2'# -1Lj%*G(k@62+TM%HBAST(1$+arT(#)e(R%rNN"GQ0AjGm'XqMJMcUEf3#)4qIc'( -&*lXmikQ)4`Gjp0r)"-SqcM%JR4bATiK1iG`JjeD5#I5UE(VCNJe(bATbRZN4-$e -MC*,RFTI6C"i6j$'9C0,$`Kb%Gk`""ijeC()'ZMDI-9iML5@6-fJUMc2G&)pcC', -pilP3SF9pdML6TTUZ!G-e4LDBefcF'9#$G3QB,M%bk@DTSD##6)lec,&lb+5lVHe -)Ql'j+mX-6'm6Z%LKR(j&Cp$jA"`%Q0hGTELS!Z!aRMRQ6i$F&'8[i9-80$Mq%$U -,CTR1jQJfR@e$(@dlia5mTBbqKpE1$U%f45G'*6[C)E6mYb9E,f`H3$%Ca89Yi() -YM*Q+*r)Na42G*$H,2ZE*I+VTb&-83j'([NA-)h`DRkiB5M[R[iA2i$-9Rq(BCKC -G`QHC$SV2FRS5kjpU-**"r'3R3HZIaQFVk0,mbXqL#mf4RMPbpjKjYQZD#qPLRKl -NkEYSJ-e4eZKJdjcT)-qPKAb1DDri(!ICqQHB)a62F&1cpCr,jbQ'--U@B#jGaHI -c"BV2Gb@!YXFFlTR$p`qMf&MESPa'9r,-)-qXA0iT2Xq"ZiCZj&PmSH*C$Kad1ZB -`cabf(pb&$YbeG!22$[,XbST$P-fQ[38CN6-ZT3Ii)S2a'ZST@f(V[jJ[8Aba+m* -5@X&cq&,&Fe`4PN+fNZDCY$rS4A&%*h8E,HHj3CjEbHf+)FUbX&E4[A`CAkli-JF -,@K(6eM0Ypm##3-V#ZT2Zi5Z#I%9P9F'kLNpeXpGDHTH[&)EHLDrLHBU[FV2A@RV -6T2,9I%h!T1kE[DjfXpCDHS+[0GKK3%jNJ9[rG8'qEXqmEPP`%U6#GLhZj-*jP50 -@'cZU3'CP@[2eI%2!Y)j09ljH+J"4aSYmScP8mBeZZV,qqF,c8FN&I*0Lb+&X*Ck -NChKKN!!AfP9DM'p[`VZ)&bZ'%-NQHBE@mFe"[YQZD(B6mf+mYaM8q4DAD"eYi#9 -"AP)j@d'kbZC3@l!E8,#@I+YT%6!YBl29V5lh5r3U,`hbdXVC#X*5BFM,q$CcL'* -SPfb$[B@Z[*fA+BD%bFj@Ep%QAQk`MPVZCL[VAm%V&Dp`-p6EY-Nd#aMXJ5+ce8S -ApaE%"JF(c-'afDUjEIf)$XU12Ndpdj55dZL!h1)aU$P-P&l-)EDU(@dZD,4Y3EC -J),Q$9bQ'I-M@FJYpb(F'qFlI'NEaUJTX66c6j1rBH"*UI4IIVGKUQj!!G#YY0Be -0L!dZ3E%*fADi'qmpI+rLHbT50$)0f65b+4VD&"!ZmAem[q,l('&Yj8,6J&Ic!`( -6B"pKVADLX+dmJKrNKa3r'282iiIj%F83'MRrB&l$MbTlfF(jMqHer*MLY9(r!(k -FRe!-VC!!mrIK*rNTa8p'rHRm0$qMq1QS[aXrbmmTKSM(qBrKGEaHmEUS[b-rcaX -83aRMr1hj"Aj4m3Y4IcYqL9p@r&,8hiCIi9F93llLr#hj0AjG-E3UcRm)[m&[+Ri -MkQr+Er(ELU&!FIj'[*%h+BD)a2RVm6[mVQ)S4Tcr)0l-lbQ'rX2jDr)@IPraPUL -r+Rr!(bU'c-2j&Ar%(m1)qMhHbTmSKN$$qD[`TrbCiNqMrMMqR,p3r(R%$lR!Prb -9iLqMrPpi'hqY'(S,jrq4[q&[&Am6pAr,hr(hLVq,qVrL(rK(a6miJYT+Rr(f)'q -(B,2Q`,a`lT5+d@0LQEdJi1MU4dGARp'ATRl!e)qHSq([hBca&Ah$2jPkLL-##IK -0hB#T'mR$TTi&mDf$r#hp`$m(q@FS093)Ae6BiJYT&(rY+2P(b$B1#TL$!+%m2"T -3)6QaFEq3!$Ce!UC1,1i,&fFJ@+SG-,9MFCrjF@LI"&-VB'V&iMjaF98J4+L**aE -hX9mkY'23e2"-MIhMm)GqiG(-+Ib,UDiBFK+E(Aj6,@#Ua3U2Bb1+hrF,$bDS`6Z -#[!1+K'Ufm"!m9@JV)Y9rce@R*YFa931QDU`klcTm"d&5N!$LQC6Gb`KIeK3!-6A -NR5CCm8kA#hk6&$"*X9SNff3390PD0-)UA`GC4f[4[k"S['hh#6KF8KLT"948YKC -0ZEP4!4bBLGELGBF2Hhi6p%a`ch!0ACLY5dYXlBha&12-QXd,[`N%$+Dl5&dm#pE -Tcm$@DEKV"[K*P1Mh5,Jm8JhSh'`ef[%4"Y+5!f29f1$LfR-(NaJ`LE%iU2PXA%I -ZE+S%6*9B(#4p0ZiBlQS5!LBK&JH*SBhVaMd0P$-(a1+JB,4akGcEa!G-I#cZ#4I -AKrZEZ)#"%LS5pjL,'m"C4J)388EMS+qdFFGcYJ(ei+"!*1i4&cHBKaTFKS03+K, -hN!$V(Ua-KE94d2Rih31reTl@[dq-5')Rk`FS6Zm8NEL!hKPG"BJi,#-j9q,e$L@ -i)SC9J1mr3!5Al54"ULKa!L#%MC,%S#6D*8Z2F&%16JlBm9fUi$e3rk,N3*GR&)q -@3&!#pXj6*PERb+&r3Cc'cES%L8-KIKC2ra632dG(I2&FjMc1Pf"3JK@C%c4Z$3T -$pLT+NT5!EE$J`iEb,%Q@&,eGrkJNf9rb)+CFUNSe*EK(Jk%IrK+TVRp38YdIqRe -r$DQT""SHfeP&A++r$qM[Sd1re(4af(lUl`,kZqM3Vhm!cBJ6$@'9@5DeJP+VXJH -8T2LL55`G6j2D5R$cc[E4C*kL[aApV@f!lEB"l"8j5F*E4`j5BJ9"U1e8RUUrd9q -crXDQX+IL"&IbT+l88`+0N!#p-M'9cj(kdN!*Y%!@f&3q@fm6MBYb5KV%0JEk+dp -rj@Y0*db*#L(KLZSJ"HIVT+%d8J,9$rDX2)0Rk#mPa"SA+B-5`P@h4U&"B0k**Ii -kb@h[Ti3LDNaFJI'(2K&SKD5a0&(5f$AM$1M-QXV"qJ[pZ4,XHl(B!lBVT*Nd9i* -6FEBjCr"-184D+$R%dG8-2PGrjZR2rQ1F%T`3X9eh,PmJ,B25mZmk'X(DfZ+EcCG -++cP8#84$&YpX[NKrkZP2pq-le1'lL1G)kk#dhLd,%Kc(`iU2jr&1D525"P92PEC -+8Ph9jr(pNLEYp#GkUa,FTE09RmHhbQ&bZ",FTE09QFIAba(5AZ&dS9q9HAberYM -6(qmDdm6GP-1bm$Sj-LK(rNhQ*)Fl,20jX4`P(C5i@hA`,p!IHIUMh9Jk1#`,H*& -d$%V(bRUfFf4b1pmYRH4S*4LJ-2V$IkGdPQ18i-5E"BE&QIl3darZB4+&H[L-ZSa -AbE(54FQa,[0bAU8rm,5lD)IE458P1EkGPG9$#44"0XFbAUlIpr6lHa@l5U"DLR, -D&Np[qAG1dcK1b(UVC58)YU5VG&-#KB6YcpAmYR5A([Sp[9N*K%@f2eIcFp*6dTA -dG$feQKq4AR+FJL$!,`lfArTG6lqlZkHFaSJIi)HPGe"krkST9!)KNX@aPTq52Y* -A#64&&JFfAISG6lqc'dGIKq-aIP,k"D9IC@qLefe[2Xq[5hmCS!3+)pZEcr1VNL' -C5M)F-+bip#C2EpVEQjQZ0cI`+j)PabZ"jXKQIS&Id4Xp[C%#VMGY#B%E&qKXp!C -q3ErYkEIhG@@&3%QrjHQhpRBPcJLbhQblXK[HJIT0*30G9fi%Q3k5E2f'IPd**$' -f+cIb&c*B6P!bf(A64Rj2KXK3*Hk#'2bEp'ZHIZh2KB)-GCfeL6I,X+!-qdd%)0! -c@9JIm#FbA%BS'HjJBIfQArAdUhYJ3ACNBAh)@f9N8%C@0La%8lCKYr&2FU+FT!3 -hJ'c$EZ-ICC5FV!6A`ba)l1$d+jjqC@r$iQ+BEGL[q3F*bfJPBCIj'rj"[qcTPrh -bP19(k"3H$%!qSBjfHElQEr4,RRjTAqZH90'k,hVDh@,lYpDeK`cekhCLIG-D1$[ -+fTiG&9c+P"a"@d!!K1N4U`64,dJHDpaR#dUHVp,jGAVda3LKL($IcBeS4aNMBj@ --mEN!!1kAI#R3'r6c5Y"@i!,%9*Ga-Pi*9&"S@[LV5+&-8"Bb+JKrR&l[kIAljcS -RAT)il#q+JQL[5XQ,J,dYZ!"f#-95SX3G*S2Idq[`l!H(Uf3@R#G*FNT36URN"3L -[3+a55qk@8J&&L*3*GJ[3VYZ5em))0e%QkHIdXdT`1Xb@["B'imPbUK))P@a9DNN -pQ5+R+F'T-&Z9@P*E2q2TChB2%kHj'Y6'QZ$dS*bqHbM"b6',Sb''mM2N6#9R1"` -BrIA6RRjk0iic(Bj'dN61#XTCPE@%e-#+k9[*i6*9TLQ"%JSF"hml19ZQ+i(Db3, -$h+fIm[46HcN1eb,!FA)S*ZCcC)D5FecQeT+QRr6dNa4+Sb5R,LkcE@T,'I(lE3Z -r%TahXMN2PGEk#8mrXBr[)KSYbhH2HrVa[AchR#8iHlN29iY&cTAcP%"YKEf-G*! -!$[Sa[CEeBcD&[3mRN!"+bIRk85ARZhEZJ#kr3'EU0IS4*4HiGZk!5A#@A+J%PkC -X'hD3!'0NYPbNC,DVA`ITU"rfp-1lfa!h8@`EGX3JIR&3,[jp"i$M8aC,9dQA5f5 -1NNXF&XblqL&22l3E#k46&NXh6,UA"ZA5bTDHkHLT[p`KFd9`&dSZNmZ9A1EUf9m -Qb"9bTAj32k$N#PI2rTK[VT*j5R#2b0DJ[a`[9mXe5Y`e)cZZkY@HAVeRM,V'e@- -!aY&VJh,YhkBcD(FXV'`C*YI*p8VFq5Ii"q[l2Ahr(PMA1eL$CDMF%*3E+X[XlNr -*b9)J0mTm*EJ"CCRVC"NV#q3Q*Hl@%raKICqRlp[,A*!!1PRQ#Q0b@5L,P#adQ8I -,'(f[Tqpec1@Aa'FZ1k0&r$jcqC-D9&)f*kBlIBqRlpR(A,K1&@@ZZceppelQXVI -m0+lkL9b1Gl(FV'5aDq-LN!$%,E*%hkA[9)+M8,D0Ld$KYmT5*EHkIL[#A(+Eh+l -N0PHF)LR@UcbpDNqrhHlkV4KMcE+J,2Y0$bT,(Da*FVSXPa9+h"%Sq#IV1capaaj -B8'"C@*2P0&NCP*@9EBaE6lD0TmZ&i+Y95Zj`E6aGCXUGFTH51ah)kA+1AZRTPA[ -E'')TfmERJ+l[PRZ8i,+6c6a$,Y!V2,hLE`1)Dq1+!F4[BhFmbJi`HVQRPqpVi`S -GPelQk@9lfaLRkeME)hD#1ejbVdC,hZ[DH!k+ITrFVfr6D&XFQ,*Y2!ImY9V!cY" -KfAkE!ljq8"j5JRY3YMKcj&*pUkG[r9d'S-6GL**,jA*j1)J,1"@#2L821$6cj(T -j40BSJIM!STNR9qXPRPlb$c3i)'A4A!h5IM3SMeEf,GEeYQmAb6*C+imTFD)[q'q -6aq8**BmlH)YNXEl&dlIXl9[FIE*pZeL@bT2bP"+FNV+CEjDPqQC2hqaZJ)E,rDE -e2Akl+R(hT5`VkX@HAVb[9k(-L2EU)Nm[fYZVYpPHA@Vh)MM5*aT(%PRMN!#QD"` -1&BdEYDbIYjd-LEFm,FmSJAV0MT+VCE9HU'pL[G#QZ-QQH!E[Xr+FNQGpj3"52#M -VP,LE9,E&p3*2,pLlcAm1!0CVc$EV(FD(j#&pSlk"pBd@i`ff)20Kd1Z)I9jMX)) -b,R,P5&qRVf@0ifZXm@F'SR'"$D)%(,e*J9Bf39mM'q3&H9&HNTGCAi-MVl+"i[A -9HTkq5PrTkD[rZL(RkARl6aekqUVpeb!pIH9rhi4+NKHS5SUqJK,ejISbH89HeA- -pZ2qc4NND8e1m[P4HLp-3%5I*De#HkcQHR[2R189pQ@f&9b"IZ84IV#rbp#9rC2, -daAZ1(A[kSRrFHdq49h'cCV#HV5r8Xr4-IB%qAjqRcm8G[ijk"KfYcm&Pp4jk1UA -VXr8d29@I49P9p'ahp$qJ,icm#N&!ciVFL3cSQAYrTL#J,pMlY`)"IIlH(a(`p(R -rU*qJ9K4!UCad+i##1BP4!%9c'TmiI6BmHYTHF@P!6ieSEJ+SX&2P909cU@"mqKf -CQk[456@SiAY&VEE-Ilpjfh&"LXpX"HX!hdSS(N*GKYSIF2KNIV02QchAl#DmccA -l[0NAAhj91#P-+@'U'UCU3DUH1BTUK+PQkc#Z#6@Ja((TG`bM!`V5laLFZ5!j18P -HY'4b*TfScp#Rbq[bKMl0Jh[rh8jpKQ94A!e,%@MJp"426rQ$'P,N$4$XUAUbRN4 -RkBND9(RU(hH-@H0UPb!2'Q[LhP1r!9dH15*F9Cp'S4Tdi*V-0FP$+"&EFC,mc2H -VNGI5YXZ(VG0A$ND*Al)P,U-CZP5I)Qr+@lV%JrXrf$K*Bj-CVi[Pl6L0C@Q53#j -)ZXM64IqkcDTa(#Y&hN6&*qK#29k2d`8Dl$KKEdj2&qjKeI&rR0Rcp,KpGr-mAE$ -R!TqRmrIF2Nb4Yc"9M09MG*l1e6PkY!lVNcdpGMmG"$6ffci0HcT[rpQpJ-k0h$d -0k*c)*G+!YVHIaKIRJ)V$D2bFBYcK,LV2UfMm&*mZ2AhbAe0199e#"Dh'39[rAR1 -3!1MDp&@CmdHm2h,%m,8MKmrrS29KkAGQeUEZ#dGmq(iK5(4mIMf+El9J8E2aKe+ -9p,Xc&im$4AShTEq815jj'09DA'$Giq%ZJ,[+6H-ETUmDN6R-V-Zd-H-YIEjXZ@8 -8[DP2dLI+4YQN4hT`rrFFTh'[*9k2N!"hiM5%&dRbMQ@BiCiHrUrEIKThUP*N)aK -QQ"kUKqJ6p'#GlHPKHh0kqMq10hNDh"PEThVkK$p@9jiHr2YDa02CHbEf&0Q%[d( -i@!r#qEb[k9XpN!#qemIV,*fT-b!k6S)+Z$VN[BGbUKl!4h"RlX'pZ$IhjD&@6mQ -j2)D,H6V2K,*Y,Pr"er&#[TQAm&+qNlIVr[bclXFl@%23Q3JC!`5+dK,Ep51aDqi -V[D@IlS2ekNMG'fZq8l#K1dXI*aGM%h5Yh+"lB8Qc8UI,`r+SlKP!HD+6'a3lNFR -0hNc5@IXQYmcBj*B4QG`#fVpl9&`-'[-[(IQ$BEq)MYA6IIqK%[0dRphk*%rhrN2 -qiZRMrNXdi1PHrl@JpA6kIqhr20hcMfe696e5(YRmhTEh2jJ`kF12F*`a-I1C6eZ -$EMpllr-[[N6-9l'B9CNhB4LeKjGKipBj9@[HJ2SZ#%2chS#DK+R'HjK0-CU'U6E -bJ[eMQHmF4Sh#G"$LkiDTATMUqr%0GX9A#90$%$U3!$A#FUmf8)8X8YL0ID6f4Gc -#-'l*)3jfdeLFMrjJS'X@*J3FiU0V%80hPiqZCITGQ@&U0BS1E@EI-,@'hHEhGd% -N1YAhhK6aY[@p#b2HY2q9qCr[SQDS5VX`(9CS5h*iY#4Kr1Z(RGmRB45*bmmF0`R -c#LVG2P,a)b1p03lGF&5NhcT%BT)@c`p6apE0dZrf8b1b8b6$dEXbG)jP3+FF%qQ -BBhGPk",0i'F"kUi4p0dL@4B"8rF)YKkl-[IFK6ipNU&AY'E!H9`%EqpG@I[XUSJ -p@'Bcp0Z9SAmX`k)`IP)$'@"Rl-U3!,QVCRkQaFQC@FRfa`J`F!9rIZFG(#'R,IE -(F`V+lHNZc'bqS#[b(a(Z[h6FX&ZQfV3*99bB$ah4p[#dYKf28UTEdC4)LYKI,C6 -YrNNErjpXF[2'&"6KFU8pGP#59eTZrh1KX""h`hC0b!l!j!+)bI!(#lB3*B9Kqb- --a5k01dU"%`@U`2h,3Q33aVmcP*@RKN+$lDqCf"VkIchLl`53!-cqdS+p*qPIG-A -b-`"5YKGGSemGrbDKqq`rkB4S84I)Bfq&iKUh8,%ic6M"E'mE0iRDaU9eAV$XPPl -0'lATE5251LqjdAT$U@El(@['KYV'K6VRP"59Gr[5l'M5Hm'b*KFdEp5hkjM%[X[ -0MV%bL92LQUHDlc*1bTLBJH0kEB2$,QRE15-cZ`r36P[5U-@S8("-BNPF&lVekC0 -EY!hH1MH8(8TmB3R9DGb9kN4mpH'V2rL5YM9#SqDIG1bdl-`@4@C("D+-e5Dl,ie -YCC'&5`V,fhBZbbNT,fQmT*9&0lBDiS*YFBc,AXPIdZV@liCQ)Q0j&!2LkYZX0Vl -A`(4l1!ZVa$ip-TVkRLYYR(98X6r6%6P2kdG!JNAaq11I8h'4CJE8m6JE),J[%)p -IjdP-C%UT3G2`mbeGZhDMd,CTde*Q8YI%mbJ82i0#%2#Qi+KN#M6e+I'*P*)B6k% -8r%e+L'PD9fM1TX92abpip!51h[(BFZ'b3blfeQZ"%hF'r6fRa4m(Z`S@p&-K3m@ -[ec"q,bF12me6"ArMBhrXTa%@QPf-@629Q-hieB0YH,IMhB&A)mBJ9L2($Z6DAJA -aFFL$Da9VB%q$(aJXMKeiYe19MlG4h'2!L@-hEXrUEpRYKp-DZlpYPN!U[Z6G#C* -4*pc(V8Lf$Rr(8T%JQB,VGLAB4Z[@`aP0B-14,jBJ%Kj0i)Ilm5k"$Gqj+CE!$pr -N!0J%aL"mijSB!Vea"m+$`@L#RHXf)(a0,-'1GFRV%8j"r"q+6C!!6'[@)CaF`Z! -'fKE%K`03[Kpe4!)ElXFM(#PYq"SrhTEC*N$iHYb-m-2pUL!FIqcKKrXP3rLkD$M -Yh'E$em6#0qfS$0qiB9HiVH#ZF&["GhG8K&2bQJhENYI&`Yf2-Hb)K8H59)4(Zbl -fGH9T59fVKKURG%rm-(lHp$RGZMB108RT@HH#CLR03`fkdM5HPVbQdHBZfkCZ"qp -SBkDD,VV4MNEEZfcVXVR"'Tp)l*[X-"RdP28'Nhf3!0[@E,"pQ4`-qTaJYQh`b@, -RZcYpNYLC[0'@,YQf'AV8llrefj!!+aNYL04!YAk(6EecJqqQ(4Ym0dJS9Y0),Aq -)6(,fTjNLI`HLe2q3!$)I9UXJFX`8#C43I5BmJD'E+3l6KRhY9H3"Z$TI$U82cY( -+6XKbSP23VhplaAhlAe!I4bqT2Xjh*CIPP1'i1%fhFalXLqdm"[ZDl25Kq&FEZVQ -XI)V9A$cF)l0R1[c2GXrSD8HV,C%jl-[)(2DcQm)iS5#Rd"lDUiEGPI8hK'hpVI+ -K$S"pj+!q`qhebZj$m(pAGR4e9!C2hb(A%IlH!lG1'm,hZIAC1X#A%Tp[I30Zjll -$lUXqdrS'hBHiG5iZBbjmq!F'JhYM'FJa"1ScJpY)'8r$YphKb%5qBGLJqVih%2G -#*'i6I,hT5Yqh&6PQ1er@jiMEl(`$Ym'ha2N'(3(I+jqXXElX9I"PZArcb,CBlh+ -BXPq$Vrcr!3!!$3!-3fKKEQGP)&"KG'KcE#kj!*!3p2J!N"#%!*!$lF)!!#m,rj! -%39"36'&`E(3K!+qR+)f[TbcC!!"a+`#3"MXj!*!%*c`!N!JT"`i!Cj66$(m"d1p -bNU19I9jq$Z`kFj!!RF2mI+p*CPjR+r0l1r1+ITp0[0lH$`8fmr1DfF"VC"1cUCd -K`0l,lqaXB(2a(P"iekp"hhN,bmdk`MZb#IMN3$)!b81#JS@!H),A2,2c!)53!%+ -)i[P#&1%[jaJKDQ3*,eCB@"BV'CYI9KV'KVLB9XG(ZSq,&Bh0MqE%bXD94JQjFf) -PCB2l$+Q282Mp%[rPZleklcBZFXbq@TdLk"!KU)LQUjRU0+eQ#MT)+-4,eHRU$+e -1&l)i[&mFE2'$,D*+PNM,+biG&b[*cq2)i$#Le4P#6N5HBLT4Xb*UPSL)e-&PXE+ -#A!'-Y$V0P6@&MPHce4bYCVZbTM#!0E[m!49raiDRY"fA,$iFpmGrEij(LdA+[&& -mQYpNAX-"NlX2+Bk@6#k+PSdV+)f@jTB86#U,aLC0+Lc)"56&4FfMdiSR4bG1,Lf -,MLNS`DQJU,3-E4EYLKcjJm0m,G'0H`r+,md[LrGDLaDkEm(%D*qLXH0L%k-YSQe -EYFPUeD'GeN1f&9PBPPp5LVVc89PKIR45Q,T*,,GX-ZUE&LdZ`U'!JFQ2PNiV,FZ -I'%maTVJN@P3mY@QdH!b++!`6$-NYE$9N3R455I(ir0bbdTCk--$)$IXrcf&59Kb -043X,J#$5PZ6R&TINP8CcLi[+BJ9&"89M`bU+#r2#'U1aSVc`3P(qe2"#bfLdcaL -1FLe4B0LJ3I0S39PdDJ(U(jdIcFX[c#r,cd1DE+3YQ9T3QVrYHK`)p)QS&T+B%1R -#%jNi4j+0b[d04X1r5I`'Gh*8,1cF5FJE0b2f#Ijb`'(fqeCULQLPXMV0AhapVmE -e@[6Q'eQGEVL'Sp'@p[XlPSq0YP,46VQ6LXUkIQDh01JpIh'$@BhVpHdb*Uh[VAE -,@*SL-eAMP[EV!8F0Q$cJ-#&D4BDIfkV6J1`KI9$YM"[U04N9MBa*Qk3kLaZI1VT -*UmL0&d5(400HZ%(8U0p&e)M(DL0@HqLjVDT%4mdlkZ!C3l+E&0NYj480@'D(p"9 -MQh&PX8Q&CDdkPHC1+TY8riCQA0hBbVJADG@*-CdNEQKfipH(Cb0M@D)'h+[0@IP -qVd%pHi8G-D02p`%0`mJPI)m$&EVQj23,Vb$-0fL'%#RJb@1M3Xc-&*,5"&'+5%N -KNCBQ4@B9-52D3(6TdP9%0mqBN6PEG%NlA846CSSSG4'C-LSb+90NTU5*c,38%Fd -Nd58UaB`ZG,+BNA++&'Np8%I[&*&fH*T)bFX8DJAUP-c,U*[V9cKA@#l%p$8Jhme -#fZq&XPY%"@Y%"ULiRV8c1PZlI,UeDd$0Qr(r([mYq"[FXEKVN!"M#h*pA`(h&I* -)j-0j"Z+SJH[BJ[rhSX+(Qi9k&(9+e-[eadN%AmE2Xm&Q*T!!mLpMHi)-i#5f*YL -mmVeY&@5)b-TY#6D,PFmKQ%M!ej%[Q5"q2C%J["lHG`RiH["1-N&ir4eA!#H`&YG -A,dp@B&C[`I9)**%J@,N+ejFR%faCQI%FVSY)i"*NL18VF9fiK*&9BR-%Ra#Z3Z# -)"(`p[)rV5-RAPiIh'@C1J1[2EBPI$e("pCAakb&NZ,ibF9d%QrRkmZ6eGlEXZ,j -keEEVM1#fkicJHe[+ViZ-jDXfCka-AZH@i#3r0h$jp86A*EmZFNCkPdV4qTRGdMD -Nc$hP[+jGkNFEC2DS-DY4CZ0SR5jLKTb4XEcHQXkEThm2hM(@6VHG6EdYpEl[[,R -cQMV,3b,KIiDVbD+R1"V*#)[F[(`9pf9'*"*bJYfm+L5,i,dJ*)NJBc9$Pm&YKKi -0qqqjcFL9J4C%DP6eh"C1(D`+`f,,UM!-%NTL'XI5Z[%b($AMikM@rj[+R2Nd@U" -b1D0MZ%J9UA[14X3lI)e3'$[i,d39X83XT5I8HH)NR!1F`fr-T&kadVbKA3G(@lG -XRFArG0a+i4P%SLU&S3,V"X6NK(L"Q*!!8R"c$j'UFD$ai58ImdB&2Y60%VSX0lj -VBB$$X&Zhp%0BL`T#pJecHL)03a*+U5JmM32[1d)!rBM`aCj#(p$qd%Ap#NDAa%U -QYEb2)5EN*!c$@Z-3TQ1-dL1BNj&ZdU6FAp*Tr$0%TXBK6!G!4D@)U)4Z51GdD06 -"ij!!-j%[%rr+BNq03jK2!HSU%@5V+M)BMF%&%l(230C%`MhaVbUUD4c#K#PSLHS -48Cd6FS'r*Ub'I`faPmBK6)Jf%M8MSLBM8MVZ(rRf`Vq@U+ea#21PSRrU4%3G31@ -&k18A*R29aVqZ$E5Skh*93(I9LiKkZ&L0`GLkM0Q'ZX9-4#L-X%DSVh%)HaUBB(j -Xi1031dY%bLCXE@P%Yh9d!pI4%B$9N!"%3a5bYfLNF3K43,Z+aK(410&$3bEmh+5 -0m0p(00%iK!NefVPT4$40p0#[#C[JhdcXUh%)%kDM[CY(42-%#3bCX,fTpm@rK@L -TF3M6J4#`Ga#YZ1@f0[@%4,k@q'H*eKU(-&mQq+*04,4*N!$',rPDilqIf&rM%1D -V"2CS'a&Y'BlbPNkQfarr!qa2@KcJdP8'cZdLSKe[q)B9P)j,G192R+`qrZe&"ie -$f*@e4%[lSqMSim"G'CmT`NNN'3dR$#dkZUkX"GJ2*(%J#ZPNIp!#Dk*$`f[lLS0 -5"AD)f"!F,$Vl1&E1%K8`G"6&*ZD(J3%)D&`1BDS,,,T%"2BkSR,(M[f,5r*lB8i -UaGL`ImX$1M*NUD)cU[P1G,AIqMKb0CK4A$8)Z'UkZQVf4V0hLiKZ[e@cRk['IXY -Gm!0h33ImZiXH'JFUG,11rFCq,HdhQ!$XejbL"rip45q0!aAJIL[dkb'LYmC"pBQ -Rr-TqDEr`l&HL4XYBrT5bBL``LbBA&VSapMc4$*qdAh,9Ac!,p8l-2$(4K`3Ad9F -FUR'JN[MmdNrdecJ!Nch#4G`!ZeQ,!BQ#dqcR)YYqjZ&BSb9QaZ,#iPJH&jNBe@) -J8bfb"I(D&E1$r96NH$LNH$b#DT&62V3-M)L"B)T)afk6#c!@$LdV+#ae02%CY`" -'B5hkKb[J%1P2I2Z*U*JPpTJF*N+Q3r%I*!CV(#LECbc-+%2%8)e$#'F'*T2$a$# -0!q$MH"@lbAjX2r,YTT!!DRKG(Si1H38PBG30%Md+5XKqc%"ma"J-+mGJSfmhLX` -XNCSlZB4cmKRCY"MUF[JLBMrdlBFlF"U-rq&LZ-C"(4jZ1Jm84pJ2a!JYMR$)0!G -lEK!MlASI4elYPr#XlbM3a8)#*$%5T4aTefPaT+$450`#P(#8'+9a#$Zf"3MqD2Z -q&NF,bJh[Ck(94fXF3S!`-pLe[Phl1iLMA@qf&+hX'XqZ3FrQPKeE*Zhlh!@MA!% -B)Zal[Rd[T%)-m0c9BB#jMZ`klTVe2$Yrm(X',8Di1QU*U(hAYqrqClJQ-4bBjpT -hY-KelG-*B1ECe3,&j,Rfb8(V[#h'f,Gm(2pXRc%SCDap8iZaVRd'SLA(L3+03ca -qQ"J[*QJF`RBD##STY'pS!BEQGZ,i4&'NF3K4(#J'fGGpqrV[l96NfJN-C9rcl'[ -*GRU$ffQ#Z`bk%X848B`E&6U@6@MI-LXF&,3SF!@#[ZbV[ReeClZpbHhf&VIEkTh -YPZrUk#akf&GmqmVIFbrCGjL`HZ%r54bMF8M1*LrEPk4pQBRj*8ja$2iP!P4IiQD -6r6$kPBR*'SH`*6RPLf++IF((mFq@R)*#TYT9@N`YTpRRIIYm+#*K--0K+ic`Y%8 -@Uc+b,h#26'EDjqmK#%#QD4c#i5C&2#L1)h%F#MYHR+"a#)HA&($cFq*%Zp,$-6i -Yj4ARPNp,QI(Kj83h['$4ECm9*hNiT%"H`cG2FK"KAf'ImHdcZb$#`T6%#IK2&c- -d$Z%d`LZ-Nm8T'JFU#Z1eaDPLTXC"YNDmTUKYRrEXdkJfTf[@IPT!CF-FT((c02Z -8&UFj("'h6pSRa1QHI4)ipZqI-qL3!*,m-Ea`Fb[6'B)aP8J"T%l(q2Ui1%2-mR" -%CB2bFcA#i4L0H8M-*M%E4FfaMfNaa`'4)5VE4chlD"`)XSpa)E03b!TaTRh%`a% -hJE3@CcS@`lC)R"84Cr%dec8h0lqde+dThFcl#*2'8`ci+H8Y[Ybhbm2q`8`q#I# -9KT%FMK#kNF6CiKb03pJkpE"219HFTh%)DEJH&M,RL`Xd$L'3!29%IIX`fBHjaJX -F*29&!rZ3!'FI!P4-FaUcF,,f"hhlB&Jl*[KilBM%Dcm(Y9pS(p$L3MGY0!DEA'6 -[&aGVFC(MP`2%[H)5JJk$a+9LVXBK6(3!-PjQPiR,YEK-T"b"'he4c"AL5RZIZ%S -M3$h$1`2&eH)DM3-93M64&b2Z2(Z[&[-F+h"m[PLJF3LEm9$4hplMfAZ!ib63M"B -,()iBfqhG[VdlT(e-()aM''!BTEfA@q%D4b$p-4pGDqr5iPTA)XFALN8DKl#8!5, -(hZRE1hIZ5KDj,2fa#9MUfk@L@TDSL2(#,@E#N!"6QdPl&aGpTF0q#1MV1R'pA@, -[d!M3`F"k#)Dr'm50'SF3Q#%BV@qbYfYaN`1'icH,@c31BFP$-IcFjY[EGUjGER& -C-%,C@helkfjJEQGJER6%-!`cpq+)@!a+#d8M@Pc[f[SSd-kY*'l&TGX%3,R0FFp -4'#[Z%%Xd$J#Y)Z*6a&+l@)ZPEZR%m6Y6aCfJae[%AH*Z$mG%VplPF"k&bISHHl- -@pcLF1Ak[Z%rM%#*iY"KYEr,Y66Ya[XpP'BA"rNEIhVJEjjZCU1m'%MH)CH*q$mF -8$i52U@bC3b)IJqd$pRSY(R$X`r%(lA8D("FL`r'(a--DKj!!IFD)mAD4CaFPkhM -BBC'2BAZKEaIZC*rVQ2'[Cc$Z"aMALZ9fJBGMLTGG8M"@3f35JM%4Xq-MGVi@McJ -`1,l#cY0LK31$iim+c#@21M#+4)QpaV2A*1Yic)'3!paHlGZVGi)aMm'!E$,9,Z$ -)BQlj*HA$`&@q[5V4H#jcI"BJF6ZSi(&lT4D21bUB"SCi3MbTF3Lh"G-`%$iPRYB -iK19-%mIC+halaFlC3SZRhEKb(%E-CdJmJr+HY4JARRATMa2(fmYmHpRrS'%[Cq# -H,!GZVQrRrM(&f#Yj5&l#H0r"NIXipe81a6-`PD`8cfNF3K62`0cf[-!!rVbV$E1 -L[G5hPqj#FC9$F4DQ[aG)[!!8Al5AD2'L5cp,c,BAqrELhlZ4,04V@MaAMZ*&[Ve -SCk8qKUNrZ%k,bed0(F6"pN,IA[MhkTM%A1$dNRKCia#1d4GK*VV!RLpHmH`&m6' -DUhEVJ'eMp2R-Bkq!ami6V`SXFXj,6Vq[ZSRL%XalVdI%klp2[q)eC$jA['(2mA" --$1"[Z0RKFSaSEkD+0j(LE2'@2F[$-6(p[q@kl!TaP6f6l*R-AfIai4bH@Pl'rff -a@Z-3JVP3,,&cl'caMQIRr!8Q0$5TiKh81dZm+plcF%b!qDi$mcV-5@XLBXhrJ2N -H-TmKePVX(Xj)JVR@JAN64UIh8mAl5('D@'GRHMJQ`&cRQKA$R6h9YkIZE2K81j- -42Td4AShrHSYYbAU(m&*aVchCcV$62AYb(1&"qEebrS%`0MPNTr2K&0k,hIml$fP -aX81NU@KQ6r,Y5AqX)Z`$c&I6bR8m'c,%"UUEPUKEb2GiGI5r!RcGKrA"IU"5Z)- -+#m18K(emA(D&aH#['@rVkrIUeS2Ap+Qh9qeHR*Fr,&C58J$T9TmH25%kD0I5VH$ -rRbreLeXhqDNX+@8NiYVT2Ap18UerIPP*mG6mNJQPdDd9SbqJf%h&Q*dk"kKe+`H -YBhR#VD&YZ6[q$h)9X55i)6CQNZXlKCej"bb#*k0[VilNM)Y"CG`QHN4a8Ij[8+C -$'VF2H)Z,l4rMKG'1lmqQmXTPGIp[k`L[jH$ZVITNpqpj5&IZ'a,-ParB%lAiS(b -$HS)pAYS6H#BlRZRT4"Eji'B'P,4B64iR2K3Ea8ILBl%*FZG2a@GfQMh@6T@iL-h -NKm+c8qaN@fC,EBNpaNkbaEE)6[6YP2mXd(dlqHqYVfr,rKkI2&Zk@f$Lfj,G+el -I(V00$Z(E5IrFPNX,0TB@BlqdD,adY!+Pf%,aZF)K,9emcJ6Mial,h+TM)eT(e%Y -(Yb$*"!'Pm!44)4hLb3UmVfX+139,CGU+GZPS*k3B,lj31-Kdm38,PEp-&9pL5LQ -!m1FV(mIIpPkTiLZN'#HkfE%qMVpYCP,Y@%CUNkL3!'R(L0ifhqD*Vm8h0YG$q%m -j$NL,N!!,EIdei"lYfp'r,qmca6IJKCJBD)qfSqa4pNJldSk`4pMKpR"4l1'Ldp4 -ipZMG@KcIMYV4I8IpVAcalC(rl%r2MN5j%iTc#cdl!T(FiY(M2AX%#SI--cqhU#b -r[2$-%'E2$SmV(RcJp5pkU'4caHKQDpDf'Kr"K[6Pl%FVLiV0aZmV8RUq1M5lZQJ -!8BS3)cliX$!LdLD-Ub9%XmFrDMb[dB4pK6FLHlMGM"alF`lj5ij0MFUcI*D4$P* -&R`i6NqeKGUMi9RaRKrJ)r`ZBG(XBFmGJmEh#!Gca2DUdJh`lD0IHIbL$rbe'f)% -fafEE!EDrlHIEJ6[cq6CRjpMTfqaG1j%"[`qd[ZfrDeILfhkrVj3baAFBUcEB3fe -IfmIfYSH)Xf`[fp2fX0eY0p[9GS%Lrf#af"jN1pN$aHZfSeKM1hMfd,JF`V0pGmX -S20XR[L$`E1ri(X"$L@lGS'`[4'c2hIS&crD)lqipfch*2Gf5h02e,qlT%Yr"qVE -clr6Z!pRI10fc"m9hRClY&&md+U#IkJ(qIbe@20YKpe+LNKdL(Pj6@GcIE1fmN!$ -QXTZYDlDqqB3T'cli%)be[RR21l,(6rQSFFmP),0,jSriH"1),-*%TUU,N8aZY29 -1bV@I0Pri@I1d1U,Y`XqEaf$F8%IXmfNBUR3YrMKAaVNbcRZQpl`VHm'L#9-Dp9` -bA+Ka`dA&"GH'85E&Zl1EEBL*+Z[@Mjp5Q!iJUSEaDZ[@,dL%J99ecR6X82!R0(` -CYVhi!62VMa)"l%9q+&G3rd6L*pcF)L$9hH)N36bf'f%e$NP*8$Y3k!'qE4G1VC- -RjFA+mZ1+FU'(KZ%F&bD`2NPTffS*ENpX#rIhlIiK-iiVRTM2M1dLc0GNfr*BG3$ -M!Tfh`f@F**+%3T4-d9)P9)j+lL&6YG`MZGDaqbN,TDZ@UH@eY[&YQj!!8d[bbbD -A&%f*BI[[3SI&#NP#,biVb$3Y+cJ98SV)Pa@PTf9&S3D'bXNmkFZ)e&VkJYM-`aG -lbh5CS6&+K2"Sd9"QNS3q@eD5PE@XP0$h9,HYjCifbl1Yrp3T5HLdHF1MaCkfPDc -Lf9B*RC+XiKEX%2,)UVDPPP@GE)EMe@4e,@(&`LK$0'aEq,E&cSl5XRT5,'bEHlC -j8X%'1aHbf*f3!)4+ApD3!(YT@F1"9d28XI[DCVDTCrH0-f,rf)6mRL8PrH(1X(9 -0"liQfj4,J"TFeV40Y+cT5UJV'YTpE'2Eb,2la%[SAPMkcdeIBbkK%4pJ'k0PA!l -2%Xbp+pLpdC!!FY4j@ND%'K6[k)DbPQhJfBEF9CKqmdY+SZ@6Ja[1YB3Q2F%!pAe -E2jb&N@PLkGM`h,pd,0N'A#m-",L,Qk22Dj1%6Ph@NA8eb$K%XERSCk1bRSak0KS -Icr-+LmI'5LFi#X,RkUhRY[$0aB'b[QbJ*G64,Yj"0T4lD`RTZBZhNieNBbfK,(I -aYR)ILDlC*a(I6cD9U+GT)YjDlLZED`QPZ)ZhNLdNZ#!Z''mZ@XK@%GQ+"HP$i-- -`1Y6J`VJ"$M'XLT%Yb`@MpAaEEaG(0(IeY"*C-LXLXeMehb"D%S-2N!!cH%$2B-N -(!6iA"A%l&p9DY,&e29XAK!*'M@VCa0f$iYc@m5f-!(jY1LdEZaaY)C@YlGRDbGb -3!16c[ADL[DhP@Fa(mA[!NI8k(84(fGV@e*!!N!#%3('m685fJ9bllZ"aaC1"HKr -i@16R6TK8A&"8&Q)@0N0RKNcDQYM[`4T(fEhNIR*rcqk&!NHA&B&P-6$`KVi6A%I -DNQ`,!MK!YY-b,S([*!k5l51b25"3`r1GX&Qf`lq$VD&P"jIN)('`l"L4(GNbBN" -aQ-2#"bP9lSq#UmX$E6A29NI"H@-+bl3md#AY,RV*6K(CD@YPUEBDPeFAri0X95d -aa,))Ucqik@$Cf9D4AE3m1(6A`Th$C9IC6FZZ6RA6A`b4hHfH@N+(lY4K3f32f92 -,(NjeNb1'f-UHVFb`MbX!#K#MZl`jXTHYT'8[P`GaQqRC61krdN)-#C@iHl"!eV* -E3ZXk6"i5NBGXa8e,G"N6iJKaP1`YqfJ*J6VR'J&&EiDbF&[4XNmj)kIl0[eI-jQ -Y`ZQkZ)UJ%CCpjD%D24T@""@deFTUDcAN#XQ+)Vk0l+kS+PINPIYJE##*9TApV+p -P2i%IDk6'bIjDaTAUBk![pRcVlDl*j`9aJ#S'b'`Y"j3[L#[D0'NVFYYJf8N5)RU -C)`GUQH2Qk44433k5Jl8F9$j29l#TGJrI9[L2R"eU0l+3!!TS#6@k8mfQbb&bU*C -aXA`+VKiQKq(JKXF8iF[$,DEQ`efrFhbi99T#MXdm`I%Mj!JYMh$G84'l4I)XG,B -B%SY+Y"b4b&Y4MV3BV5&GGh99P%GD&(YN3TCEd9KjP$'HX4L8mQ-PT@2'j*@8$fC -4%80Fbk1iZF)Z*!-$2-Rk"'P4SE5+$bN-EVP@h`5q#AC0,G$VadGr15T$MT,[rUm -%LSlqAEX2hUlSB&QVU0#RG0c%@,kVpHI[YY)9cd(4`EQ161e98*5ARa`@rmp(9bf -Zpf@AAJ0k$')NiSS1X2,f6`pfaMqpX"MMDL8D$08$UGTaS$TZcp!a$X[rEU$2q,0 -&rSmq)e4Nb)(i(beM@X)C)8kiCS[j54UiA8R$aL3bK[pSQD[PD%HiDD#i2*Q[CGa -QJ&2q+-HB(hcMV%V#16&K`HLLF40'NV!DN!"McIGDMLfRT1pmJj8V0XjEP4Ma@+L -q0pm$"J0l%#fKfdqXX-D4K$f",*!!il@%,F!N9ibF3-K!jP[cM@qq$H'!2@&*@@+ -GjU+*ECU"U`K*Z"V)3MP45c5!BjD+XNJ@DeQ8m2ZS)#HCVc9U$"G'($p'JRZ2566 -!(ZBVmkAj`MGIrA[L-'`kBYKd4%)I&,F&-TXpXcQa4M)`1G(SM@4lI1kEcrrBlU% -#NU85mbF'4mE13ql*FJS1VJ"2q1Bcr2lZ"#fRP"ImU@mq$3[QYARaj++b-0+G)b6 -,82"8HDb@8eh"kD+1R#D2dh+D'i$545ej[$a"5rJ,Y-15-N28-Tr)%q9*R[NN[UA -@mN4Al*kLUYRN'qFkmLFi*lP'V#CUbZRQBbhK(F"$&-GRQ)mdMa"F1mG2PUGSHE) -E[QZ)QQDMCcEbaMbr#-Z5Z0+qQUKK2[60KlY*4aUBR%J$Za-Y6h"Ci6eN2[$0"lZ -cDRPFH4YYm-d'860,q2%G5TJ-`4`1KX3QMd8cR5TRDRQU%m[A&6&jQPN[6pIb0-G -d,F9)H3E*-j!!D*DFVH8Xeh8Y4AXj4jkTj4a(35h&!@DG2-ZmljYeredLRi9bcMC -VYB56!+r"S!Z5jmKcY6c(`BHeP9RMQc@l"X9cNlBRjMhI[*F3@EK1#%11mFQXCEj -MUa3*9i4%DlcVQhF61Gd+)!`0#N-NBEdJcc2[D!P4+5pX1U!*cTFAb![P49UHlaB -f(83RHE'm4-Z,(4I`!ZY5XeV,5a-+f)lQEGqm[DY-D9Bc+TFi&ZiS$M4[+326%#h -KPF#YeeRdP(0*3L%V,j1ADhQCDlh1STZm3PkTj48*$j%ZjNhI[,Q6-E@mXKch0hc -caVpR%RNj#Vl+[+lP9@k6dKdiA+hPeBNe9`rcQM+[F9ZpcY2,KIKI)qGT#9m$ESc -HiP!jAbl3%PB*A(G[dFHmkTYAGc@#PM"2i0,kL,lQ&@9HXCBNI"INYHCP,Dpec6! -!qkq&*"ILfL*jRCD,A$--%!2PpI)',H%@`#8-%0RQ*@9HBY(!$H@i[qLE&rq$1q` -3j)hQ"5eK5F#i$d,*0fPj8p)[aUa5CKA!-E!j)326&5d[FM!-!d(F,'r4mQCS3X, -i%A+a[&A,a3k$BH*`mla[R([+EcekUbX5GN6Q1@8Ja0BblU2!m+hdcFSr"L)$DaM -IV0r&J&Sk'f#fhM$2qZEC[dF#f*[)fq6Y@XD0&NC$3('(A+,P(3kLd5,A2+2--`a -4Z9lI21fETrr6B9$ZbkAQ+5eKdT!!f0(GUH@GVM,Xk-b6bN",6`Dq*#6K2bc[NRG -V'4SfZ0h!%qCaD@#K)XhMR1*Zr1q4pfS*$`IH$84%KVa2,Y2b[[,G`'2bI[1SEai -6$E*%aM'6mdZQ`8LaH"+l0jE',r3U,XPf&dMHMj)H-#ZdI+!Fh8GmmmKZEfFb+jJ -4(Q9'@"EI%0"$mN'5-(#3!!r*Kl9mU"c#jHCKDH#2+JfF88JqM2pbqBKQCA'KXj! -!03r*&G)m"$MP#VLSl"AY@MSK'KYG2"N1[Z0L@)BAZeeiD%T%%NB0mP(jQ*D2*[c -!Y(P32LkIm-b$IiNFB+$!ZhKHYceT(Y!5VCGB[cd9N8p"XYP`'0FEEq$5D&jak,i -m0FBEq6J)EL&[S-K1P8m)CHkA6mYR2(0rFL(r0&I*ESS9j,-'V3PI"9l3Fh`P5GJ -Gb1INmeU#p1)@C(*94+i+ADMCFM#qShmHraINLeUqN!$d5j3[4H4,'2!V1Y1qJX3 -krdAmAcEhDIPbFN-XAiR)9`"#5VGL$*+FaF"m3CTPM0Sc31eHqDUjac2h*VIkF4H -"01aLAS[)elEP6MAhF*Q2iIqkI%2,ea1EL$hPQr)Y,Gpd%b&8XI*Y!rTk1l'CU#4 -A5db9Ua1'2TA-ACkj+lR#ImIGicRr6XrFQ9MCQlZC9f!mN!"JSk@q@4Ub1*0"@A( -BK5iiT$JdE52j"V"j9lkRjEZ1GkU)+QD*Z8-D0Tm`E$iKhm0rMF3-[XEa$UHiAEi -[$I6L%INqjS9D@hQ(p4HaNPcJ"#+BA*,[1QdYrZ[NHLhA1HDT)ZUEfq3'qB&RE[Z -,H6BijS(ETIc3B%lkd(8EacG'j%EX%jU%c)0"JXd1S%(rMAVB%6912lGb)hq!4Pi -X2j)IHfCaNRkJ4QEkUBDpd#D$%@f6Saq1Id,b%b$iUIa-bdmG!Y9%GIPj4(l1cPr -K*M3(!Jb'qM2m0mX[Y)5$-LHU,QV),b2b5jC0(0!H+cp1mJAqAjQEYIc+*B(pT[` -k)VrH`6c`Jj(Q&JEXB`"fNrc'h1LCQj,-mih,A4Z,V@mMmYXGc(-MPlNHrqmNPTM -I1HCT)2D42mJIYB3+N!#CTi&S*(mbQ)UKr@2QiIJ@'@Lja6&-3p()A1qCkj2-%lK -l$84$FjeRVNXbc`h-2$q@-mmLhb`5D9NLKDQ!NIJHIb1Kh6#1CjU)*QDKZ9DDKBc -aYCc#`ZdD4mh3-mp`LJA3raRi[N4`G3I2B'#%mA`8$4rhUHHd8"d5+8V4"0ERK8` -6''6Y3DPQ2PA3"'GBf1$M6JG+SiUDlE9j$p&%Y##2I%h3L6"q6846-mmhmlELTmP -h[3CY1N8La2kKflTH8d9A5jCS5jV508&GPYJlAH1EDlEA![dJep*Dl%mC%FVBeVH -D8Ke`RF6*P%Q9c098@F291bbZNqK+He)96AZkiL"4-PIjjUUr+&j6PB4@U3Y9M4$ -dBMr23CSUZ9'dKiK405,B`9*eUU'TZZ2U(Q+%ZC,fSTUHZI*2VLBS!CQVHiK$U*D -j3P1YmRKYFlQQfJi)MYH*8"diEQAeq)fXhCX#Z,AG``1L5EML(!iV(@QZ!-X40)I -Q-UT,p6`$dbj(j!3C&40jEc'BSQDZTUJMFSlA*i*!MaT33df`L'8iX)DL[51dpil -A$"""Z%H0U,'Q4Ll2S@)!l41KIGbm@8ijMI&[BLl9""'Ffb`0T+B4DVU$bLpPb1B -bC28!f5A8c&cXQ8X59%jaeeK)V'MI#%(e[Sh+,qBbDq$Ih&bNUEQMmT&SeKE88P- -,4q8Ma5KUC5l8e-T41FHcU,8Q1-BbC4mT4TN,2(0"JXS*HMUq0e)FDFlhc2P*+Vq -3!"NKVKjN+Mr20qIYI"%#QBXBfkXj)pb*Q82b`&YYL0S!VIeSIdhl13l*%mHEFkN -Y(H#CFrrL%-M`Q$2ba&KUCml4"-9G)YlHR+fT[@X8MRH)8!FX06[mIa`5EB`V[#k -)NmRCI)!V6bSGJ-imLcV5JCij+dNQ@*d`QB`6TG6*R+N*AV9-*K`rL%$,4!G6Cde -a4pTaBJ*eLF#1rfFb3Dh8PETTLR[06K"&e$e#hAmKNflipc"c0%'pahQ+a$(8-`, -RZHeN-SFKBdXK1K#3!-fQAQD@CfBRb35+2XjG*UE5)4'-20[*C"DA#EpIkQh1d06 -ENFN*k0Sqe&F6HTA*j!3aR3ieTfZ#45Z6#FIl8Ap0d-`aDC`STT[62--'3Bj-S*l -MHbH)%me-cma-NJQmJ$4"`CFJNe0pipb$IL16-aKE1(eTJLDEBCQ*k@d!C@XDi"# -G+FkJR!MPl1JZcHDaL3*2mFdTIa5)Ya33$D4"QL!QiL&dMTKM6MBcT$QC'iUGK`K -@Y$5BKQL#c)k(8%iaRBC+!dZL#!hpHFR@#jX(8-b!iU)@#,N@KKk2$U0KQJjcNp` -Fm5%G6X205A5%*SMaq$d)Fm6$0)*'DZb!ir(Vk8Jk5K1%@m`fFm5j0-UFU'Q8dj0 -`r'KcJLD)RhJ5j(L-4QZ+fm,1%@HDihecr2Ba-fi(HkBiKh)Md!0YT3&Tf-I'`-* -'8qJmkm&hm9V+-mGT!K0ab4c20p-dBB2$8c2(ap"B64"'-33AL%YT("9S'ZFJZ%" -FD)lecE&r$k-33$%S&m+"FA`%pY(EPhHDi1[+aF&BLbC3S5EBV(*aPiXVc&6I62f -l1$3X&hH&Z*SQ4QML$X5Rm3&Q2*VL5XDEa2e8C+CS-&b)--H,DC)Q#(NCK*[%EA3 --P@JkaS&`NlMC62E0j$qHa`(+#XZr'6D%T4'#SQ`EYfZ#+)[,@L,ZS6+DV1%T%*B -&#ha6jTZbA@9")-9P,49hdj3)6GQ"kK5ZE,LE[9D)pfJU%I41G#bKFipeXpF+mDB -TTH2SH-q`#p#rCLmiV[+XY8)m6LFBi!ij%4I1m4-MG1+ZHCeCF!TH+X"VFCDJm`T -`qiL&1P-*-LYc$*e%dcec6(+k#[95(JcjAU3C"Udh`deA($qCm(!*SP2S9%f3!%- -a%Nq)TfPQK'Eb+Lh*YkILIaTK9S%3LC-m,9E5'4%kJeFdfiRjG2aRQ@*0XebLP@) -9cBl3l"fc&IXB'@Md8QNk!#ZL1@DLCiU5Xa8m9MRh5q*91M0#CqkBVA#6#2)b1XZ -!Zk"GiJCl#eej0Q'8KB5*CkZha$YdVTQJ#@DS2&Yar$`kAa-F6RQ'HPZmBmClCRa -bYS**+Ypl5laY#Ma6N!#FVG$bQZ)k+"jpa[PQR%L(9e"Hm4KJML1J*`-C*TQ610F -4$T!!pc'3!&a!f"6%V9EIKbVkSJKGp(2$D,U`[,Da[KRlMpTS',#qQ#l4a0SQ*0d -S0TSa*PmD+(fPBCmNJXdUA8VB`PaDRL,2j%S$!b9TS&)NJR#*,L-XL#jcK,94&TV -4G!9GkCR4Ia%@2&PC&,C4MU#Vk'T0F%KdmH&d$Fh6"+'4L`qPqE4!dra%I#"G5`X -e`9$9aI[6)VT1%l4#,Yk(VUFE0&fIL2HN'qNQ66FQiPhTCVT&%d3m,Ri3,DCE05e -1a$[3EA5l*LKMA,`Yh8&,0-'#e-9Ede+k8p254,`&h89hDi*maF@EdMedVbCS99a -m(lU2PQQ##lq,0k6lk3&08+#iH$ekN!!HdJ34LB[ASSGTZ5BS4Pam,hU%9QL#rX2 -&Up+Mp*LQ4a2a5[3i2D%*-JmAer3N2B9$)Zl6dr5-*JJdA,`#28XV06fEL#YkMTl -Ap&`m,LbYSKFdV8V%Ik)Ak590d&Ziq(Id-VfL#6D),[i9[8U[DASe%IqFAUFh0,h -Z#'UMf%4[4ZK0Q)jA(C3IbjY@2RT-,Z@A56LkJLNMdp8QmCQ*HBEYY8)M#AV0c4L -ILbrT,A1dTVK!!R%cbM1MiRQN1CU,H-@9r*AiPYk1d0[mAS)S[S5`aEPl%f4M6-R -IL4r08Cij#L@8a8DM9%K1q0j2`TJM2A0NmKkX1IQHK@"TT'IBLX[G@aRHJlY0UKR -K'6EQF[FJQZ*l&D4RMX![HFmCPE)[M4RZQq&rMm1`13A`N!"ICG*UFlJQb%Ni1q* -QQ'H'*B'(S&-6c&J"2*aXUY!l%AU((d(!`%2`9+kYL+1r`U&69GB`KhN'Diii1XY -GIA[*QQDSEiCZAdD%XLC2eT*ek9f$p3VX+MNAiQD`C`BRX4M#b5#SBLcUb3EdAS6 -H5f$4Vk"S!VIl4$J1&XDaJ)U+X@JS'jY"RKQ8a-*Cml,&LKRS'fIKpGY`$9dBip* -80UFe*NI6'TFAFC2YQH`N,MPFV01I`BFPLpC'D#d%1'PKMm6+iQK!jmCSY*ElQ`' -H'C!!410fGkqYE'rkHkCrmKl8I(b[JqaNqRQQAr)H*(emlb$Ca4cU'AEXF[FJ-H4 -lA@82dpFcIC2hS'$NHcePEp2(-qcFjHjGjqleNIe-Emq`MjHl"qGS[YGIjTK$2-1 -ZAZiHp*9mEk!FBRTjKMfqh,ejlYj3HEMTkCQHbAYXJShZ'5k2S2G0$dh[Zqj"h(6 -h6IGI*dCTi)k3!%TABV,Z4ZYS[@IB%-bY!YDj@NE+20TJZQVD%+i#`[J(42"KT!p -TSbBR!-+e8I44K$lL*8[h@&%Zh!E#)4qqJr5akD,TBjGRP"a0Qb+dL4eDX[R"#4L -'mH3CDESb%$!R0ChT%h1`CcSR4ra2A1Cm#2FrMG#RjCP6cF&F)Q5[p"PpVZQcF-% -R*mU6D$0pB3ibR64Y$TFmZ&0'Ap*AQVi-Khl%*p(AjN"0AiG$IaMrKVl9"!d2GeB -4G2XG2G-a1I4rkqj0P%@QJfFk*)Iq!jPQR'K)6T+Pp&f%[Y[4!jTJNJM4*-6[ap( -hQQ"lahdd98iclFR!pi[-3G`!H,m1dHIird!rDQ*"%-3hdb&EEfF1N!#Q(DH!'4I -4MrMr4&Xd352%"K26jDN8N!$4"#d3&cCGRQcDNS&lPbC6[M(BhcIlKeV6LG-53NL -%%MT)JXFB`IG$%e3r@0[*QA+Qf8p*DIE$RP9*'-EALr),95C2#YG*mGGf410Uc*B -Y@iC$(f3qq*05@X'*K*Ya*Vc#8Y3HTSeTV4Af[9MXSED,9DUUS"AH%m,019219QQ -USPCTMUjQ3XUHj4Yi(rdj6LRh'K4jQTbP[)MbrU'M89KEFheRbI19Vb*D366%pCd -&#AXVhl6kZclhI"4jYMa2kBM5ff9"#PjRf2I)Z6*3kD4J2+Sb9+C@'3leZI)q98P -90Le0#kdU1G6RbK[9RUU+9[!CBe6QbUY89990+c`,K9'C+bmccAh6I0ZBTZ!XaKK -F*Up8e50`VrYCjU6J6-Dec*1,9!fePeCi-3VA-Nr10r[kCYrYYHcPDTN[&kUD%99 -c"ji`(Q-bZ8AHT@UTfPT"+i64(r'PUSkUUe8G9pJYFV&TjTYQZjK%+kKpQ&%Abb@ -URSTU9FpP[P8Z-8epdc6dSLSX')eANS6RR*cZ'Uq2#A0!H@fDq+E*AkqaJQST`@R -lq'DIIh'DiGG%Q4E-5""XUIUUJ9EeAAmZNfqVKQT[dpJddJV#)Zl2CI*Ce8JeeJU -1B0a6bq6$DKr94#Xm1BA"@3BemYkqfAYl6cQ0NEaI2U5D4P66VCT#V5"%iMT@b#G -9-i9AAcQc,X3I03epdh"l(IZk1Kk96kMQ%G9m4frZlAVcHIQkDU&DDJ@&%IIQmr* -9KGFkDGA+&IDmA'8Dq+E"lYl-FVfj5VkL@UXf@N&ca*PIN!#[Q2UqU5mmejX-)HT -Zifk[NLqBU'pJZlDl+lF+P1VjTYlZVS60R$4X-kIJ++Ef-b#Ar9aAVJDClUrDQMS -'"!4*$(IPD[QT1N#edqS!edfVj9V9ARA3#X)M"JHkA&2,0l9f[C(,1B2*Gq3De6' -L1[iX!P$3-h&Ckq9(kN$955YiJR&Ckq8'8p-h-&rE@4CN4ec@"VP4(444"qeS@)L -QZ'%hbar8`DUc9V!+iiEG,,p6A94AVEUi)U&+0A[jCUrG$3Y6-@lB,q5hUTX#8F, -kLc0r+Eme0Aa6)i5RG&bF6K("!"35DRHAj`[jTDRZ'dKHGlGZjr,@VHDEDVYEY`k -hEQfH@1[b!5mDN`C6-HBpr(ZSRPVKL5fB(JQIUDTk531rViMU&DTdYNk2S4JK'KI -ZZlN4,QMU%09E+b`r`!8Si$l94r8e9FbHQTI3i!,Ff9-GU[TTKHNI6BYi"G9I$G$ -+HB8KVNaPhe6qHkjciL@-UDNU1k+bIjDm+,c9KB[c+%2PU)&DiB8YA"`8UDB5IRm -A0p!9je1k'K5"8q*fAS$`#X3+6HGGDM!T+*V8%$98Ub%1mQV86KfQKTP-Nk%9A-- -BmQUdMcTF$GF`H3P4U8Dee"&UK&C`#@08UP&eNqiE,,kf$K0i%JTM8*eUUT%40A, -l8!+h-DkM,M984kUMY$V5e3(&TY'qdG[V1-V98BmDU&%40@S(PT!!'S$MU"RYTij -@-DfJK!,()GjDM9Dj@N(Ya)8eShe0a$I1%qjr1!kL-A!Fl8YC+NrPDjAR-MHR,12 -laKI4,$al+&5APA+E-T6aH0LfL'[PRQ@#'TSEccIHAh`AefJaheAd6FAGI)GRP8N -$cca53r%ISmCU"E89pM,8(ZV(0&0"'MM,531EE&+3!%UTF5C9Uh'ZRGZMb`[8H,1 -(5G'U`,9cHqUM*UK#VG#0h)EYk5!e849TjGkrJRJ(ShbMYVHKHrF+GD"1UMLL`UH -YE0m"!!qZT3[e9*28-9T0FV9dSDi'R)AR-ffY"G)TVU8Vp9!P%9@bSkAKk-hde)r -Z8+@N3)HU6%h@UXcKfBmQULPUUS&LA129D#'HrHK)GDbDTKAmL"L$IM43(DH1emU -j'5(H2l"qB(H08FFl22T6MMSKSNliC6U$GSI,'N,$eBRU*+fFr42L3`2M"fCA@AK -B#TFeP!jAdb0UqJkBRIm8(8d&DSBk@H19C5&c(8eMe5RU9(kGA9MNd43,!Mm)GM- -AT%l-A$%DNhM(ACKj0)eallB,Q5Z%*'3ZRY(LmC!!ZF**$5STcJReB2#6(rcd&h2 -"R5V1A-'2I[$MEZCL'cqBqU'&mDLAa+2b`MBZSR29,$8lq#(iAZ2*H-Q(k-e4CfU -&e`BN(U*hPMTEUl2+(k,hR4pmYk[IcLjrL0ij%AA1,`r41l2m)AVRU[1dFLC3L%m -0[[@$EhH9"38@Pc@9MP2R4p6j1pSBANrFaUI3QHS#GD&@&lJf2S9QUi[8a9VKG5P -F*24U`6Gqm-hZ0SCBLY[i9*UP,P'ADJ9R*mimNfB&Ar["elm-)+k0b`H3!,#0RAN -8DTJCI18(H$l5lMBZeh%&ArV"PrpUi`$@G6*J%cXmpBr8h1!,VHDk0Mi2*(fCZMc -B((bZ&3bQZ)h2SrRU#R@P9Y"KFEqG4aHVUp69@X%2LX'"ULhic!mqqe8'S*AcL+, -ck5*e684GXeA3Tp@9VTUjG*@DTqCV"I%"9c1A,JXqpB02reN0$+5iQX[S5V8JSKE -Xk&ZXklP[&p*LGDeDU*86I5&qXeUNVY2+[Bm&m8A"*hl`bHkqKHm6pqdLZNPGVfl -3#PC5R2NkZLRBj!HER%emV#aXfM!5YUY@cPm+HDm,2[D$MrrUeILEAVKA2r+$MhE -h+YlA*)2289F!NcibF2q6"Yk2C0JUe-"+94UiYj+#a&[GU'l5#ZSe(L@AdE*JBr# -K$$Cb!4pb#VcI4GfXEY%+$hH"FJ!T(P#,YA+H9)MH(hcJ"arm#`Ye#`Ui0GLJ&9l -I`M8q5!m'ki0e-X"6NQ6!MdS+0Z!Jld@Hfi,hYB)b,Zjb&+`0eXJ!jQXb`(2`+)! -$@kEi8D3'lkREe4eUL9UUlT3"(ZU@U@iA+F'l`6["kZ"Y2h![6rV62Fi2h[Rh@`Q -#eArl32V"frqA'e5kZJ22%`MH%MCi-hK$hDAZ$Plh%Iih4ZN"2)"5JYI825Ti$Bm -882G!FakmkJH[rQ'N'1$j5CRU,U'#9i+AJjImi*@GQIcJj9dQYRl`dMmpQM29hA# -Vf4#m',`3V!UH$ji,9JE2"Xr)9M)VH&Uf#Ck5l@A(i%RC+AJLH$ai,(K8(P)KH0% -CGA["#iPh"35ViJk4A[$mRbm-#2JC4hmiM(["bYhQiAl`l$raSq!Cq%J'r!)M&Qe -j`90aFC%A2"PApkMJ#85#ahI,5VhJXEMDaJ[i$8@XakN8[#i+*X$Q(km!1+U+U,Z -fU0RlmpBejXF!T)3fqhZ%Tp6LBD,ciIc'YBrQ0IUidE10&Z$rE+02'RhkfHH&8f$ -e$hYr12Y(a*lCSd59Q+J+MrpUH!T&f[LHG``AHa6d['0Sp[b-M(5eK-PNK4`F2") -X9rHUqi+(r@$&[adl!cc8L!,iK@8UU0q#KrcJSCh8N!#Ti(SQ4`82"Jpi!6YrrH( -Dk`82a2f!+`82L`bJlcF&c[,pjMe[ajX#e&,'kAkC(b`,lP2,e2h"[Aj`rpq8QKl -J-6XT`6hU!4@!lG)9e(iLZ0X2l[l6@M@!#eHQ@SDji+lJcQ"TX#5i)lMG$qlDRG- -2lYa&M8YhZZ6j`C+rE1rmi)jG"RTqF2XZkm*-GEp)#fi,EJd@"lF%0`Fh"6F'0rM -"EArhY"IFQRL%4E$iEpFm,q#(#i@2D`KZMKZ*HJ'l4B92E`KZh2hJ"Mqii6qM5UA -JAP(!,lX3DaZ$#9IJY3[c4U`E1H+)&512Q,HqHCZH5r(kK@lAMYL`$LpG5!eIZY" -XrN*q`N8&['*KdAM`R,qJjd[Cic1'LfU,#MJm!H%#K#XXQ&$A[@PKC6EIQF!FH#G -cbr9b@A"GX%JpU"i+&[V"pIrh-"CJ8Nm*VP82U`#ZN!$T#UmH%X%#2eM`Tc9IX)J -CjN%`c2aJAR"0F(9`9A#P(mcIRG-2j[feR[H$EFC2IR$ecXf6(ecekeE$$klF0A" -RUSIJh[j8F!@d-Lr*9i,,j@["CF(Fi0,J%VP4IJkjaYIb@i+e9(!a9D8kY$IY3df -aV1k!*@ehkNQ(8!lPdRLD5+9BLTf)cG-C0*[1T)[ScH!LHMZiN!$HSIGS,Ae%QqK -6qNjjd0G99c@$#e46e6`iAh98"`ARU@`e5)e8Si*c9E%U85HSkF%jkKaeIR#fZNB -Y#-lbJLZ5ipIPbI',ACU#ZAq0AjFQabrf4q,ab`XZjNKa-@MXSZ4dGf&FKZS(&ra -6j18(f0pYP4IjJA-aqSGka3r1rHr1h`r1qHpqe3r1rZrkcJr1fVNXUK3XT)IAV(e -rhIU*mGGPC$rp-Em[Bp2D6clp$(Fq6pjCNVd!%bAl*Z--Ph*4ZA%GdAFqASd"DQf -!Kf'XaB#*q6)QUL0[604)CPikA05,LEe`[fC-e)U*fZ(p1Y[Z9iL*ZL"d9&B2ZlR -UU#V+PH*F2kb8rlL(GfSdi(Xi0dcH#k[I'p8eLJPFf#HXVNQbZM[$kTVf[$-l*TU -0%[XfiRp-0-HjaDrrqI(E,F2SJRLd94Lp0Kl0qMhcErq&MB"+kjKS8mL3!1bAJ#5 -'p`rb%$i&SiJDKkGmB&i"dQhML"m3lkhak)CfmAjV(lq6[QKH6(4ShUMRA@&Uh1` -Bch$JYJbGNKR3+5cHiSijH&Z'cSN-B4C8h59HIGGiPS@SU9ZmYZlE-[IB9MdE4A' -'AJR-8#FE3('p[EGPlE-0NEla$)GZbp![Q@&K$+p$3!DF"fc,N!#p$E-`dk+-l"` -m0H3c)DZSjHPUZB"+p*(J6,8LA6h#X8H$1HUaG!Ald4VUm@#fHL*G`A1L+PB4Xlb -!hl*8QPFk`3[BbLTh6(&K4$d"C[0lj%r*,bbH0$%INcUrU5LBNlcr''[`%frDG*I -26&jH`ES![+@(h`N8[J@#,B!XhTSVl93m+!%c0qE#b)r[[SXhCHeiS#qH-Y'q'Xa -M4@h%-NYc5q%E*1E`)f0a[S3I!i[cJL%p$aq#a,H@PNhMlG36TC0+-HD*PlTRpqL -*Hqpf'p#$c@ZrGBq"PH3H!b[6h90JCFf#h%)m!%3faU$!m6BiFrcJFGLmi0ahF*m -Mm+3NHGL`R')m3!#ZpU%9I[bEBI(m'2K`af-`)'dKahHTR6)Zc!'(2,L@cqCB+Pj -M#'[6m"jFBT1@qR!AMFHJKXA@&4mHeJQc3#2((cM%e35*Hc)I4-I*@U%TjZq5-1B -`#'-TH&P()TED'(KdLXI')lEr4mXj9J(VkX6MIY1JC%VL"qfH%2mr$3d@F("MT8& -`F'aP8f0bDA"d8fK-D@)ZZ3#3#4DG!*!3XKN!!2[B!!![#rq3"%e08&*$9dP&!3# -Y,$I#X!1PI3!!-Tm!!!I`!!!+Y3!!![&bjHld!*!'*a%0`09PJeCQCLEhj1EKYlU -P$G`VNe0ZENC@`XKQALXl1Ee1Q@jkPXI2+hCiDRK16hEV`)fr+Rr6IFb18,+2pB6 -YSi6(kYLPC'[NpKZjcFKa5TjYFPZ6E%)j*C[`Fa2Z&8[##0X5IK&11$QfcpKqYQQ -hIA)mYXNqXJ*IA9Hff@D%RlIerGEfXD)4&VQYK'ebQffb*Fr#N`e-m!,KJHfm(S! -"`,3P!!lm@Pc4+&LAlm9I!(j(f)T8JU+c1IC*J'a&mAfR@&%#FT92p5Z4UXCbIjh -MU8B"XhJN0D+rUXUmRq!FhSQ1QdS,GD6`-E$L%c1YLq*lY2jARTfi"T!!#@,$1ED -4X"E'X8l#MRXiGSJRG")@[)9MAq6BE*ilK@2e(%[Pf'UH)m5alEbZVq"$!"ZqdX" -+R@"%,Qq,[iF0"%aN3D30Arr-f4F#XNJc!@""3E@B6kmNb4&ZiYhdYbLL"c8L2Ba -h0@YMUF)A6ZCa3-S*ETI#ILT6!GJBB2FC%Bdb#S,'kdq+,9X!CU2Jc)lbAkL'U6C -h1#6j`ReF8f!5T,%ZS5AqIUFKX,m)L8!5liXeIX8NS0G-61+H-Smi[hK4-Ae(Z1@ -)'VjI9PGSiRaTT54@h9ST6QB&(GpM"IF999H)PD@0N!!V9Y&V6Yk%@F!@2SAL[LG -M`RaS%+XVN!"1&MEK-qa0BBc&#@[!F[0Qr'FXIR0)3DR[!GCbGHKp*HHL(Uh#$&D -i&aKc6XpP"3r[BZVAMd(1kcrRHSQYcG4(-Q$dSjd`lZPGMG'hLjLk#ANGfJ#MYlG -M[Xf)&d"fd`kQE[Nfe`$eNHbi-ULEpY$rP!HbINe958@mL2K%$hbY(GjJ5hNeK#G -I-[+MIU"qlIjY!2-d'[RE5N'`3YB[IiJXL&-EVdI@VhD`4NLVhJ2V#Ip*#e0MFK[ -GqreAfC6RZDTL2R)fGPD`YjN9l-0D[,#-6FXX!*M`$D0H)U6Q&l&ZB+R1"MNNUhk -IFcqj'iZNV4$a25jHcfj[0ZZZYZ)hrJr!ilG#qKp-+P3QLQ(BN!!6p@[I4I@,e9$ -(f`rJGcGE!Lc*'C4mcYVYV(#V!U0',BRV3'&l'f5Z2`Dh6$R#GD"`D`Z-bNL"l1I -q"%GV0b$H!CRE@eRKilQF9f%llbm$+qIrBal)(YR)GD"`DbIa1Dd$H[iH(5MFHPM -2hjl"G5"lq!CN3C`bH$fb4l55$[bd'4iNr%AmXeF(i$Il-4[24ieJKqkh0m#aJp1 -KqhJq("hEJCB8r6RrIaZN3LGV"H%QTe[b995*98f+%PBMcP*CUTG9c3R$(j[1@XF -6(mDk[!AXSBRB)b9,f&FA&L(ZB9e,UADN1`,Lbf$iPME@+SU)[B4I4FHR[-@8CIQ -%8rlSJ3FfXBfrhiaih&QaVQVk[if$Q4Yh)ci,m@f8AmHAjL,HSI-CXpR)hdPmm%h -j+2ma2Im$Ka&[jMM2rp![M2aaA+pR0A!qbV+Ce!0M6r8!6L085IA,QY-dT3G3#e1 -F[R"3N5*1-aFYC*P1TcZXbLAqJ+b*YcZQ1qj`QUcS!-#BCm'@SBZKaq-5brfK&6* -CcC140*JK%6R&(Nrjaij['AjTL'J1`-2Y,Tq6b*11YN!X#j*$S0+IbH(fP*HB"2# -SFFde"kKVC9AP@B)Im[$1Ur9D((@02NhV!(Dm&Ha12K2PND+m48rl(#N3#)G$BUN -FL)h%f!pqa0@)q4E6G)(c%"bqIVjfGihSQZDD1[9FGqJmV!lIe+QQ!$`X$Ppr36l -Jd6m*r+#Z5Kq4+ccN9FUd089k[clj'VNhJI#XPj(%kZe3+DrK-p18ZhJ[ilrlm+X -)djT&GZ3JGe*k[j*aqemp-Z)m"JDP`j'(4p*m8Z"mBI@k+T*Q&X$$eeIC4&h*YK% -2'r'iS%5AH3L1!4pPSAkp'$S2V9qRE9L'BLh)G6VfkepeZYC9-HKM-LK*bB#6U3r -lQK)m%N(q3pA8!G-`a%0V$03PmU4ljPfX+[+)0*N%m+#`1V",2UUVKhT4Gq3cCLi -`Eh(N@2Sc1DikmR-m6!-FHF@Fq9aKqq[KpY3NkQ(fiHcIUqT9Ccr!iiUc(q3aj1` -(kcVNl"-m,MTl#X2CXd-r+c!$F2CRkr&[ChqZX"mkq`52)@GrPXBeCcr!)q(XEFJ -MBHleZQTb`ifq0rp`j$0QVML6ikSMIim(K8Q!)kraKqiS&&I0R((GNDIqbe%KdAl -PZ1bS"RKFF8+$p4Kb3JNHPjAq,)pV5Mr!`q)B8-88j)(#-'MGVBk![dr1HLF@jcZ -%H)6VP[IaU+KERZ#4k[l[QNHmk'jAkIAFTcXqSBJT@#hHU4GjS!)&qVcQ51)4N!! -d6A6KAK4Z"*fUIUcMd5[)pjN#e29Mcp(Ma3Fmr@8H#@90p&Q2)NEkfZcp'-CAK6r -5S(3qh96HA)K6Uh06VRHMCmV9)-DRQkB!2&`"6308)05AFcb5d5[``PqBdr1TT#P -!2IJdd45!4fbDf-IMmM3abG%B#3E+fh3HApk('bV*3LhLfCm[%%EHZ`pbK$YIQ96 -H+BJ(Am18Be#lAXIr1i8lAp`KM&b(@mma(XZaLmlAie+I'9-F[h+KAfNr)m'$GZ' -"6JEFk(Xqa6%&k&Fqa6%&i%&K-`A3-`UV+8"r8$PLGb1%PCGZ694VXKU5J[*eLi) --'6d%jVc1`$3NU"(-AhSJ(YQ3!"56RKi*iJMZ9[01dG&d5%D%IicrRiANIeaGZ4L -c-I5p(YC5HrU@bAria-&hVlXJcp0*Cq*fY9&@A&)bcJX-$5RXB1((AB`$,qaPIEr -lP0kB!-A5T9U%RedbF`KUibb`#)BXRZaUdXSHXI`af,V!k`ZJQ*5&r"'r&2#[N8Y -8U5%SKkk8m%E&GIjH@3hk3e,N'RfXCRD23qf0N4&Ii-4TV0XGI)jKXK)l8HAC+'` -aLIT!ihf!1kf"1ScH$LbrY$YL3K$XK!XkHq'+lN-*r29q#(E-jH(M!m-1QVY%9Tk -VBZkm2$&[EV'h'*qH-TFhcfbP"Hck&C4Br1@f(Q[ZpRcU-2ibMR@"S#cL%r%F4F8 -PK2&`@j@hFL*QI,3h[l@$$rAT2KeBR`#kFCG&@0+$N!#2ceQ%TI`CI6S!hj49fS$ -@8h#P$1",D`&[EV&*K$AA!&jVBIF39[KG`%0UM+q@&$d(+a(l&Q(H-N!eC'm3GTX -#H$(&`R2-q!Tm%l(e2-IRi!R%Y[&ZI`&fS-(E6GLB)$`0-2&K`Zj1!raRBMYK#jk -(rFL'ApT+fJQ[)XBpdH3S(%AX-i60fJ"r4)`@Vf$#@SDecXXKV(3R`iZ!HBYi@ae -NH+8PMbpVI2Bi`m@&bAbM9eh(2SdB[`D6XirKTXTNAV19M&8"61&h"Y@lf@+!UAa -$H[%cV!%JRerBbfc'1h#3!-pl#(E6"5S(ch&c#f(X#'%M2'TiZHb,L0LVQMmFXXG -`YercTI0YS2L1b6$D&h1&kq@lj&"DcqiBrme)1m,BJ)bPM1%eNKVbKaSdflakIb5 -X@N[#SBLGcdQ0a1Nah[0@494*'q&UdL,KS,K!ARer@+hAl-8qRicV,KiTdUMC[*, -D)%IXFjVmJASMBHSL&jj)NL00bM$D-cHUP%(BA,q'Nemj@)Ie51YC3ZGjBZcepDP -Be3`iAM4AL4Z6$D16-M&LK*dNeR0[*TNJA1EMq3b#G[fX!GB[*!IX1)Z2Frdr#X" -ep*@YdXjV3#LC82)VB8H1NT@4CbYCbB345KLK%EBH1HD4Sq6`-I&-I15BC,LH$-p -12#0iHTSIS4HK&lQ9N@2NQ'6%*-q1M#QC8d*PC,D5#5-d-Q,Nf40'MT%"*30'MT& -Mj#PKj"QC-A+-(*-F"6km9eeQK*'M(D%RSB6L'@%%4B``!!)F8%ib+a8(!"M1IS$ -%!ja,L1Ni1h"qJ8l)JJ4TGAM@VAK"5V2pB(0pU2q**&9a$q$L-`eNr%G2iRapaU4 -QPe0QjDD9'NKjPPqTHDEP!r49Xpri*-'R&Nd(aC@pNRIh(EjY4GqIi1XZh""dYZA -rjHX+6'I-b#q#p2`&,P9$rlU%IiNG2iJc6CP!PMEIT6F!2HH)MLAC)jD8(*cc11m -a&6%9-F9IjDVB)R`qY3"*1)0JRVh&$D@kb*5!VjpGb0*qVf&2ZBk9SLJJpr[cZeC -H`CIAG3hCkha#$Q"#D2bR`@1NA'"CDC3Yb808')-R!5jm3!$c,#ZJ`NMB*,6+Xa3 -Lac&jKC+*iFYBXfjEC9,mZ3S+eVD+(Uj#0%6'h&I4'DQ3!0G44DYTZ!TUQF&-0Z0 -21Z9$airYU+!Qh&Ca)ZpL6!h6Xpd!$6P3%IA+RSVHXI)Gb`b-QN[&fYDKr&B4rVT -(T`2,Ze8bV8-RH-2[Hj%SP!,Ukcp0%+AbPk0KjirATJ0lbXUdj85mHbU`fB@%)d1 -LE21qL(,240+h@ZHJ+qK4Trp8%IA&PJV[8)8DUFq&VX5TA,Rq1XIZqd'Y6!K)R$9 -1i5kV,,3Hj@APBl2*kY4iK%!(CifcLP`09LrSfJJKQ)X`TA%,0aihUkaH(*iS%S, -C#PRM,$CH[I`U@"'""(FSEYRPZB&9lLXKS!KIMeTefEmFX5+#24mf@R`A2*8IVR& -@3["5#Af0,aYdFk2Pk`Cfa)mdl(8+*QHQPD%C0RGk!GX)fdP@G-d2$dBfrfN0$je -VZ$HZMcKi9,GDkbTpG-1k[ERC@X+lANV6$Yd!r`%!!!f3!h"`Bk9-D@*bBA*j,VP -`G&0S6'PL,VN!N!QCLJ#3%1h#!!%0rJ!!,`[rN!4069"53eG*43%!V5`hTE!Bb43 -!!$#J!!!MA!!!#H%!!!I9lB`j4J#3"TI&$F$9*A0J!dk6dfkccm0[YHJJ@cIPY#- -X5PCZK2NbMp02QA)kb-JqYSmHRKUHkAAQEr`92q@a66MG6lH%ZaPKYqNQq`L2AG& -Y,2+mJG&0119N5flV2R+F8%)**fc66BiIf5`*)ca'H-r)*V`Ra`R[fAGNNp[(pNP -Z"EjUX0PY@K(ZE@Qh*P[EANH2X-KY*E`4fB`m2ccC`1X*"+$Af3-`!&Me3B"Lr$I -BJN%`GMq&6`"q49K2#N("p4aE!C!!l[Fl(kahGbL5dQmj)1"EZph4D'ZYV@)3a2J -6IMDq8Ac6J`$,Y`+8l!FM2RJ[`-FSclADqh`cFI8%1*E1XGf%$6#1M4&fbX'aRr+ -%9X*kVq2B4cQfRZG1jPJRae)ieXpcH$Nf`RAp)Ai)B-+[9+j&12*i@I`P6#"J)J- -L3rMeYjba%*!!4DS1!)Y`e*%L5C,&emHVkFp46KpFI2`)IEH`)CBLI14-RK)`88f -(i@#3!&%3Y$3Ur,jp!1ZaAD`2mMHN3)V*l[0+6Pp-+5-83#SE&`BLhj2"f9#l!9J -,jY12CS0bTBFB40i%))NAb*eZ[ij!dHQ8a2YV(@*GaHB+qXqdb`(&GiHXp+KLRA5 -l*$CGhbJ@XT,4Vl+5EH8Y$@*MM3[ba#EkUXaIYJlBTJ2BjCr-@PB(A@*,!p,*`A* -8f10#R[!5X610![3Z3f!4Y9*U)3"hm8CcqLYT#EB*"l9)GKaBLV9,pXU+ffNp6#h -H)+Np)Ri[LG6fmHCFGVc&L2q40`!2A!mC[p@TU,#cCNR6lri*dLqXSBEIrbMq2m' -f!NZbpNT1DiZ(PAl"$r2REqAQ!4XG+adHJZb2Ri6VLRlT#[kQ(0m2`2bXC-MplXY -`SU8'm9()(KPNT3rNF9kP`rG'H*F1er2hQ!GbVh(KNa6%aiK2m-LRKq%PeXBV8RM -iD#JrpP$8Eq)AT-2c@[lKV"S3M*!!Qhi2XL"1@9b2h-a"jS,8lqq!6a(q0,l%e0a -c"*rkqM&iiI!p)3h)P*MKj0'pF2a8!Ik2`BRhB*I)3p[)hqq(&"KMJb!XX0SPCd1 -6f06RprZ8J,9'PMTP4E9#qTI@X-'Pa)HamHB5YQXjeNMe9VCR8cRL$MEH4YSPilq -!H$ZNlaYLJk+)f&(mpfYidDrCRSd[%dljJdGfISlYIR%[iK'$`XCELK%IiQ$flJR -%eb'qRr*VH&XHiU-DRi9l3rR(L!pq8cl+Ie,,[r0ja(G`R1IIpE03rJLZkGQ#CJE -jq0[,U!mN@jfqAVm8X1Ujp!'@EEADIBTFlIE)URLMCBePY99RT3m!,$`)TLbY'6S -F0V(HlHf4PE-f)fNQ3b)@96JFpHqkRAEmVr$l2IS!21cfqXT%RJ`F@BQe[H3352T -c1Hb1qQUG!"kYYJhk!,Sf0M@H*rJ@MqDU,Fd'5iI,UDSP`%i0JVNZ1Jj+ISKMjNV -*ir(j['+0l!Q23YLpph')06h$ZaVa%#c1DEjQHkYSHjpYjFUTkY"i'#h1P5Ye!AJ -B,-jT3GlN-6d"HP0AIic)C4lbG[qKE`eSpIV`6lKl)ccR@5642`+0mTeml*Cm+ap -`XN12CH(l8AES3$[E-hp0Y&l*Z2e2Mk`)MrL!,"ej1#69+ANZ#+[TkTG8[3!HcTL -b#9h*YK%2%r'if)RQH!L@Z)mb)3mUf9KS206T2Qe#'5V8AYkR`dr2pZNYYSBC(j0 -&5DVM6UE6jqa,m%J%q3p&9H+QBCD(k[*d*2*N1+SZUBSm!Rdk!6`SM"DXNUZk1UJ -@08HqYQbMISXM4qR2jEMLb+Gik!BimSE+1TSaar@`1eS6HZKp12[A9,hLl1-m,M[ -l'4kccRj'eePRRq"abGP6K*`pqf41Zak!Xcq[acqFrC5`EcRl")pCChqHaY[12Xj -$2m$C'bfUh291hHYr12+eC6hRFPaaj+raS0!*F15YEZrU8R&lfGVr12+8[cXU*$V -G1HBF9Cc(C5FdSmHX%dV`Q1[djhQmhHRM2!b@H&G-4KlB''DXZp(LFFIDfHQ*aB8 -+)4kqMZiBMiD1lJ52&2Yrec`LSYYYZ,QM"a"[G-4N9)YAkL8Hf)%m-Dpj$I(`5+S -UfR![#MH#*Y829cak"AQE,S#ZlhU1U"H2HrSj(SR1QULcD%F-a-VXVj('9d5[pU! --2Yf8[)rMe'TUb[9U4+GFc`e&TTZk!$aX(P8&l%$BAkCic%1[`)@r1+IR8dPG!$h -i0&%AJ%GiQKMM-6G06,+i!VfH4a`DMlX2iHZlf3m3cre`#4XDpi19MI6A2$,!pYp --c@BK3+BAh`q`%Hm40[4cc"IQdBe9G%'20qSX0-9aqbr@U`&(1!NHY!-0Y#Vq6Yh -c+BiZ3,hb+BiZ!!m+Nbj!2k-`kJ,8"mN4AZdAERppb6qY8HSAkh`ZVqVcrY0K)%0 -'(`+crXZKk)J%&B,q5`e%)KH5`UdRfS)iJV[9[&)d0!2Q)F,r3Zm2`VcAcfjFL[8 -BfPi2'pMbbMQ-Ir1*J+qHpd#HVb3Y`qeU6GC-HfYEXp1MEGI(0U)LBDD$+,`ZH&' -`CmmF@*QX+cfID'Y6!j*bYG(S!359F3iBK&"E2&29e#ZMcI)*-)hVJLM1F[R*)(f -Dq$CfH8-D1S99D"*S%&k!hi@65FL,R2%M1JU&q`I@LP$1RM1X*ZLE1$aI3*Yp&Ri -J5*Jm%h3a"$2Q`LPAk+Il%MRjYSB09IPLrSD+jJVmG06DQ[2e9NV!V&e"#FFIMkX -*"EI9&*,,AX,'3I"[jK2a4Ai&Pa#@`Je0cBh,-H0pTr-E4rP3RlZ06C9!4mjb#0Y -@"FAiZBi`ef2Sd`(iTUaT*j!!0FH9-Y`$E`5mYF3+#-Yq'MBMaUqQp0`&(d!-VkM -Je5@%%AZ"X-`A!5F#l2H%hA`-m'++J8rr&hm#2SrB,X*@ZH%VL(f0X-+$m#J1pVj -(f2)I`AI`aY0R#8Yq%LB3qb*Kk4)FaQXY#lKQAiCML0e)Q,X!6L$'Hr%Y4q&hL0h -'H43ae(V&BX)bFKLHK&[45TMXCALPC88AB6A$$"FAmUZiPM[B6BKKGH%@fBmCEUV -Nmp@`['GB%d!"lqkf$c(8Zp"1f!fIBFLK+)hA9LhHri+L@hLK6G$eT@+HBr%!BH` -KAK-1aGFY1`-LeUVUpRR0BGcZ9TdCI"XSXQ154[YL0PqRI+[X6BhZM[&RSE5QUNj -h`+FBUhhH3'CS'c+F2Sbh5SVAlHe5cAa1'NUF%HCGY6fJ5'UQV8m0q(V&MA,r(6k -P8c9A1*dbVVXiT)",069,5TFF-&IfZ6fGSB3TQfei)NN1p2R6D-mmT&)@B4[F+Nj -qjGi1e#!eZS61mi6CDqY6BD9#F&JSNkhDMXR5k+4-Q"KKCiK&lmh-)`LAqALq%%' -cGYB!pI2+(M21iL0Fr`m0!&6@1I#bXlbm6%[lcLLR[CfGr1cYG@)$`ZQPl$aq4YL -4jq,jHY,(-hdMq+G(9NB'R,!M!hk%Nc%MamNa-QEN@13BBIM)J"pKj$NjrS4&'1' -%%hlN+1(N@8rBNHFHi9j('''%2@&(RK&'f*&M3!#GZE)e6[Q4ij36KQFV!&AAC`4 -*()!T-"jSd(NXUZYa3NJ&rYB5XZB')@[RBaE"hbI`pc[mfNa#T(j*a&#MHL+Pa68 -e9YHY+M(9-(H&$J,MVaF#(L(eFrU8D0eJ0'k1e!fNe+JfT%8*QFF`+Kr!-EbU,M@ -T'TU$b6pHbRi[Qm+$(X[kG%2Ye1+UZD'Z(ESS9YdkB+FqUQhjQ'c+iP@%(%h+H"p -H*@6f83V(hba#&MH3!%lmS`kK(Z'8#+RTfr-qa(+Yd*L+M[aM"IDDf@qA"5FBF[K -8@p%iV0)DMq[44PM%Ibp2XkK`@Fah@E52+-NC%Q50d+,+C4&1MKG)N!$&3J['SQ2 -RlS"&5eR4c[C%V%$MPFFXi2X##qbq4lkSF9Rd*#h9'%YCMjLX+f[4Np6b$(*EEeS -,aL+FPLbf#"B,A"BlG8XE1LKiV#V[VSL5e!UlUd(iJVPVYfVUBdBdlp0AbqiDd+1 -M"9qm@(EAS*B)pXA+XKE[*,9dJF@Lab`X,9jJm95C4DqZ"([dT8N@Z(ab[TKVU-0 -U1K8XG!IjAaC-LdTS86Tdm-*##iH&H6"CC1%j`GHL66'$aBARi8kcS,G1QjC8M*N -PLYFU&+8HE4p95XkSNBUfJd+`r`KjVXJL%@[YPLaS1L"Cp24+&Nq@@I6YP5aQ&ph -P*"I"6Rp0X+#h$Q846UH-'4T[#4Ec`+*$X3)Km0B+&R2"SR5Nibf8lJU2UmRJMXb -Q,p-XU,[#D68k*N9pAE#J[LLGqRME"![U8AVUle5#mffjG&HA@R3&)A1NdlX9Fk4 -)BklFAGfDDHRb`2#50GmA2FQBQZlri-!-M4f#"EeeR!K%RS&,")XjP%9rb9cN@H% -,4i[qdQP-RTFEX+Hr[(C@5+IhDXRLfF966prT[A#kY#MCAY5LH1VM25eCp#PD%#A -LeFYp36Ha+IG&Zh4k+DE#HdCS3AGkd9Rd[5'dS2XLSKKQmAbV%LbS&T(4iC)@GB) -&hHQ)j%h9'#r)X9Sk2@+8!KP#1`%&,A465`pBKG[i"F'#CT)JS#@(!kHq+Ca128V -MZi)3H'h5&qAV!Y*,TlqV&*@!p*-X['5&T@R9#63AKQKcS6'Q#bTETeN`AbcXd&$ -JS)GNZji5Zl4*X+LNjh9!`(Qddq'cU1SF5,NGM)$'q[pmi@Na&XFkYSSRpSBC,AJ -[*+#a8E#SS5`k9(28dP0p`hR(G`J@LlJ@iE4P+)m8D43XUNh,5%B98idQ#THAej, -jQiAcXa)XKUaL$ZkLZl[+!CC*XAhNm`X9K`I$l`h5#6!G9*RT!ZXL4lf)2FY44BD -E#@hjc8@P%bM-88A##Dcc(28m%XSFUTpSCQD0IFP3-8%LQ82e%dclMfpf-&da3D, -NHLK)S1aMjfi`9%b3!#!jU$*aJR1ZF3pG3f,NS-U%#3a[FUihN@&`VL,c!%-2&42 -F`p`0iRi'`eZFkbhFR*bVZ&(YXfIICULBi#,MU1+#XqpHk@+SQ1!#imi6&aZmICU -lr$6b9BiUmPMlXjqqCP`a3BV2R5G5IcMR%[I3*A4&R1Y5GN[X)kIfH+LRpU!E-SR -kd"#C821iYr1Dap([FP"P(``-ph'Zqj!!qcQkbT`3IXY`jf@3!%4P0dSqZF)Z[X+ -hmK9dT(+kqTdUU"RMZXD3!'6c2555Er[iS9mU$MN+BB*NLHXUNLKlSUH"S@+#M0P -"PCQdIHam082&"+QRJbT68QbI8biUR5#Ij,U+2"21ZFT3-8(R,HFK[b0RRrej"9- -)%c5IFUKq8mVqpC16$"86G%kbpe#qSf,rq%-V3m8%l61(UfbVf41*kjlc%YH4Qr' -Y,()fq'd"Gpi#j'6FVb*AXipmXBUKBS)qCFi0I[m5'f'#liB*Y$[icK0Y%$"FbVN -Z4CDGhDrjl"YBUcRUDQ4Z@9hc'4f`DMPU,CU-MUkbqBLp2q5KRKT#YblR"Vq,Kee -XH(ZSf8#+c0dJ8QISXT)VY"*pY4aArh5!,[Zj3[[44(43CA-4@(XjkPkb[X9*4f4 -ZGI+RULiAP8l)"KG9jP46U"XCeb#AQN*YG&&PJM5&ZUR&G813!"M"!mZj'jD6cCk -ZK5a`LQZ6LbTcb#R8,C-ZpeZ[d18!9qJ!NP"Aeb!jYBqIX,`lli5&RVDlmi*HGbD -dlEDh[EEG4LmlYe(mHL-fRFjhRSl@mZ6YpI"QXimIcRJ+(FkJrF3hT@K,)6fjked -fjqkL0j[EjAl2eVjhiAH'LJRDF0Q8)YqH`b9jKpq8Gp$biULL&3DX2cRURqLdF&6 -4JE'r[rB98`J6G$AiR5FD!dM@ZKNU*QJ21+LbE3"GlR'&lU(9akmSd3+%,QHi3QI -3Tq+SSRq&HkD*AcC0k-ARdKHr4ip0PqBl,if'+Em145-e%pT+2&e4''M,hZ@L0B% -Fj$*24#kMXC0042)0(r[+TpXC+LDN`ld!C&BqG3'%(b6%qBBXe!aaA81NNeifLD1 -28f`AP8j#pE[3D+T!2hCa3k6AY0Jhk!mXkFE'q$E5'6FIi0,r-b!8'9#(lprR(q' -E#N+rSGf0r`%!!!d0$h"`Bk96D@e`E'98Bf`ZZ90S6'PL,VN!N!Qq+!#3%2[B!!% -FA!!!,`[rN!4069"53eG*43%!V5`h`V!$TDd!!$+I!!!)k!!!#V%!!!-pe*!!&38 -!N!EC*!h!VCp0C(j[0XAc8klAbeIQTYc00Y[VCQ3cVlAR0&01*G3ZfmBfSBHRKZI -dV$@IikmkZmdfiA3c3VH%j4&fHph'ZYK!`Xr)IX)M2"EK0,)CZFeZ+pQ%%NSfiHF -QQh@a*)c`''&E`XNq"ahEccElMQabqpJHN!!9q1TkpTYZYNp[kjZYE5efK%9Z+q% -0M'c*mm16$EbH3!"kR6d!!i$TL`#Xq'qdKm0JDRN+R`$mNV$&b35&jh$X*S$d3-$ -p9CHR0H#9UYeHkdi$[RD+FY!eVrS'RV82rA0dMb`V8*'#"m'%RjMTXf(m(U'qbV% -39fq3!'0$1,D@X!l'X4l#MMXjpL*2D#1XG6c(2X1a16ah%XFD1CE-X@8mKipM@lQ -Z2m32!jMa+`9-9!PDC21bq&ZB`B#*M)L%m1[[1I[$J#a5G!"B8*!!&ZAdP5"Dr@f -mQ[iDKI4"K8JIfRF0#l&N`kG2jE&#dJPZPm25PbNIc!b`qV3)KaN&34286iU0'`( -QB-1C%qC25-0NXm2[%phqIUj*N!!,+DcAd"(prNY"B(d4%S3%AKI,23'GJ&V6-BR -EjcQ&mU)&4I5IlT!!JV*rU53[9S4bFBNSZ'kX%UD`r1k[XI`l#QXUKDUbCXJ@A23 -e0fILE'#hlF6Q[LGMBMNd#6@95#F6Lr!ZpQ2fV$%APS0al!Cm-aVrae!(TES(Z)Y -hKj0ILGRBMpSaJ`Nq"BcCCQ5cr(Yh-IQ,af$-6jlMr4*,QmRhCF#)66d`l[&GcH& -I&c*j2I*kF4@-f0U&q6BJRJpCEGZC[2%V[!I)pf9&1i1mIJqpTcb3!2Nc8L8Cm8, -L%plrq5jiPG9a03b2(G$bBrr!rVAl&el-dkcP$j@"`35C,qp!&X3Ta2A)r1PfeJ` -T0AYJ*H(Il@"bT0f'RrVkmfcUphKAaAcNE#`XrqPZPVmAYALkRNdIPJm`mAj0,`' -5m`VC%@$*YLE**mNHYfdIZ4ZMU#`@m(YF9-mMe9RX5)d*rk0[!"kk%G*qSe24CF) -BQJdjS9rA,Y)[SU'+Gqh(rpeX%E!%@k[SYMANXB,0!4JqI&'d$a4dK@$BbQ-`IZT -KhJF+0RI!m)`Nb(Vbph#d)3RaEKLfYC-92*60H49dmIV5X!Vq([0!eY"QhJF+0[F -3Rp0p3-dIk`-&Q`qTqEXbH"r)'V)+@4#R$+j(9RSRpB([Vi$9K$q$,drf!IMj[P@ -D"P3)&MKfB!-F1Ck,rce`G(3h@P,djrcp&NL'(YB*KT%fKqLZG!QZYN$!,`GYCC, -B+-Q+$BBm1)0e6L!qM29@jl-eNl"'5KHaGEF9)ZjN[A@N(I8G!q,e-'4ML(8+!Q) -(m$qJiP0raGE0$a&1qF2lleR2eVkb!I'SXf+p0AQ)KcJiE1eZa'FM[SAbUhKG0Z, -G+Tp4'l6m2F3([bNIj6qQjVrR%1)V1-lcVhP*bar&96eVJ2-*e-qL'KMG9`-9RJC -CP$f5BY00U3(XK8NfYlme)!CYHLkpN!!0XpNFIPNUpAJP4IL3!(@'p4DEcNSI!"M -e"*Jce'ESG0U&#Sp[X84@me3N$'D)ajJLTl2L!mGAMrp&JB"A(i#(`e%a0jiR$@f -"-+q9(!**IbD(`eP4UK2!SpCHV!qJDj@VkLc"YhP8PbbX0PSEQYf+NJrXH#GBbQ2 -6`+4(1'DC+hUpIVp2+*1mNC%BZhm6KjMV@Gl9L)I"kVl)eq+S&Hc6lG1QRDX1PBI -*kTif64H!Kp(U[LM)@c`Z6J,IdMA36q3D$kNpX2HE(@Up2[BMlYi)ccb)**CYK5T -T1CqC*Yh+jpYXlii-I0r0pZkXCqZ'ciM9+aQhrqQ4%H8a-#JGJMbFSZ)@[HH&9A8 -0L)TH!!ph[l*aAFQf%3mcmEM3LDlb-&J(I*54k[95U$b8LhhDM$)8+Dfm6dHHrUP -2,l4A$[UB$%T51Z"N'[hZYML2H*!!rj!!&AR!0&cKS64l'q*jdT`PPe4&(X%fR3! -H&#BV9XPlZMUT&P9(2R2@I2d@4il5RmPahC'Iik%Ei-JVjjE6R(e!$iHc0Uk(hSH -cIeh9kmjqJ-FeCcr)iiUc(p6eLV12mlMNl#NdCmmqPeQ["q$XcqVa6fGr6YLhRAf -Faa9RIjE'1mjqJ%IFfCZ44pcFUlSU8Y2lGDrriFKRcPTm*XGe4rik$`UG!%GHkr( -G8L#dcjVjVL02rSHM3U)A1mG94cA!ijS6'Y6MLK1+mlMDkFrbH+I6$r!`@JHkBK, -b`-B`D0e09UqR[jfGR&LFVa$Li@pSkHG4fG!5jj(Xq1qD4e4dKlhXhGbR+clH%C0 -3,9kTPhKJ"r,fHmfKa--V+STJaldSh!MU8cp5mHJ9T$Yd!A6p`(2%[2L!Tlr+)pj -Cih8@kiM"rM*l-e,jU["l25L06cG&hlGaDR9Zb[9Da+CF,i5LddeG!"jfVk)!GL$ -X,qGi*+*Ai-*IQ02cUD3ZJ"jmQUJ,`#-b6HcRFA@DQ'"Y$VCkYcP9(RI[aGGhXam -JRR9R2J[e"Z!4pZM"(GXkf*D28E-CKAFPI2LqJchk6$%,[Bcj)MaDX)V1kh'jcV3 -TMLG`S9jT2b21JhEKJ8i'[&rhI)UM#e#[I)UM#m#$`U`,d-mS6,S!p8&b41j''*D -mF@XLY8TF*T6lQhf+hrF[Ki%-'AdBQ1hI$N9(*+J3p&pU)"TCN!!3D6fa&X34h+h -QPD+LDC!!L!Mrdpir!BP[A&fj&(-`e,dHeV(`p#f6rr#*JUpGGd'HTj21`ZeU9GC -d4fdGh[Y4,`cdEd4&``*'IYa&1r$#$UVlhAhp4JFSkZU8)"jFdRH3!)$+1"1-"V8 -,aJlj8&#[M$A,li#j9`G#F@aMZ(&AdZi*PSQqaY2$`FZ#Cr',8ISdm5hUmKRUI6! -"+dh)4E-`T5r*8Sr5V(UEe"diHcQ%6p"l,15A[A31JTe`39pJ,aLBN8[c$4bHMk6 -02LZr$fAJAfq'`B+jF-UPrA4I)M2(APPFNL2N&"G9&q'RFjkp1NG[T33XXDN"a4p -[kl%9Vp6I60eZ(1X&3f!"YajM!M)Z)8b!bDlUUNQBFG0*1UCZ2Y6REX2d-0#0Zdc -#%PC$(Rl1*LcT$qM6!ILQE#!%C-eaT3cJ%`m!hYaLZB50V3HmeX*Z*qcQMB#(e"K -I,5Pl#CBJpJ"K`Gm"6J6BUi5eZ`![TKKj$[N`I!QaPB40fJB2)lD&X,BeX"d0hQl -#XTq%ar(e[B3PMJ0m-kQ,X')4pJ&-jTHf@Zk%ja($LeB!0lA#8F3q6YMXjq#hL0( -L&8ci-N1YFmB3YR3e`iZ!13X)beh1m%T,$Pr@8-BcA&bB`MGkE82C4a$Mef$FfaP -ZUNcKQJADQ!YJ+Vmcq1'2XNm#61-EdJ@6@40!(Vq`*pIK(6M)ic8%ZqN#PCAR'0Y -"'$Y-@,T6pVG)lU#!YDTir$j,"(Gi&(FDh`D+lTLNdVkBhGmSh5Vj8Q+lBrbCPMC -Gfi#-T)cJYD,XmrLD&(0*SbISPdfPIPr3`ZHN@Z+d#1q5pU!X+ZRf0LASEaAQ5mZ -@qZ9'a9,NGNZilZ)8Jmf+Z9U8Qk5JC@kEapZS*8aHB-F659+`,C!!5R[QQNSCK"9 -l&*cm5Ud0U%G+E!QGjiQ`9pHR)UTTF&3dHkN$NkA55CN)-F*1%B[GQdNN#*IjH$k -0S%8pDi$kq55["@Ia8Dlr"`#3!`[!hGUPNlU9(@%R18D1(EQ9-$+K(6PU4aKKj0Q -4Ba*kNTAG5QiPYai66`mI)e3bA%q+CbHH(CjkR4iPc`KE'EReb$&bp-JcFNc###A -2b$2b0$*K4ii4YMiC-FQ%%AEN'''%NQH%%RD%(AP''$P+D16B%AD%N@IN'"P3mZc -)J!+AYaicb8TSK0Q!($e2*N%5)`b!!11"dRUmNXRS!%#`lJ0`jV"H4dh#fS4e$Vq -kJ%+l+klSIRPBeIA2Pl'22bUq(G81S*6lq@)C-j20k%Pr9%YPNpN,V(QTkVKLb2f -mX8(KT+R'`T!$QNr0Ebr,3k$jNqNKri"UC-DcLQUXqE(D$V$r"RcTQ3&DHJQ2Mce -LVH6&a(HmUYqp((3rH3Idi4cYR["C[@0A2[f)K,M*9H+Q1YBFeN[%JjS(0DIa3$K --`G+Z5A$$EK5$j$Pf1-HQL02Nl3FQZeLr6pC'4RA9ck*&lpF(Dj`pq)+5&%Ah2+r -3#j!!%)cr0(L%N3ZYLdE)M1-i@aK(G`*d[1(cljL'9JKEQi5emPQbP"fQSXH55R" -d0*,@c)$bKh+Eq&kRF#&&A$8fr2RcVP-36Z(P@@b"Y'jN`5JB3PrUA*h#XdVaGIG -C&"jG5ihJNJ`-CHUCZLX8M[II+(J@,B,Ll`bl9LQU'j[MH#0T8mfH55SUVY606I# -,`ZTVP50pTa-"53S&kKM0'a3YXD3jh)M"HKAIGBVYXF(3`(MDe%E8HKL9HIT*%6` -P4rbKV8LGUa6XFPUKm1"#lf!)1+ZEL9CmqEkS8IMilUVF1B(XEiU@bUcf@QRDXeh -XRqmP"F-F6c%&+(HejkIiBIBD+F5ND*JTi1#ZpZc@@*[ip0Rc8AEN5Tb9+G$-@He -Y8j5eIT%3+RKG@20NAb0PHN3KKIM*4*`T1%Z@UcelTDH4Cb62A*N#6M&$MHe4P$X -A5CiRe,N),M&$MBeqpqCm'mNR3ReKTZ"eB#9NAa1PkGRc)L&8m$,KZk&abC4Z(GS -MA&("fmTbY@qa-MhmPVXb"@mT+b(lpLVG,Y`4V%c*I5cMjX00k*L@SSCe+*1,EHa -iH)9ppk@`[R,Tda2X3j,9Xm[,e5EmRd(E@3ql@[i$!*!$$3d1F("MT94ME&0S6'P -L,VQj8fK-D@)ZZ3#3#@#V!*!2!3hq!!%UFJ!!,`[rN!4069"53eG*43%!V5`h`V! -$TF%!!$+I!!!)E!!!#Ud!!!,jPjp3V!#3"L0r$F$9CB2@,M16HhCjH*CZCT1pXRA -6,MIG+f&N-epfFYT&C8VS)#2m2-)16`h2k9RV`)fr+Xp0pdQjK**0@%pB5[Da1RB -Tf4Ujr4kjcFKa5Qkc6EDA4cDKK1iMr0c25T-``Q1%2q'%Nf2l22HccAkEj2DaHV) -#AeeA[pPQTEIerGEfXD)4&VQYK'ebQffb*Fr#N`e-m!,KJEh1(S!"`-aP!!lm@Yc -4+&LERX9I!(j0f+T8JU,c12BaJ!a&mAfpfKHSDLchecQHD"6`EkqN4US@9NrN@8q -LEdIA$@@cG+6J)E$L%c2G(FAh+2f[I$Ya$83iPXka$B5e-Bje%hE8bl(p2+',X1# -0(2XFaqEah#NFUqGB+XI@mK`KMQhRZVk%$`&Xq%S$+e@#%AQm,2iH0K!`N3@4$Rc -p-fGI#-JLc35!"39TXBKH5C)Mh-bVk@p44!mU4(SBlaV@`9+&cjl)ii#8Bp`ZK[e -N*LIB''$e'4'0-JU#aZY2LLeE!1CK`jNAjEq3!)DT0Nmi*2R#I9a6B!UNX4kK,Il -qDd&JI4%5J54H&beqa55JeNa-iVD&AR&4mC*LqJlhb"%eI+HXVY,%4G*U5DbkU9+ -FbTaGMc,R(88e&@*P@52NL9Ad+XQI-"IBiLH`ZHr+R,!)'X5D#U56M8Ai)q&E`N6 -,@p!#PV'EmCmaq-fP$NTe$h!Al`l(AmPjf)r@B!BV,!I'A,2cQ,1MPDPI1J+jVlh --qb@@0P-Ib)44$hE$Z#HIDScqVSLTQj!!erle-'Tl*qCELVJ6FTTh-(A,ehJ28"r -)LAF'GG-ZqTrb32B[5*98a)Z)6h6[aNjiJkhJDJL2l62bBrr!rVAc9`(-dfMNlbJ -$`3VC2hmF@4#R$Uj(pZXl@#1NeHb#GB6rX)fTXABEIIDEVl"T2qCG&I14Xl%cjdp -@-ZGZe1+j+@aQPK0J`TF0[84)R9(%$J&,G6A))9Reqealb0eB*'f9L1paF6d29HH -`3c9@r-Er!AMi*XMi[8P&PiPL'$ENQ(kG6j&q-3ee[(-[IRHbCF#5A%(*jkTkQ49 -X9@$Nb'Aa2P$3f3&Ckil!MG-1mMj3X,804QDQ3-icIi6$9BmMhJ9CfpYC`F0jR&G -"*km[!b[Rrf-Hb"R4b2Y!`GCZiR1U$qMjHrY!`GB$H[l160i(FY,A)`[LP-Reb"R -H6RhJZ9DiPr$RmFrMI3"qZ@HpS3%9JKf1l#[$lfBiG,3E$SrT3NZ+rTcr[`e5SCZ -eJh#$bb2j+UV%UQC&#DX49jNXeFZUjS,dKfDcp[(%Kl'HDLHlEa,@51NbG[rL)X5 -pV'F&D8Gp4d"m*D4[k@$YSSMB2[`U1MlY6ACrf4(#+ApdlcfEf)EIE%BmlUaB6md --a$XiQ,9K*q*c%Gp'qA9m44lLA6UIdCZ0r0h%"pq8Mr)IdI2IF`$a9Slcr2Ipc-J -Iah8pDi$c89B@8Jf-19N$1*93*G8[Dbl6P"V!ATMLmS@$LK4aQERd3TEPFRR#UPc -U$mLDq!R(E-FXPmP+(`!Br66B-[9Qk2@kaA*rD*9-9[0%*!eQ5%4ZXGGErT(M@iR -IBN8*Q!2`m(M+5a*j-Y!@L!Z$j"")qY-j20lb8T-!(VAZqHB!ZPC@9CiKq!'2kJ9 -,Ubf1ZNDITR8"1pS1GKHILI*)8GkNTle%#J6#iC!!@#B(BL-apZh[m@l%I,I6G)( -c%"bqIVjf6khSRZQH2[eXGHJmV!lIp1QQ!$`X$Pqr)1rck*m%[UqVdNIN-JpjM6+ -cT8L[emGH*IFQ%*lp)T*BZadUj4Bq-dfjKGFbrVXE[iS`Xe9N"erJ6NU[9c*Zrp- -M-mjMB&#DMMbmNZD6!ZH%eA99*-dXJ)H[6pQ%VQ6EL)H0H*c[4*Gi#)i"(f@KHVd -31JqY[drE8)CL,FMlG1cA[r6TTHk+34q658P+"ja-IGMAR1#4#2)IUUB1Q)BK(PT -MS#k4*m1li)+Ub#25E",!Jm,U`#Vj8&F[eD,Zb1F8hQVHiXK4qY-jVMMbXca-!aa -j4FNLhQ(lpI"iDa0kQ(diqhG9[H,X"hKFG[D$2)DFrD#Z3miq`H1#XkF`R$hEre1 -R'B#c2k2([jhp@@%rF2B*(N21rJb0UmjqJ%I#fGZ3!%I#h1ZkDR,$pEShrh$NF`T -ARFjaaC'rbi2#*-#4erT$X`V%0B9cVMRbe(mj+L6DhcNZ1DS"(THGd+!H3diS`H0 -5Tcr$ifUR(q"KF3ada46NJBeKd,TE(3&rAcXl2V%i9b(%)ecAe-HMSUiT`529mpm -eMlMS(RICYGbR+Ml4%903,9kT&hKJ"`VdHFd4a#-JDCVSaVdSh!JkUAkXiY%Vb(H -B!ZMkNHISpH)$R[i5Md4R6G4CEdH-p*ACHc'-V`Trf)-bq(46qHeLR&UGRA+p%le -6VJBa2Ydd"H$K$QJDB!I#rR+@4c*k"5lmq6NpRdUD!ZM"TiQQ!$aLdm3q(THQL8Q -1aNJ`80kKmrM#EYa354D@)Tlc'DF`B[PZb"9ZIQP+HEFJ[[!UTKb0[HXer,pEZ2R -j(F+)Zh(V1FDM#D[SR"iAkmbBi[L9mr9+qaN*(V3,$h3bi(VGmbQ1+8#pmLQ1+3! -2#TXT3$qMX*S#e!I*%EXE)DbqH'ZL4T29N!!8P+pC&'6)k#%`ec8'TL&"K@$q8J2 -ab)'N@1[TE8%F`GeUALNkQJ(*L2#2mIr6N!$mMkXV&f)HKVlA`pU@RVTPmKmqFI# -Gkbl)me653YbZ0Q6&*5AM[-$3N!$#$KCqh-8im-*He2Hl6rBE%k"BX8+,i-%PF`F -*U)bc`5)BEI&%991[l'f@2`"E$q$a+'`Q#d2qL&m+q&[N8P9U#-UKba*H9ecRAbf -V3Ap)LPbPMfVQp$V8if',q!+&$Mkm-'q*lf+ACm1`a,!1F*Fe8$F&ebHR[Pf"j4G -h4d`)JKec3@FZA0&p+)'rhJ["MVQmI(aJf%&cPmM1GeI-Aj!!,qE2,kiZaUGhSEX -khfbP"1ck&C4Br2Qf(QXp[2RM"r#AFD`("'8*RiMR+LSZ)Bb(b9A9PC-`ii2(meZ -lq&#IlY1"p4'J'hICK#AG#c2`1CH`P$qK6`IJQl*+"p"k#Uk8!Acq,X#E@f`+BDf -eJ0GDf'f%&A`$m*!!'Z1V*8A2`'V%[NTBmdV!EXMHi$)k!5qQ@(L1U6[J+iLY)fc -j1RJ%X@f%TEm11p$Jl56-p`Gi%Q$5&`QE'!EmCe)RB@)&l!'Bc#pYP86J&F5i24V -lI6L-f+F*@hd6[)8B,9l"a$D'@ZIR%KBqc2!LB2i5`LCR-Ec5NXqA09SU'#iZ618 -E[FNEf5F4ipGJJX8-0e@QFXfD[X1U!+E494QBi'Hh!dcR'p+IfXJD!'E`#hXjMq) -G1*M"D`KfdJ8U"mmaYSd`GT!!X1&H0G`Nqb)LeUVQ$iIX-GcMeh`CI"XS[Q-bM2E -&h1&kq4BjP0Dl1mCr-p)10cBJBbPMH+fNK[bK"XffS0iI#D[@dR!SBZGc8L0a4Sc -hJM849G+'ZjZe5$JShLU[[61XeQ[fBTp2aR8AVa4Te'c9NYSJ4q`PcIj![C%`GBN -E6b6*N@CP'1fC'bTP%MEIVq(N9`l@S4jT[8[S2%q-[Eiq&920J11LZ8XpQ'`BRC5 -*%52X",(HHc2*"1%b(mpR%,6VC`e3[j!!(,$M,$l1pIm!N!-,`(Ad2ECHRFFPR+a -N`XMM#502#Hh)8GP+RT&Rj#NjTS5Qj&Cbkh9i'Tj'f%S'M2ak8M`lmB6KkH%lRj+ -M%@ENeXJaFN`bSNHHNMNl-UGfC%E*M*%j)j3-'*Nb`Ti`mS``-QINf*%*"EkqSjR -A5GK+ISh32$b6))N4"N!!!JlVJ-r`TZXk!-$`[J53!-62*(k$MRFAhPqJ'h+J`'" -kE+(ZHS&@X[d!3(R2Q5V!cME81#NmLZ"PM*Q5AG0-GpV5"M62mYejcl4mJ%`M4p` -)*hRT+G0"ZCTAp4kp`I20D2p)AJ*CXflJ![[k&0BK$p$h#P,8PBNe5"rbHXYhTCj -Yq5GqG*raf-!U`2!+,kAB#NXT$Yk,H$pKDDbPXCEdAdVB+RbqZ)cpq4q,HIBDAb3 -EUbb*Sd6RmR+1h[FEpQcGX63D"@5rZh+JI"02AYG,5'q+'dB!+Y,aV`D(NEQXjC3 -LHki18f$Fq!pJk!-@F*l9FHL&!Nm&HXUT#Urd"DC6VTSm$l,@3VeMf5ZrK3A0iD' -&6)LXfE%)ChrI!YS@AXH#NS4EU"p&cZeC8&B0kITSeV&V[qFQj!U,+#@&43,T2-( -L3k'mfp(GV"@pN!!@f@RhD#ESR2[HLqlpAPc)MaY&E64,6FAK1,))lGX@jihLa*h -+Q86%r@%KBU!i&eMHrDTTR8K%1G2Z4D*F$5KarNaAQ""YLhkH@VIRj`*leMTZDZ, -B!RF*UA$DN!#HX,-M2$RL5@K0ESq`*6qBVe%&&%'01hp!9F8%a*QfU5jZX+@bALT -3"EU%Dj`E,H2D@pBN+P@J@e$MR'JCpQ4)Y5HK4dl$k45e2QeYXDBrip5S!JP"M5F -B@4[5&5Z3!*3cG*V0kbqf-kaC'CdS8!@cPHGLR-8EDeX2@A0UV$*&&G`a1$AH5C! -!9BqSGGa[IP&rqL+V%9%EZ&[Y86Zlf+EkE&03HHAH93dc$2F1G9`[dGk2dI3iFad -$I!hI,HX&"aIk+1YZdBGZ@!pfGU*(q#p"'D3hP0Er!*!$$3d@8N9"4%e&,QpXC#" -$9b"`FQpUC@0dF`#3#4-H!*!2!4aF!!%[f!!!,`[rN!4849K838a'33%!V6CC3V# -$Z[`!!!'D!!!)h3!!!58!!!24cTJFa!#3"USQ%3!)(03FJKJ31)9R4#2T%CD+3bR -TZ$mA@+C4l#FT[VLi0T(LAC-5%[e*2TiHaUeli+MJ!fL+c-cdk!)VHcSGN!$9G'U -6J%!jMpQ56kaeF[e0@`(NIY"TIBYZaPSZ#Jh%Q6a,T&"-4%TDC"$eBGaHiK6#F$r -UE,#$K6'4MH2L[2ePY((0QJiVbFa)MrLFX4C&XrV9P%k*E55PCMmU5Cp"9'4'1-Z --Lf[I(`peHXRTR!r8LlC+CmbYQ6M-8l)b+*0iU$1*`cN"2!)9[(l15!V2AXTrX0k -2IkXDVJbafq3iprDLfarSC$QJ-RJmccPl4rQGfdfBlQaj86C'lbPj8raYH`fTHV# -M8'J$b0qMPE-r&2B(JPdGlSZC1ZG+q#P'FmIFrq"C&J!!#diTH3##$'"#b9-bSBI -R4`Nr`JJPP%cibZNASCa`)j6`p5+FF$)$k)'TbJ6)L`0mp2K+d-F*1MK"1P"Pe1[ -NbSmFIm+0m#2SiRLb(S#H2IR@*kE8kB3r6(I'FL6Mm'JLY5C`NhcBN!!1Z2@",Rc -,hqX3$0kqmVDPdp0MHZa-dbRSe@cFQPSH)+X6Ya@YRMap8,m*RNkcVqb@YfD9Gdb -@(pL5V[f$d)%h(&9dR3K2-3A[eRC$%24pcklPGN+im510NG9[4XAqhCK'q!eX@8H -1&G%ekCkF*`Xr(+MAaLAm#N8JL8`U`c['UarA(D35p@268DFM0Cf'DJ[UkC(Cd9R -e+9JlEBp*ZeDHKp0+UC8A*"NaZmEk#-NKq2H!(61`k%F%UCp)Fdr*Cl%"fA"*TFD -+XDGdJ0S2%(dd&['`dC0MSHr*ei)Z5lrcJGrQe*e@ReHIU8%hphS0Hji3Q-&B-r' -!mp$N))LP#-B!)B`&f'`LHhLMDN4DcNc+m%'`YYc2QFGPLb"(dc,j1eJ"[*DXUB- -1"Jl95M)mFbK1DmPq60TDD*8#LVTr#Rr-&km"3+6fj@33Ul%&lGaJhPVr+%cQN!# -G+hA`jZcqjfmbM8hebm%*,9!L#+N1,H'dJ0VNPPJe9Kd-3r1AhXh0a4pkH&Kf%#f -#S[15JjfFi&LDIV#-jfH$L,5dRc$"*5dlYXAG2h*LG5FAZeHe&i@T+a(C+6&bY`H -P$M*,5%%qklpGV,EkjjR2$X!aJ9$a-0&D$,#rE))C8XN%c4LZINU-S[#S+LmCIC! -!cK!11deUqPDTKG4E#6HFSVUI*E5mS8,K!P#'dQb6&3RCYY``3[+#19G%q2Pb0#J -ISIRVG`)P&)Z1ppJB(MhdimJaJ93H!'Mi@T5Rd"MAQVaaB1MMKa)()M6L(,6@B,f -BHK4EN!#q(9UB3)UXA%[2l9N8ah+I0m'm'dV4rqeSET!!ClSCr)6[ZI3NaM(h`Qa -[Df2ZM6pYS!15DA,kLjYTqqaZXl1YS@d*(H%rQQ&[D0Y6m!1*dN[C42ALBTH99bc -,bIS$"qQCTrb*Z50"rfpQi4b*Qd1"l6*AaQdb0RkSM+88"F*R6F)JpAKak0@bKl, -Y2',&a88HM(5M8lHhF9*1#le06*L"L`EY&BZD,)Hj"+6$2Ri5Rb0DhFpTR[Dhf-I -XGEF$AHi+SpLrp2"q'$L2d"SE9NEE)@cJ*[*N!9d'%SFBi[m"%%kr&p8R32,F9C9 -DmY6@hedY,YpG65D,AUqEhF!6qMhQ++lae#2F)Uqq0MeGZh@RHrAHp"8f(jkqB,H -ZiZJUl!(e2`d0$R0ST90TEA"XC94ME#kjF(*[DQ9MG(-!N!N1MJ#3$`%UFJ!"2CB -!!#m,rj!%68e38N0A588"!+dX0m+`!k9%!!!bR`!!"h3!!!Ua!!!#REUK4DF!N!B -@d3h!e@86QCrCbJDCKprUCMD3!+rGTYfQR*+9-,+C,cXjlD*b+U'$[1dCSH'Ti6R -ef+f6MEmU6qiQQh)*h4,@5GKYZSh9XB&NDj&pK%GZ-l+PQh$*E9C+RK*+0Z(R*T[ -PCTX44KMKK1fAF-+[-pDlf@p'1,R0,X)M+r$9GI@EEEC2EqZEVHhcBNGBj,B5(YR -(pNZH(jjXB))A#!rXGIB!$!!+&J$Bm@Yb4U0JA[3XrJ,`'m)@Ta)8RF@a6`*NU0j -[eIS#BEpFjr(ERj3&r0XY+C(DZA@Ii&P2SAq+RP'9dc@Nk"%`ia-ch4I&pdMYVc` -VFI9(1$D-BkX*kf!FkbAXQ*YM,r'%$X)#0h,XmabEaA1RF+b&BkNF@mCc"$QfQH[ -k-h`)B-&A'TLT%[6)j@Aael#!J)P-L(6Kkqmj"d*!&QN'!#`S5)Yjp%U5l+%fANe -rL9*k8#(53hrAXbk@+Yal-SmG8SjcHbHXTc)9JS8"9TmHd5LM)'LmpU4B[ajJ&MD -F@9(q#fQBDR'&JT)R0-!e"5C$'ZX61Z,[2aF%eKFK%8MLGG(Z#aX%e*U"5G`aebh -1+jYI4Yp-Paa43[I)bQ*9R#FYNF6DQfV%+Db`jpZXm1l5qQUaTY),Z@)Y[FVc*X` -%G[Z6f0ahC%fB"keLI6A5bF%L[*mp`AiK[!(YB,TK(Iic"VpMUB05h30mJAH(%kr -NA1a(5c'$'Hi#aK`cFPRK3pZBmTA$-2EPRr0qLDA0P)HcB15'AKMhe$C[p(HP6&Q -,[&jD#5-hGf1qGBJAJUeY#e2@Ij2h!19K@l`c+'Yhd2q8"h*H)995%5mP2Y%pAqU -')kb*Ub%mrTbH(rX(pUrYVrNaMeI2he8*JKPbIV89@4#R,Uj(cUqh-#qNeHq!&B6 -rU)-TXABEIIBlcl1T2qCG&I14Xl'b`Th,@H%Ze',R3PD3!&d)-1'VZPiLT1DAXS2 -!8KfYFP"@I"l(ER)h*NPG,1*lA&c2Jh8fGV$HM0ri2`#2hJ3C4`dUZN`83lFKarA -VhNEka668m1ipq0h1&J",FJ3NMk0K!5[D')B4)aE%qd"4GaGNVcJ-0dip`2Y!dFB -1'*'9!VCRhS4$$5@)pd$fjNj@p'JZjeA8cHY,akVirjJ(E-1p[!m8EH`P2UIlJ*D -r[`m8EGb[jHr1iRh!0Q`PXL"1@9`2@fBRpB'I,)F(#ImTrRQL$m#VZeIU'P!K@1( -JXA`i[(F'((`c"3k0k8&,L[kFrlm*8U'AGB)`bZ'520@eBQeE1"a5)Sj+@@U4&G8 -"`akC`6V(%ar'qZS+fDU*@#-9#pLDfdX4Gl1q*Y+1qSk!q%)BYVk,GBSLBXrK0kc -K8epRDqE52f(+(phc`&UfqVIV%)ml+pCARipi&`Hc9fp(I#ELQbLrKMIP)YkMm4Q -p6XrI5hc`6INSrf%Yr`2l%9r1FCjre5rer(&Fdl-H1*r``K+UJ6'RDU$+eka)LNp -@(BBT0B#p--AK#3A#8X4Kj0),@EE$i3STFSA2,k[LTq`cl0-G"LYp!'$ddf$*dTU -Kfqd8Uhc"a6*CcC140*3K%@2,h1kUMahI3[b@KF0qB`!H,PG9H5*2"YS#F@k!(!* -*IbD(bee9B4$!Sm%jfaK!ejVDQV-%hqG40kHacQ4[pRT8Y4$BX8k`e[#C+)q85Kb -6B)XYPrcq8#JS9XVqf%L-[Ak%3q`EDcE4QhJ)GXp&[PCAJqJXF%kEGUik0"jQZfI -D0%-!(LDljk)Jlr'i1!Pm6pI`!*'V215PiB,f8UeH(hq"h*Y!H-iq*,&X-p6)l9V -phXTVQ5C!q,p@V`IfFLHPe5XCYrrTN4AR-6JS(BBmh*,UNIcRKG9d$8ZU83!2ci# -b#9h*YK%2#r'id)QZm"$XJcl+&+[A#k(a8#rfD3[+8+B'H*q1rIV(2YhSV"lb-9Q -8T',3bE5%2'd*(SNJrk'SbU"TZ-a$pIUE%hNbh(-ZUBSm)Qd'!6`Sc(DXNJpeG9- -YDSkmZ13fiaC(MY+IbA(0NCrMB4MJb+[,jp'FI9!2PlXKSBI4Kl0r@p9VcRk3!-G -9Ccr%il+c(p,eXV02m,MNl'2E93B#c[kX([pdpZH%IGrC*hKFG[CRDAcJl!Gj**b -p"ANNc,fQUbUhIP6haKq1[,KNmCNFeacjfc`S$!)FHB-[1,e)A&T5I0f4Trl$85( -4LjhMLU-Dj((9#3hTFGN**AKFkI4RHAc3k3GjQ1b$A6%&H@"M',,ZCV[I0p$16N` -XcPF)m3Je,aVJ8Gfm+-%MeI@I0Bqik#jRjIAFTbXqd4&68#eHUCGiB!Ib$hM0iF6 -$,kQUk-5p+0`)1U9qV1,4+mKh'`,SqV(Rk2ILJjlq#Sp%Cdh8@Ap(M!b8fEZ4cPH -&2qa"'Abkf60T*dkYcNfjhSVq+GH'6I(TTL%!$kGI93%l%2DAFcb5d5Y`i5r-kIP -8dK"!$cj00!6J%CXQ$[#i-Ne-XRXM!Ap9PmEMrPfiA*FX0#*ZqebK-2bZAI#U82c -&Se@pJVMh"8`j'R[AbrKrVe#m[&-BIKpZ2FGi,-)U1Ur(1h@Q6h&mi3[e5[XC#4k -d#`pd-Z#MZZG6(%1!HZ96(%-!(K3@3i"q4Q%f"+J2NL0f0d*BmXkYLAT99S*53,j -Z8C!!)D1(`"cA'4L'""@#m8X0a--'5E(@dpq#1)+leEa50$3$NK(K(rhrTb(jEeG -A,X8X$'f[Kh8dRVjPmQmqFI#Ykbl)mh65%YbZeQ60G$8diF%IlF,!`%C82+aJiXG -Gp!-[E*qfhhfUhaJ!4916'X'$5mB1%P!Cji"*d0[LbDUQAYRI,(m)PMk8c"Id4Ab -5hpIq,mGQ!+"i8d4@!VkJ&2Q[BE6aLe('02%$k[)MY!0K)KS'FE,U[6NFpN`jNB6 -qdla0qPDF[HcA@NJM[qaPF"$XZ![k-RY4B#DZba-i2"p&QhefIKp+i+ph3l"L,MF -I(qKfd0JPF[+FeE2Rj)PjXm[Ub[$TRZZXbc0D+3'VGJ8P&RqiVFIZY4fp'EXGM'0 -p))6RmiRif,##5`MMB9*YAFe%c,MK4(jc$arUFlGKIJcSaPd1B8N23MiqCa+@mR[ -dk3"m8cEF"@60FD8-1DF$hYaLN`PVh!TiVBAG3GM)l`-H8Q0mYF6r'La"l1Z%YGm -*1"&J4`JVAJ9i-FA%FpLq"ep$E!9K`@ai$$%qT`ZBB!XD[1f%M5k!T`!Q2N5BHJ6 -`RiRGK*9e`@k!5Ic59R-c2)mBRqf@[`L(%2X-BER$i3h%D2%+4MBae$T[,''Z()B -A!I2Q%rET@aKHDFRMbaS6[XY`F@%+hqLGEQ+h)-D[`FamKZ'QbK5Z@F&X9JX`PDl -+32dVl%k!DAa$fJQX&5#IApMll$km!`Ij[)CJ1efJX[-F0h33aJi3PZP@3SYN6d6 -%@P9pSD!eKVYmULH$E`2&Gdc5D9r-'@U4Ej@$DIflBr`h2@fQ[J%C5aR$'b3Pk!Z -fUTBj,Ej)5$&AK))4+jq6kSNcBVcR,)dSNTVTE&-MSB"iQlcXRT!!dU*Dbc`H'GG -Gh&,%UeVU*+99MPM,fhcq&MeKkR`RRNL5)fhKG0SceeA+)Qbf6mA*VaaS4Mh5qTI -3HCiBHfep+UDD$XG&FeDi-&NkRC5*%52X*,(qHc2*"1%b(mqR%l4UC`e3[k$XYq) -X2Xler`#3!`V!hGVlRB5GMFL%NPm**i``3MYb$%p@`JNP6mNcFQ`p`RiPE#@h(Q& -iTNH15BEiC(KfUicJUFr`(hP'+$P'eL2(b$(*-r+-c"Pj4Tk4BdH1ND-HQ9%bBi5 -5#5-64KJj4JD-$"Jj4SiG1IEN'"NbmSa-+2$ea9E#EL8$YK*'f"(k!K"'RK(N8-) -!#("!!%#@!(DMi3%!`cN(%%rJ2)DDLA-#jc1mCB$$I+*LHq@DihRXbfem*`pApeM -r"A!Zr@E3,eedUllPhhb0jk[$m#Lrj*)60&Uql36TiqQcM5X1KC*L`1jrq[$$,e@ -kV2"F*pMPSlNRJGr%3lc3l[ceBlPCJ!Xc3RU*-h(M(NZ%mZerDaRiI("YYZbZ0$d -R6D[$%X'E%d1%-hKbTPP%plDFN!!&@(lk+mZp!`iMFU9PH)%pL*fQ`PJm!($UVGa -r[JR6N!!A68*2j9S)*4RDAX8*3X-H8dBYmTf#5BU8SVKB[Ei,-UdT5TEp*iliL%) -PZPp5j*V03YhG"U%'&45apmJ3YD@LS)CF0$*'821U1hZ4r*C&[fXPaD&q&TjV@k( -EU"[qL!+EIC!!4C5-SYL(rNZYHZLZ1!Dff1mX*VFTX!-9a!i$`042#R&,&HUKieq -eE%d4EH8SLhM*#QYMJ!%ddQ6&CQRkp8[2Xk`6K+dU+F#PUkBGZXEN&ZYQl2(rhl& -1jIabK44-@'5XfkI(&qc)GF''5CQ3!0l`pBmEYeLlC"EcT-#8fSEa4U2A"QY6Jj' -#V5N5dLhEIGaj`YU8%#RB6-*90eRh4H'9FN8&@e&XVQl4AZ`1ZY*V8["h)(-GrbD -kMdiH8DbNV"l&MaV(rZ@ECM%3RcDfH[JZeL'f+Tmcmei`+*4cG$(,cV@YVIiMr&[ -cHAT$VI82!!!0$3T8Bfa6D'9XE#kjBf`ZZA"bEfTPBh4c!*!*k0X!N!m",pJ!!8X -m!!![#rq3"%e08&*$9dP&!3#Y,$I#X!1P*J!!-Tm!!!I`!!!+F3!!!X8d$l-C!*! -'Jc!0`08PmeZChjX0mK+rfFQeb9k6f4&fNT8``[9DQ8@lU*Zkk5$EaSVGQZ%jpGL -Yq4Yre56h56[#pV20)SaXZNhhX8[*2PCNNq0(EM1bTH3f)lGCHH3TB@36(YYNXbk -ffCD`,H'ac3M[f$jMQffff@mMccr#)a6imGI9*2ITEIfeDfdI+hD%4@iViC(EE*- -YHAjiXS%*AL!mX0IC!`J!+&`!i-#[aGhC#GE&6q-[!,mRE%N'3Cdc',X0),2'(kS -1++'3!12aJ)4rHReUV(T1cBFi)mGIrMJGlB2,*qY)dGI!LNr-Y,S6hi2d[`VXa$8 -8Bk`IBaX)Da'-G4$fUTHaJjc349M6#-BqaGJ-cTh1@!0M'BbYi"aKaVDaVMr$K`3 -fI'@#P5V"L(`ZLlq($54-C%'N&9rrc*N-#9PNQJ#`S#!YjY)VcHH)0(-er5e+k%' -&5!rMA5YD4BCdlkNm$NJr`He+f-pNFS*0!&DI%CfGJS+J@r8RaHE0!$1`iFcSj&p -)``bE*a,fq50*VZN`&M,&6UNPmIjV3@"p%4+$0+k,PF'S58#YQCM%AA1mmYc5HDA -dcIBS-6@b6&'AD2*Fhe+IA$fU5KiRR1f2#ZFp*E@9FP9j!2,PDRV0,"Jj(F4((XI -Q[MYRj&aSP'XVN8iZ&Z&piKGLRf8XSTCE0Z&V+(k(83HPZJHiMl[$b9HII1a(bc' -$&Hi')9a6mSAcJIe#rG*a'2ELIZkA@0T#hCJ$JalUJ1&22"RSI,P%U!mLVi2VB0# -f0Xbh!h%Rj$9[&qVQEh!28$IQ*6U$qZ"ZqTrb31j[5C8-a%Z)6qHcAfL$Pm4#9N0 -kl$NM2rB2l&qlIKI#2!%MIfXj5&E)rI81C%'F@PQ2h0pX&`()V0d0D`Mr3BY3iqf -fmqP[(K$MImKG&I14Xl%,jc-9`VN(YAKQN5JFi!3Bq@9$,aNb*TD)Sb!bA)e+@&' -$IYGHFMF@RlC%a[I`K*j(Dr,%d9SVIK2r!$`m#V*H-DRS-TdBKJdjS9rENk4IA%- -GEhX@[l[%!K"TVLDIhe@p@a4YLF,!J3X5ID#SV48'V$N1)mBIi6j3Y+8&"ZDN3pl -hAi0MeBmLhJi$YUd943rR-kqL0Ui[!k[Jrc%2j282F"mSfY*"I-lf!6er9amSfR* -)cpq@`hdJVpmkC%'FFPL2[1bee!GqY!V@%rjMr20N(i$$HpFC'P!Kf1(SDqP`I0m -812lF9MJfY"dY+ITcrRmVC%!(5Ld0GRPmrXTUZESj'SfS-9HjiQY39-f9V$@aXmC -l"Pm%r6DhRNVb1RikAm*CLCfe%a(AF`hBX![akBK[jIb-,ma([*e`XAE)*V(K$jX -3la$hMilLQr*4rZ0krXmI3R`9ijcrrPmCq4-i8FBFV)q),LUQ'KKkTJBUJ[@U6`d -Ub5S`'DN"l)AT,RqN+HU,ZFaFHU%Bi(*j)USb1aK50(Q5BiTMXXYNT3m!$(N+E$P -k-r4khA*&-,a%)DYj+Y*k-k4L@+RA@r'"ieZ%hp*S0'31`-2MUCLCbT1&YN#Hdd3 -1JD3rPm2MVCKY%X#McMh,(%$AUZUUm`6Ii9&60Vr'iUJ2q$A0#H,9Y@#[iTNS4hS -jMNQ`aFldK8+45&JZ9d,aNCK8Z*)KmI-ml,Jk$mRKlqCVpp6*lN,hK!NAUN2RBAA -i*d``"H"KFILl"AQE4rFNm'eGSdNLehNSbk1&+d[dHRhX"A*[@)mPN!$l2**BX3f -UP*8m-dfrJfXCrpe$p5S9VT,&NAhXT24k*H2f2ceb%Mak"UApN!#(ekIjID',`ZU -k4RfD@3!2Ie,CP+jNfiL(MAKFkN6AH%L1(KpPSAUp($S2VEY2fe#'8Uf*qh6mepI -lp(ahCDq2bD%NXhZF6%2%hjcLN3Vb(kUQpTL'Ucbd3+JqP5I,@hCC9H34DcB*i%& -KG@#9[+FVM4m-4ckeq%lc&NH1dTr,FF14Aq"K'Z$)+fI1T6PlMaiHEee+$l-2Crq -QUMHFI3q2kmkqPmG9CpqVke9RRq*afGP6'-jH(2bTd`c!fCrAipr1rS+`lcMl&)q -Vc[imMAHGI3q2P,1h)Bq8ZGGeeC6'pq[Hr-146beHFLl($8Iq*Jm+N`"(AKF-6bk -5PaG2[HR)-rlPU*!!D(IRZ1DSHRKFGd+pHPae3LNHecVpH4l[G[SH(KC(6eG-4al -B'(UYZp84#LEEfFQ*aF8+)4k4qX9*(TAeLe-m-McrAI0)L1jaPpr-IEEL8ada(GA -L5Vh-!cY3+1Neqa12N!"2df3hlNAK4Y!CpH-9Mej"ZFF830F22%HA&qrap0GiT$T -VUXkk1Q)X@@C[49pH&Ak["fAaG22`Y`kJ'li`jASMZUCFSpS6dde6!"lZN!#Q!AB -Jl#mAH24"Vm$#AjV6me65&%!2RLDD![#)6a162+j0%p-FJ9K6U+*9jr(C2CLPMc3 -ImEa21UAqGqq"`p+d5Dp8G%Mb[KF`j4$XA5rLrah5Y,&VTIkVFHXjcQ-a9Y&&2Dl -8Q6(B[e5[YCk4id#imd-Q!pqZHTcLQ!2A+8aa6!"i80P1!INCK03@S$j)MIMG -#@RVPeN5YTUKKAj0bdk)J3d%25A4[6TZK""@#q8X0*#)2dZ+YTkX&-B+le9`T1TS -&I4$KMr(r8p$R(eGA,XF-$(f[4l6-2h[,j$pm%Z!Eeef3!1ICT-@iADh,QZfT@iL -AIr3,!mQ0U%6B`F,(AB`$,q*jIErl6,ma!BU&#l8B(P`bGj!!J-Si&bb5d4C296A -ebUjQq6f`l63&89cNmF8SFjVi,RAjIZJ8C$i5*KFlR2@6aTe*XLbS"A4[daF[j9J -1k5eN2Prf-MXSh"-Zk)[LPj+`X$6IaZ(jB0VXFr"p+)PIEi9NaeaH(KmBGY$F*A) -,h*@cbJVNJPQP0DAip-jaea5BVC5!AEq#%Sr6YrA%[B0AI4Ll(3`A1d'+cZ1*q,# -SLNX)Ym+BkTUUdCMaSC2jVHdme'HhBAd%k-CG,Q&Tkf%L2UF6P[jRp1N![#NEE3@ -bjVK5K[qe!YlF%R4T#qSP`'XYiLl#bVi1H%K0m'V*lDYK+@*I*@ckB-#*J(L*-28 -@`!XX&XkamQ2`&F6@%&Eb'AJ%XDf%6IS*E%H$YiX`*2N%`1J('2X1i$qMf`JEXJ2 -f!ScK5eZC)q!!BMcE(I-b(-2AlDc(2[J6BRb**AZp3+d,KM(A-3)[!KE-)qbMIa4 -iBDD!Pc8qFC[!aB9a[0'lE+LBKKKIJaRDAq#QbMM@l0-E46A!H,SU!pTqmA'!#E` -KAEKD0!*-j!Yldcq(Gq"J)YF3l+),9!l1F8X,BH))kq&9)iX9Idc'@Y@#NE!pMRZ -#QMq,Yi%51bCpD9r-(@P3lP$#Q9flBrbEN6EEf)#-TicMG6ie(!`hDVDbKQ!XSPT -R4m)a1mp*MF4CFGjPbf1U6mYf0fZa5*0mTl*L@84Yd1bPIVq#kbjHAbbJf@TmDU- -5XmpX$SBDM)3Cmpai)NQ*08IldTkjS9)1BE1#'NjqPDCke#1cD`QGmm6CkqY6FG8 --1#'DHlB(Nr@PNc*aBS5G)YCeEkB23EM-arN-JREpV!(U&eC#GTc&*lMq(`V!GFa -@'a!fm$TbM$`M[a*'RT'9(6QfNT8`3JNP+hP'MUe(f+rN9X,@BiGRkj0MNZ&k-J" -fUq`!U-p@,r+-d1[)HZ3B15BC-3ND+"Qa)mI)8Br-+*NamS`m)a0''$P'"S`-'$P -'MKdj4KLC-I+-($XbSF#(ppDV@pR+b'!PM$"b9,C+f"%88F)!#("!1FQUe`8!-*a -(!3,hFDiMCZ,FJr-jrK+J35aBXN5d@19#I%81p66ee`FES'Q5,dam1E[5,$I[[-' -hc6"kLLq5[kVSE1lmijXVF+IHDPSmHMbkN!#m&6eA[mEK)$Q*rX`1q@MZFX$(3Z` -K#fN#j`V1Zbb-@"Ja`hNU5GJDI*jGK4!F3M$0AZ''FAZ0'DjF2lDDS2d$4AZT)AL -8SS2FEdq-V$q,,ffD1@4[b`NTJ%@PF9H$adLj`K*DPUhVCkJ`NTL(8qpNrR8$`T! -!mCU%9Q8d2'5rDiPmf8Sh'YQDlFDYhbUTEqL093444BNl1r`rZQLX)L+pq#YNCUb -#EDXJ#CFV0rqS#2G9k"p33lmYP4I8N!$*H#,Z9%9PiQKSU',3Y9*1*&YcHI0kfH, -BRT--re,Kl3AbCEFk&6"Xr,'+ICMa3U[QfNXm2K%6f&'"Pi!5-6A%'+VSYiG5mEe -,B`[*LcqlG2$f$T-q8M%hk#jK@fAAVYILcE'+B$pP+Fp02j8E9ekN@-Ga@a9#3*1 -XIJT(V,T-MYq-2HhdHpBTA9JX%B)1HallVGc6jUdqklb&IHLaq[hCIGaj`YV%5JK -QbqX,2iXpIINCDp0P3`J%C"Vm0YRiZ(Q2YI0Q,N-)'#TjdrC!VNh@TXiP"(2VqHV -R[2XbqeVjLJJfXZHVhq!pr3'bdMBKH!e)KkEA3rI4bF0++b(,4ljJ'f%lkBDCFlb -$NDem`MYbjK,Z&Fb-F,l9mhRkQ%9qBfYVX)4h[4DM(ES"rJ-0!!j9F'4KG'8J0MK -V)&4ME("bEfTPBh4c!*!*I`B!N!m"2CB!!9A4!!![#rq3"%&38%aKF'ad)3#Y,$L -SVkM%6J!!%4!!N!B+*3#3"1iL!*!),Vm-`2MVQ#GEcq[CbjrbTd8"k(946[[dqF3 -S0mV91Tr62N*rUedQfB6rbMa,QABH@8pDjbDFE,CZRh$#R`ciN5hC%NifqDfh#Ip -Sj&Q%4fi6hNYZNeZh(GR(HRUFmM2G6KaBEjHAH5XIC*6r@X#'[lj00b2l*-I*E3Q -2(#Hc6G#cm34!"jdGRNJMSX#G4(kmfMhki1-2%c%6'3rTJdrm5M"&aL2!dU3aqcF -RqX*@4+eU(&3p[E&'(HVGiD5eDAe2&D"rSepqMjr9FDQ$,!Jqm6!p)&iAV)5rdAF -b0[DZ2[M,PaNId8)#laH8YM%rX2ZSiYE&dk(3E@3dhN683D5ZqmhdpcFb(lcr%D, -'#(NfmX`"8!NF)kh4eXBUkVl9ihVdpK1FZrfh2(hl2[kN-dhU9Srqk2dR)(41k$q -YNZm@Zr+F*MRG)HRM8X&9R0alEj4UAqhH*CdMkhVL+MNbV+b"D%UPHT24K+A#L83 -XfKZfS[(K#pAZq)JD'NPCUMqD4"8G6PRK@%be3#1bbGDVJqQ+pR#UEh2,*R94h88 -0m[VKe4f!GiedFQ%FL8aJfQ#q,fkGh'$1Sa)6KEl6*XhM8e6U3h&Q!mdIfQf&NcX -L9NUJ(JFbUC5d$Bi"mZKSYNlcb@ZLd)CXQNBqJhbdL-a9M4XIZ5Dk24P1lUll0A6 -`H2%D2'15iFK*Ed`$M6Q$!L+h+6U%VL)XmS)m)kSPH2d8-&(S-H&KUR,mKFBj11! -[4#+!0dJ,6"4f+d[)`jr63Kq+LJBb-$**+j'-licd@RQdfd&0")IGLK)UjFpFr"P -T1Lf!Qd98CU+`hF`R(dr6'9)XE+$5@(4lIc3@XB&f!0)qf`-QJFidk%`Bm+dGLFE -ke'BV'NXj[5r$HaD9QbM34BP5iVr6f4S+M-2Cp"hDU$B2pmD(KL,$&Z)JSQ*Kc,Y -eFec&SX14P,,L$L[Z*)1+ppXiTNAeaf0pND5+pYYTFA0if()mPq-pKmie843pIdS -9'JTiVU!VkE)j8E(iVbb+#K`TS*'qU"92eMRZcX@lQ-ic846GrBdU044`9dNYG+A -#d#8L5@Xh@T6XME4'NfUeUPkI'KJ+4f+V@b1l)V&i3KUq1MqGUG8@9S@kKYA9MXI -cm#UU-P%82Aj#e4S+H+bQ@UT@UBL&%E&(86TBG&T6B$P@U[!ZSD8QLQ+-I-`IDIb -aa-K()V%8lrP8Bk,3Sq!E#*B,U0C%i9UIPrb3!,2mJCFrT2+kF'5A&8GB$ir%BN4 -TX1qMjIJdcNTiI5#4@eZ)h(TDTY-bQ&K1+d`8HY+QqHP#@QQL3%rQfCEVq(f6kJU -'$IiVeI0lAT6PGDRGUAJX(Zi6Ni8&)ab,)TEV5AG@*3rrK4Um+0aH#5Q6'NL,JkF -MhplemEYI*CM1lmN-[#m0@qRS5D[ImI%l0,q"jShB-3B2+r"H4"HE+23ZM'-!FhN -*A@ULX2Zj#'0r'Ddb8D"rJLrQ2p2Pr,B2T56aGSR&`PlKS2R93UI,BDk4hc+Td@P -"'Ch0*hemmZYY41HhC-lHPVDYQQhEQcjqNi)09*+-@,[#-E[H%SkC@-*XM3!&q3d -I[h'kY4IM[B*I0qN+FQq$5K9QDM9Gb5GibJ5JVd(i9#%KQZJU%iAYT)UUqEL2Mhr -PpLTR+DLQ*Ac-aFG)-j'hVQY"ZB"@m&&D`dHm+"%M#0G)-UPQTpU*%C2@1"D@)5k -D$@V'PV$)f5Z3!2f5qqeK$'qIXbSGN3*,UXC6JV`Z2Dh"'k)@%d8amPlM9c9q6A4 -H&BN@['[j&C2@cNUmc#pTr,*)[#4@AT'8!M-3*"H9m*pS(EAb*0DF0JdJ9Ujej1E -$r#)IiKGmI2MVFIAaLppZBciqp&8qHIQ&Eq,@6kfNZrPjDRHKd2h8,YhbNHP#Pc3 -rY9&TN!!RU*DIih'kQMTic![i[r(pR,4pA&TlY43Gk2Ucr!`rc3IjMp6Xj@IckHV -PClj*C4mr24Fa2MliE36ki1l,*&R!Bp5`I'UlE-[e1l%jYahUHQSKqCF,J`CAN!# -VlI$QVYm2DSYTrV+G*mqiRP`$!C*3!Grmr0La!h*lb"pMC*H6J``'5aCc&4lZXj- -N04#4)F"3fcX@"Yk,aXXk8[MXD-"'59KTR%mZ(BSHENBBlXI#3pJK51[F`Y2eVPe -8lfTSfRIJCqdeP5XlK0(302U3!+#UMUGrRYQKkPfUU6FaE,@mclRUMRd(UZqUUG` -3k[GXH)ac1r4G@Y"98iIVb`fG)jeEX$`CeppEhp6CeE-HEY1MPE8h+U2INh!edrk -$0pA@'rYrU(U8jrP4+Um+8ANHU`"@XIRHqM*eipiEeU4lZQU(16IVU20*lYP!1jD -,Xh!LCY8hTAS69U*UG,Qifl%32+1q5AUDS0(PqcrCfJ9&Uq!"[!T4&AllY@hYpN5 -NekrVA')M$`K2J0+@lZjVmTF4Qk%MD0bi)pfLL1i)iYb!'iVZ*MF1-Kk24X%b5UY -U#S9D5'A6kH$G&2,F5FTp"bNp4%&089!28Y$YSD$(65U)J&FDT82k$bMY[NdM6bY -mG1!iXp9$lMiNpP2`UFRG#Vl&[`YeDBCS$pB%l+NDMKSZA&*+FI@4Fe%PFlUC1E1 -(H3URUbcHDE`j[+I!BA"235-(VHP5m&h3`A8TJcS0("l%4`l[0*@qR5AAlq"6Jem -lB*d3XAH`dep@!Q6f#ra6)#$lp$m%XQ2(ja`%b"LE%mM5f$M!JS$3S9F8b0-,!ME -GjMX#3Tmj@K5`k8FG!b,!$2U460("U5-jd!fM)$!c0J&kTLL3!"X,M)01"NjC)K# -Jc"MSj!JD%j3em"%j$Y&(#!MGjS-15D&RE,kd@34!(mIabkEEA3&p,%qh@`Ek@)& -1-eQKCiVdSlR6p#-6Fh6Ti"aG1RJm0dZR3'BL'aJVdTd6F+j)ci[-dJY69ra#@YS -I@U#UJQXp*pd2hRCI5kK+93GEbqmk2eLM&SFSVD8$QFUTjZbHDH61+HBph(bU-PF -jhCaYRPUFXB0%hS$ML6&6JKS"ff3f-b&c'6!-1a-i1f'(aFca'6XNCJ*(T(8"'62 --U$eriePS"6##N!#'Ur'F5-p-f$$P*Q`B)96XDEkAMFlje6l&jXqeT[Qr23[RkZ) -mD$JqPLbk'iKhka5jN!$AmXVpidI8U*r35qcDTIqN)$GhKGFQ@dFVCGZSd1kKB+S -hp6eJpmLQ*&Z)E$5SIpV6YV8(`SqPV0hLrJqT4'S!pD&eADeYi"eEfpNU5mURcND -MkFj'SrQGI8Bl*pSE`hP*UiRfTJ5r',AJD`Ekqh$fd6CX@VqY$I@@klVMf(5el8i -S!*RFeL-hq@kLmi!e1[GjqV%fHFf$lJ("2%pUNqe0Lqi@c1q(4PQHplSf'FD8feJ -12'bHmRr"I"hBGqArJM+D,jk8imNVfMMQfeJG2#Ab[%[JpARRh`(['Qfb,HGJ[VA -3f1YJCMZ`MMb'LGUfe2Qr`,m"@+ec`III"1a#aj0r@*YFGrMr$3!49A"NBA4P)'& -XE#"8Bf`i,M"UC@0dF`#3#3i-!*!2!8Xm!!')DJ!!,`[rN!4"8&"-BA"XG#%!V5` -iU,!DCEd!!&q3!!#3"M)T!*!%Sb-!N!JD3Jl!MkIji5m!qJecY,,23BkX0`IC1E+ -F@3jbe0R+r-lVc1IdqfcLp6DaL8eciR9HFd1#fG61FQjqCcQe3Ckp"h"!!,Pq$FU -qiqGQhF+lML`GQ8(bN!#-)"NY"1)*`*PfGKkHL)RSN!"8SS0amX*SV+#b)1Z)dT+ -#D$k1SPKakE4C"G4Up)+QZR!"FBdaCIQabS*SV,Ji1MU[Z&[(E#'K2L0'$)f9&9F -ffaicq!"ZqpG[qBhYZehMBT-AE4NrqY#8rGX35HrM+,YEM,S0T-+Rj[HKf[-HqHV -`)@E,V$BH8CrMU2CmTQj(HG5lpl'8[ZmkSRR[rR!ihScVeSa'(*AZAAAmHV2jq)I -0TZ(c+AT8ZPbeL#Rph'CQaAb28VSY*J*'Kb128JC5D[9$%6qUS1(KZ0U6+(e(RH+ -efa[RlMBH,D@8aC2YE8QEa5f'cqShZM4D2UXN@PPB9"'Yb#X[+UZ-aXV+LS[bBT9 -&T5AYSh0,Cd9RcUUSM%iY+XHYU+5Ld[C-(q3S'"AQk`KB$AVrT8'fI8fh0P[T9'! -YX$dA,5X[R9k3!&GCB3(8$IZA+)0mbX)pNN`ZiDdq6P[l4)QMY,4A6q*V0b,f#8i -HIT!!fG6*QdfG[1bH5fkmHN#VTKd'fKIC2Dqjh%DM(FfQj5ZQ46YjdCjjC5@9I6i -cQjX2A(*Mmj0E04hFHfVki*[-jQNbQl1m9Kh0em-2'6jVq%&%R5,Mcqc8FhMZk%& -!1rqDTQdQ4b06dmZmAR6YNiHfk45jpZcSk'MkmpG3r@DpUAimeJLa4Q21l&3l1RR -a)I[2(jhETX4XVN)dr&icHM"0DfZ4@B,Te,-LVkbbV0NeE5fkD6Aa,Y+TTkeT'9h -6pYU[aq8LBf8#!pieXPRYq`%MF`D%(6&r8,rK,F,)qIDG$D4CrJUI)'aIb(bL&,6 -Ti9'L"9R%NNiL+C55)T5HcT49QqC(Qi1BqP"dircj@DG3lr36+CUbJ+,5Ql)i5PQ -549NTkC59RN,4,+(H8DEj[H9BQTpb(&LU2h!-6+(dFHQ8NTp&hNVJC%X,`'haHlL -RV3$MJIA-4Q+cL6bcQG+-TNa`9&0Mj[FbCX8mBpD"XcELh)4c-dk00`C[0A*X4Uj -0DAM[)3mM(qlc%3F'Lf-ccNf8p[j'mKi"6JCHLcp1)[JbIk5QMCC!UVl-l3Nb85I -DQQ$MUVAE%'45C0@f""YTeE-)*K,BjmLA6""rRNJ32JrIZ`6fqCBeb36Kmc81J%e -J$*krY5+*3,qe'FmMN85#,DY@irQ+C),0Uc+IaA1+E(%*-QR&+M`RPc#bQMC'm"% -jK+JM%YMRiAXm4dVlI%AihTEC*X$cCcI(RiG9`I09mHGKbI"m9H)jEGPSRkp)2Pq -cHFIcYeC[HfiVZ1fjVH$Dc9A2+A2&kSfCUj,2E8[B*$mfF0Ac40FP[pim2k0hM@L -cV,lTlk9FH0bL2VfE4CYRpDprFXZX9Y('[@NqcmpFdA4GVihc0S&hY$(c6#rGG(2 -66EdfpPVAH%9)*2E-G*J-HXT')jNKb)dV9YZqc)a%3Ni`'eH(C,&PlCD3!#5fC,j -P5jGTf``p'[EIXaZ4+a-YL04!pHaQQhV,kM"-QeH(BC!!8,+Qm9VZjHDZF!D,cfP -+rHH)9E1+"8()UC4Dka4%r((Vb!09fj1S0Kh1IH4N,a,H@hYAZh3(A68J9T%rTXq -SD1H1RE2YQB&A+CDh'DJm%$'43SaRa!&LUNM"bfU8UR#4kH%M(abG&Z"50jZUcja -E'5ZI9P"CB81MA8K4'[(J-&Ge5XG!!3M9b9Him-aiiB))"95,e$lGKL`E@M5P2&B -qYq-pYV5#d9%`1#U&La6ER)KRQ#d+8f@BhXBc)qJiT#mVbpZ4RJfB8P"&`3"D3q% -5BN"eUDECV0!q)3BEVa8"JMU8D8X`UQJQ*Q(d@J)&q&'S"XlD9%IK%U,!p%jec3r -+cVN@KBhALe!pLm*@iLF82eJ8GA$@Tpd8,L'+&,45!r1pSJB1KBdhM&"$S-b`+*! -!Ie3KLTS!mEd&X4[14Y4Bi4+#3%Y5%r1GSLB1K)dhM9"6&0`2!438*k[`R3A3''I -8E&+BZ8-!U@M5CZCE4FdF!"Y[(U(QYJS9KAmYjEF!JD%-`95F,@KhK3Z3!)4XC,i -aIfEcMFhcCjYLGj`YUCA#*550J*6jQPS(Z$6+TJL@$q@9F9+,4dHiU+,@VK`"4Fa -AR[N+%bke!TSfY)I#*85639RQ5fSEi&)cQp++LkC-,5SZ#!-$%&$8eQ()!%HdLe! -lp((3GeC4FAjd6'94FB9MQ6e`YUF1#KG8-4bfc4I8NA%"mA5N!fP)G%a*AZR-Q38 -PP5%6&mH`1DQF8aSY,LSTU)K@PVTATBklYr(ee0,Lr),bD0(8F1mb*eC5k6"h`0Q -*XK8Z5F`EU62E!69#R@PIkV)YUBAiPke1N3dA*+)&q8@9TH8G(ETXR([5AJUA*,V -2D@r'"HMfTMkdVjdNbJV++qHL419j"If,bU-pSXd(9461M"88pqKI-,ZJZ,6-&Va -(BZ6S84QZeASdGaMh`YQ&pP'i*$&q4PdC&f$XLJjY(UdSU%5,K+eS+jK%fLVabN( -C"fFhkUj`5G,)TqB60TpD'X%f5+JlcKkdVm*&L[#q"XLT*qfRF2%'a90qE$ib(rV -QBkVI-9B`Zl)8Dkq5@FA&EXCE4'haXIR)NYH(GVMC,c(FG+,pKIB(L&l8@q%LjI( -094rUUh""6DU&'kaqjJ0&r4+!)qCpkQrqj10D[f2&h)V5iY*B[J@CQ-PLa88BJ2U -6f'8GYPcQ2FVaF8Ra,8NTbL%Z$3H3!$5c)6!ErSh"a2c*pX!(YQ"pA6jEkRF$mbj -9ckCUXd)D!iEH1!I3!3SAb88lCS,G"p)JK8YBceSB#!E6%)8,kQIMMFdl005X$h# -e6$c&dQ*LJR24q"!R0"6JKTPeLSDj%Y5QhFcD`+cG1IH*`E*'c(TEYL&9CAXl-'p -69MDPPKG8cSi9KrH$BX@+"VNFQD$c0B&CXk1d"q!FEYj50*a5*L",-h4X,Sd`EjS -h&!+b2mLR'3D0!fQN`L9%dSbDQpF$mrUrS4hTKS,Qe-+mjTRAL"@0)'mNRV5QGZC -9'Q9HmA%&MB"F#mV,Se9Gl@K%d5J(B3m-'+-M0"T$@5dh9i$l,Hm2L+&jmd0k-kr -BbjZfMGq`NEGX6II&1FDmV'K-&H@pC&jNmj,0mk,0ml+P),c-a1i0NrB,G"#00Ar -%$$11aT[Rc@Vc(1-4TVb$3#h2QPAQ'I1dHFSmDCi`M`IQfCfp'CK9[ipHJARQhmM -)0dr[iYE!2,@YE`2cj0qDMmd6YX#2fpU1*8NaMp%%$jHd$*U!X42$RKhQkf%%ENV -02C5E-e$[Y#cc+1eR(M%VD5*0-Jrl#2p+mSrBrPPTHf1L[8bL9,2#2'3H0!qBqfQ -dEeE%1GJh$qhLlX!mZ+1J$ra1P!(3rEAN0Fc$P0efh45lVHJd28+Fmd,ZbTU8dGD -qS"RYb-YjD8cZSc1i-9AIBrTlGFD69jLC3H2Y1ZBq1KJ8F!JM!#BpZ'SG-ePS-Pi -H5M'&5cJ5f5A%&-T6Z)3-EbRPAXShp`5i0XNQ05[F+#8k2VjJLVHmN!!PU`*cYk+ -#+Vkq+c"h8HeX5LmXR9P3&UXXG*%4L)LjfcEC2EBZHBQk&0*8SDN!-Sd+&5la5FU -M)TUZF%RXI-bGRVR6dZld+Uah"1D1N!#cd$@cbNYX!m9$k#%"0+%C"2+HBHFEZbS -TS*P8SR$a$J`e"2P85Q9dQ-*9l$Bp`%K36TM!bPejl*B#GEB$q#bDVA!*"cP&pFc -Y0-IFjZ-D*jAmdV`U8XQ+$h*ch##RU*DjP3lhF8RahF[$hBLBLCA5A,0Fd9b5[(# -DU8P(d*%+Pq4dFdYJE[QjSa3Gk4S%fbTcXfpZ"VkmbX-Vf5bhRADE(4YQicb+MPD -iK-@VMbRZ*R1MZF%h0k&i`iD0'$NX0U-JTlam'0DM@+M1*eY)0MGD#$GB#%IM2-C -FVqJB"k%*TU$Vc,AQ'YpF&iI3VlKLK+ZrhFNQ)&aV)8!K)qCkf`899GZCUp2-e@K -)RVa)S32$3FTQ[SVQQ@8qVVm18[1U''"TB*D'r)P--bZQKIGK&G2%,,0i$h0Gh"j -p2Pr3Q%,(dR%+Pl#+l6(+ANR(d`)I9dITq9!)a5TQ1!V#jr!H6c)PK,%[R8!R+Pc -LmHjd%TfXF)R(Zp)TY&$K%SphS92T0)9,2,iAR8jR+&cLmFjd*U(qCbELRHJX1P[ -K%VB*pNYd6S61XI["dGMDK'1$(4BKdF#-TqKXe`FGU+1j)M"Al15)43i2GNGdES6 -1aHD`G[0SHDbSSL!rA!HKCdV,Hf#cCd'Gi8"eTMh0%YmX!D'!8D1+6R2[pU+pcH, -!,2jEdbPDk(*Ja@-ZpmhPbG`RZhGGUCZjc$HA*GqGk*D*hE'K1FpFUZJm9bJE2cm -#'F[Ze'48BHNX9(e30+q`)'p'@@P4I*d@0J2f,RBbZ06Z(aG!5A)*A8!AqVLQq&- -U5m#b&lK0FNr`fN9#&b(G(qKLK8Z)%mXJZL4#PpMGl2L#q'E[BTbA'L5je#AC$fZ -Hbb*dQGe$$mHBB-RXBJ[i3J$q!eeZ,[*a6I(cTaCMrhLj5pS2+jA&%9Um&9QUZFM -#1`lR%R1K)R5@A8`-!cGG39HD#fLT3N$f`q3c$12V-VT+i5,&Q2H'B9P`Y6PIdG8 -N*@(1dA30ADY`iFk)Mk$4jMcIR'I,APL%+PbEb$Z#VM2R+VV1j8(FR11EFfcr944 -M5$MAGJr83SUZFR8EM3(lqJKG[l9ZLUjd-pP%1S4ZS"X9,Q%Z1e@IlCQcEBSEUaM -jV-#FpBqC$(9'ZU8183be[iPZ9VL%L')da5cbc#*M&0eFKHM-`*bj#p'&&P&*e6, -mPNbk4CUN*iB4iV9f)[XI!EjqB`IPf#fL(H"#B#YXIpKpHDI4-k*BFrk8mHE"`B# -qrHdQ-2@@1[e+m`['aXV,LdV,Si2kjd"&dE@Mfr,plbreLjXq$P+YT-Y@)LlUUr9 -MNVV$#LV,5qF8P-qSL'j&M,8"&(1TYq"FL+VeV5TDMkU%@d2EF[IipmT9"reF%jY -DjZCc$h0PGb`JCS(%,iZ-+)a9&%6hM%k!p[,[TF`BA$5cG89dK!8l,'B(hahIVdh -P)hGd8-Qd`TK$rYqY3hl(8Idk$FSGPR0!(pXh3RD$YYaJ'PY1E$9b8l%ZZ&A4VBj -hTY)dFhTJ6Yr&1fGB&$'FYp(Y#TIN6ZidFbUEdbbeRQT6h)lc$VT6i4,ZA&+`XlU -,X$5jUfVRXY#FBNi1c-*`@@6A3Z'#2VqS2)`kU3q@i'+JeK&cXQ@mZa-,P+CdMj! -!P9RF5rFTA+!BG0rp3[FMfdRQa-#F&!k(i6,GSR+4%0'*YNEhiAb!(P5i*"Ic*p" -$M!Yff!pKBcSS1L#H-JSj35aD'-ZE%Df`)SCBCA4@48&jKC-`i$%fIeC4%mf,PEM -eI6L`!6Cf4UAP@(4Ba!rLA%%2+eb5L"I35XB&L&GLJG[(V[qR3+b!14Di5UC&5i' -Mh#,HVQ,BUP3&T54KGZ`B&cBmM2-4HP6K%Qjpl,,N-AVF(+p`$A[)3dFq)I3%%Me -*6bPFf,+@eHFmVHKTa`L)QZ-#!pRY[cF52BAdcjKM&6hM#+8D8+e5Y-UPKm,'c!q -`'2QP$iqe6Ieie5CNRMR'(1fEHEXf)@b1XA4`Y+@DiffT(mAjV$P+dE0Zi98$j2! -FV9DiK!0A(@aZRUFr+Pc#l9-Gk)&H-0Jf[H!'4KYrd4bKk%8hD0Vi5i50mdYZ['T -!MFaFhm`0Yd`PjBTH6Z4Y3+qB`a@pNX$9J&ieFa5pkMBYL*[Cp*UCjH0D[f0"V,a -LkY6mmUTk4LQ'Z+,A,20D2(A&31A+CSkp306-jJKl1G)f#4DmLG%3DqI+R@Z2eDj -S0E"5Hcf6AZHhrdH#QA"BRhkMYXq%GXP%DA&0c0mchPbamPR-K$EA`DN$LNSJpIP -rm,R$i6HpYHq+!F2lMl59L-q%0Al-SNE0VDJXQ!N'Ym)LC!@a!6dUe5JKhYQHS8H -m,2qc`B6hDi[mh`N[R1R-8CB%lm6j"VfTF%Q1C"@QR!dDP!h+,r3QcVGSMF)P(-R -5XC*mQpBUA*)Mf@'dcT3&Z2j6k,)1B0DE8NAVUhLT*$!P9$qEI*F6j&#CL!e&6!` -5LF'JTQKYe5,m(D&h!1CGfU"`5Fjal`QpKf`c6A&JC[iZ`a#$MK,DJ202p,l#*Ej -2VdiId)F+PlJb+Bdq-M-8IH6@cMEq-AfLF)Nh3$8ch45C`X"-rpG-LJi58fKVq8P -56@LQq@CDFKQ0!L[kX+SpTJCQkLmD!ASIYIZ82P1iK,AcNIYcfQJ[)3!IUSS#(2r -5!N*IRJ#F(jMm%$$QaVc5@9$8f8Jr'a(k$)#rS#m9,L(J$+JG[k+[&5lK&*3"CFQ -Ik4Z&LpH9V8bUSFQMEfQ6MbY+A$S&3S9[(9K)3Xf8`%cj9h%fZ8DXLdRT1`0"aRG -ZNV,almfKLVjhf'hm"i,bp!Hh`UZ25@UbEbB$Gh&"#9DZQahZZP6I("+B3hD4$K[ -i4,#*f9lmaQ@&a0%F(*L$Gf99p(99'dd+c#4UN!"03A`6'bC$F)30KX4'Ak+CYT! -!9VKiij!!X`P@*-C-C)#'6YJbA8HDa#cS)m(08e"SKPhANETa#PG6R1)SU#1@b"- -ieB`2c)6rP+)`C+@FCXBT6R2,p%kd*kGcGFATVRaBITZaJ4Rlbl6)8!VE20R8f4` -8Q)2#a3mi`R9#'(+-,`CP&6-HEF69UPTM6'$'*(+k*9%B'KQ'8'H8acHM&IYZlGX -G64"`K"9R+!lFfVFlpH4-cP+FkEJ!Dh#ZB8BTVZ&J)Qj'"QEN6TKX-)XUKUq$C@& -)(mf"RX(+3c%84,EeHP%1ea5'#*aVF@h&Y9cVpD+qA)IV+UlMJ%,6D%B%CX62M+N -B!ZC%hA-$Nr[2QB3KJ1CkCVMLHQiedJpeU+qiIQ*ChYm-m`c8*f+'i`+0Mr"Zh%! -aC-Zf-3E5%'l)M43hG,LK864$!c0dCb-SEZ5J$D,"CSKRKKJMh!#S'T["#TUTX"Q -'dfKZ)Y`%cjTb9(&6e`c$k8"ZaXd9ajA0`bRA$2)-e)D+QeI9I@"J"[kVlT!!9(! -,Fi$L&UlZ)`&jGm@l1f3M)4SFi*N"+)ij`"BI8JA`J5[$@""%5fkP'"TS#0)3Rm# -YZBeL+*aY$FE51*-6Q*bG2GV'JE6#[rkHk@r,ekUUI2d#dqqAJFL-YX+eL6XC8&N -cNB4JXQpJq[iq%QKd`4lF9M&%dlDd8kL!fh&laHeFL5"!-hdmdmH@U(e9LAS("KB -U[hGB@f$VB(STlT!!h1*b4m8G(6+laGhI-rY$"QjkfEPi$G*eiQc&SB6Dl3Ef-ch -Cl'G()rLY#%-(cCej6i9a+p`0`#U!pq+p&Hp9Y4[BPlZB(S(CPjTR8qCKX`V+jf+ -29eTQ9j!!&I%(f*EQZJI#8$[c2UDliRfUUYXY-0h#X3YQ$BR&JSdPaE$G,52dX)b -`Gha$)!pb9q'Z!010!@DVm,QVfBG09e[#I@`*)AcQ(Vb[BJLI%l[9,S`UGd%jZ5H -@JVY&qe6-L-DQP-kUM-ka'eblDV9E$@5d##!ejIeiIm@JAkGF9QC[lX@pIE2hVe) -TKL,(+RT3#ZjMpP+-TSlVplK[K2Y#r0TLV-8EEf$XDdZh#pDhbAVf`YiHjM'HfC2 -lFArIl*Q3!29`2i[5'MfNFBlTV"LUD#[cXI%"`P!cm`%m82%"5EF'(K6K3@MPe0$ -C`#Pp'#TR(Xa$&()Rr"KiD!3dNNR9R5Y%89`8a%0`$M2J$BLCicS6(KlKi5K#5Pq -XTF-X"PS&0TM58lNrUYD*Fde(hh4+D)-B%QZE1jfUmiJ)MpL@1pA!R%-BJR)qN!" -(+Mi`XBQSaD-B8q-S0a&Q8!dHBcSSKJ,BE5CUm%%m9[&"EMZ3!!N9B([IY%m)JAL -XHfIRr(DqDCF8rR5`[$+kLSdJa'dEXVJPJmV5X!YGF(4TU&%@(SRDM12aLXFjhUP -0YFdHTJfE2@c9VHd9MmFjJ5FURZ"iakCScC2BY,Dm-`Rc3X1Y['0Aq,(b203*4$# -Vh1RkH5,1JrN3KI9Nb$beB624LLIcSEjTp4[c30TUQ3H''a`c,4A(A,ICq*3)6m% -qS8h)2"JNmJSU+L"Pq6[e@-&#R(jDfNBq&)fm1qGa[Qpf6p*2RU1IZY53!!Y-#`@ -a3%Jr0Mj9'&T@RXEB+%ac&DK,pEJS`NABJ+5&kp!4S#pEDR3q6qFCLU&SYBRU8Ad -ZMV#YSVG20fK@E4*FHDE"1$V6*B%9#*G%Z'3(mc5h"B2j8bVRSf$0Z04%IG-Xb6b -P,MFF3,JXJVhLGZD"ji[`)6J2ih,&KcRQD8kYZB+4'J4SQDFjYH4CTURL@BjjE(` -fce%mfc&-#fTTQ[LQ5C*jjVKh9LrIf$H0Nmc6e$*2C4Ac0!T-)dV2TK4,"EB5j6J -2jlQ+3i@XYHjSBaUD"Q`DfKShX#NJ)H%Mq%M&4cLHX5Pfik2Bl'CjjUJIH3B$Bf9 -4AK30Ae%B+im,l2P)R%Ic-BU2GJZC0R3+cq2jTMiIUhJH#3Cb[1R1ar(aLL(DXhZ -)0Y5"&r!*LZ%GCqX(9a&6,c$eYYC2m3N*PApl2M(#*rlBpBSK*V9BXUN,Rm3R+ck -TDZp80c"eYf1"EY*Lk3`EMP-LI-Uf[P93'S5&kdR(mN)qeG6Kda4$ffA"pD3qI$U -ISIKd"`j#4e-l-,9rShM&N!"q1X9MEcic`QIq0!FT2Y@0S[dTaSZ%&k'(cZ+c&Cr -PZ,Sr665eq"`qecHeIZ2UFaaApkF$q$a68r&j9I(c63h&jlY#f2J&%Ei!CKrCrIp -1eU15V6dUE1eSXPaa$SF5JNe0bi[RJKHcq%+'@M-V5H3A1L)I5+2i$bC6-A5KPXK -Yr'*K+%(j%Vj8m5@Z((B0G9Q%,`[Rb"#jSj*,F9l1LaA(aCp$D$J[LI!50fp@8Fj -LR&FBl2ZZ5'b@$Z3V)hcP$LU(U4)EH%LPmN8SQH+P*Z*$$jQJmU9*S5B[Lr#b(93 -1VblKXh&HC3,&9cNURi4Q[CU[83ceU+Ab565CVc@qBUK%,CAEq(9m[H+i5[4JQQb -Uq`C13h%U[pkpQd3(Qh6I`0NY6Z@qC34)8"08$PHRY(#RP&mDCeT%A!1)#@aYkpL --%"*E$XN(EpdJI!1UG52IT2K'ab(jG+4*jC[j&YqNrXBK0c[1b+GT[0aJEEbm+Rk -V59%-)CpY&"Zr,F+hBDRCrIp`##aRh,SJ6LC@0'1XPT0[3@GkI$[Ii4XX$H*N!Tf -I*C0#UZ!lM5L'@B%P%aZr5rJZe2PZ[NFaG(Zf,S8dJqq0m,er)4-)qIJq[PraI5l -2$#VK"b,m`&r)"-SqIY"JBrDJbe0#Kr&$%AjS"jRB6Cfae-"hS'43V'VM3bQ6)*- -9,RFPcH'()rc`GM,4b#0m%mk9@LYHkFMN+(6Y)rbSiNFFQ4a&mrJa[8AaBij-E2a -aIN,aiiidMUCjHV1[0bI*j!Rh$SB%qJGIrj!!)"-0hbh&MbE*4(mIk1pr)41YE@h -K"URi@&H@"CMHRZ5R&%1kCbZkJ%lLTb2mp)lZ8[a8&F$[![hG,`$j'*6p'9kPq"N -hK#kNKAU6rTBe,+aB@c-VASAc@Aj1-E4fGJLe+ElKeDcKBaAKe6mZf3CJm`#+'9j -DdJ%Kem)3jI(cr%I&clY*EL'pcbr`LrV2r**L+2+XVH0#L$"IjPF83fRRiPIcUrb -DiPFGfbbN-rPerEALejfHa-EId&mTK[M*6S)frLDrTIK09rQ&G+Vq-Y"IEKmchh* -0FbUG`@XL['BE$E$qbPkqYQPHFj!!ckBVq@hpKH+h(@3EAkXh+PlVTQBEAmIV&8- -BC8Y`0Ph!lr#lLYpa*6LEcY'I"rVchiG4#+"X8FkKmhP$K$IX@0iTAZr!3B$2lr' -I&,rR`%(HVcm,p'HrJrZ6!hFaAFE[4rMp(4@(R4CVq(JTMXXCVk2lq!2pU@+STfb -&EIa$rNMaKki)ep(0r$&rS[KM9i6Vk(Vp5D!rqCPH&-Ge8YI66IaTK$rG`Hf+)FU -bX'kPZrJcrPcaC`l@VA5ErMM3(qq%"B'8KA8EhFNE)laa4eAKLkAi46GlVD5er)8 -`p%lm*B-X[R5cedTkAAr%Ar1IIIh4El2Aefl@@NQ2m6Ik3m@3!"0Ci$EqEB5rh6Q -[@aDF$DQ`ABXR(-qfM9JD*PZT$*Q9rS!hmAHqrL!jAB9k+4m#f6rbprTpaGqlkFV -'Ia$q!CAFc"K$))HbPALFRQ)GB@eAD8QqhB)6`j!!BJa#0XP6Y%Si)PDDP,D0Q-0 -6p*m8)Q'L9E4D[)M!8@RVE+@YbCCqhaEX1a6X28R4'haYREV#f3UZUQ(Z&qKPU4D -4DMYQU`ff(T!!PdQUIPF*Y%Zf`GkJYC)Qk8SJBE+ce4Zd4UVVGj6!J0$19MEZ5k$ -%Gc28Ql4'VrIeqX4X*B&l"r'MAZIVGFRCkKfd2TaHNk22fN#[T3bi&1@A6NA0F8A -T4EpVU`S$2X8[ZB+m3qp,4*35b)GX,Gq"&$%M)KNr0S`5Z$iQX,dGk,IrLShrL&T -R5TB5Ufe#dJrS!le'[m9kMHdLDfm&BeQ4'P*6#A`6%bRHe'q`YMCBfYTJ#B4,8NY -U+kRP#1X$,YD[5afTkq[AIb8XJBQL&B9p`"1PRY4A8Lm4(bql53-P%"Ujq"KT+)f -80%c%$j6'dN3*l!pGI*JdPDJ5D)9FI*!!0*2Q5Z!9lH)jdN*f9`*[3aI[)bfPP4+ -)H&am2fNYEC5d6X5lbak#qN!Ciq*GT*fd9p)Z%HmX(D5M%PMrZAJ(k56C5L"IFI% -pT,2XU34D&4G[,A[*hNTJY1IL,D5,l+-%#K3AEbTGTCX5L%KF[+&dPaj+S"KamGe -NAqQT"2S2&kmMqmRq#Z0)2&j$HNP[*D"V&eI54rVLNSJ(dNrk+m'ZdmA6*%F'+-P -*a$dj3!BU6&%Z6NB'b@!PD'BArd''b&!Pd&Ziq,Fb6)BV'CD)Ib@j-N*"h"k2Ibi -(bNJPF(#c"28"I5bM)M)+JXdk)`YLqA1V4SpC&GC"`0%9[0`XAAe-RqRAI2eD`Sj -'4VJCih2k8NEV9jA%"4+)keGmr8Sm$qYA,BMK$[*Ap)f-LFJBDbFDaCF3YS4#'L9 -$(59r5prVPhhp-L"8aUB!+L3RpYd2T29,[RiTq@kJHfGBp)ZqIM(jEN$iMMe1e5r -iqSAN1qLkl,Xdp[8IF56I1Gmr+c(8c`IkqImBKq(YE!Z2C9+@(+4A+i'Fa'C(A$r -RkqH5KBF(V4+SU9"iVX'eC@a%aN+480-@(S+R+Qe&[2S`jlE9UF2epE1qIMCCR4i -1(c4qHP@J9feE4NJSDr+KpfXLir3c5XDjA)MVThhpG,)@cpKN%&6C@M6PjM)q)Z- -6Y4KD9$,$Y[Y-'*F8afX"&C@Y43YZTCrbp92*@ZcTm%&ETjm-p*1r$0F#ACLYbal -FALES*j4-F(N4eirlq[&NAH"9Tm6TclJ$Cm[%#24l'C3HpNLX-Pi0k0aX06Vch[S -aAcq@V!Dm4qfl,Ya02qVV4j2[S1DcllTc6rf)Vap*[S1NcllEMh[VPEjHQA`(LD& -peiIlkiGprA$b(45-pPd1$p3VI'dplGblU(XhL)IUKhcp82)Gr'(YZf%m3MrSk`H -6lk#[Y1m1j0(k!9mrN!"m"e0Dqfi-Mp2hqrVqj,[3[0ERm6a"*ZRlP%abhB1i[MI -3prid-E+'HefUe-9NIBmF,)IiqTl%+N"JA'#a61*mQDc[9M)jA!@%m80&i'`R-CQ -La!Q!m'bbj%@JFXH5T9qX*!q@!q'!2`9R[Vj,5El,-jQR5%&%#Uc28blQ$cX-hf8 -R6hM@TFSK+-5G-PAIiHXlNb2q9*HjJ!YP@N5Q9@91eAGBL*!![8UK&#NT$"Gm2*1 -2NHNb3pqZEe1`SV9,(VbTP'+CUHc)Lk%Im6)TdEFU62afk!rMT9+Q""SHfeNPA+D -AqhTjFZJ[FqpQFSQqaGHh*)Iq@bh010%3Ph'&("D4`hEdJ*)CS@L5jr!48Ui`mSG -p0)IRkTY&hf`Ei(EE!0C&$P*)N3S"ALX)`[*L(Xr60qNE@GpN8eLV1"MSLFb5f8U -J%E)Z%r2iH*NMKbZ"&XJ#QmI(kKY%`e&1bH&9'i2V!hhp2da""ICe-PH18!,9$rD -X%1!Xd0I*NDb[`jj9MS4(F02S+$$[V,*`R45hFil'eCK`J3Q(2K&SKH3S19V*8Di -C&d"qISc-dpIUDj4Jhi[&(V#G*r2P@!@Er,!j&r!TFT`FVq3i4eF3rqLV!hhelq2 -8mDlV6Z#6C8&%&[a94`1rr"$IDAb@R#!R+S&Sb1)lM8rA9`AkUYraRHM`R3i0cNN -41@Ql,%KJMSF9(j3Z@q4NNC04p90NSC*6A08[j([N9$P0,p0,PF#AcPEp3Vj@6TF -cP-#AcPEP3Vj8cT4&5Xjd9B&S4PmCk#ZhMfR18ii[iN[NV)LFp4HCNjcKX#cQCA+ -fR+2%HG8K[N4I%HJVYQ-jaf&C`N[Ph)LFZk1HTcNbZB([N!$cj(`Pd!TKp%Im0VP -!,P3#LcF,l!Dq85m*p**rf)S,e$k@8@rN@q8LqB15LecQQrK@[6M3cY%1hN8`d3l -[)dEd8`*&N!$0!B@+[Mc3Pqp5l#U"DLR"DCF&qV*rF*U'15(VTCD9)0L5Lq85*4H -lrVbAhj4,j6*pUFBE#)YXIpl,cmMPXPM*jDkRlZ@(C)PFS@5*+mkpI*qq10!AEqm -TTc'#P14"Z6)L9fl9&#U"%-RL@-P2b&*CTJ5D)SYM*6qLra$S2fc(XFcKH)3IPkX -LFY@1hVc-pHCcr+TF,D"4+)aXEcl(,mZeFTf5Daf`jhLe[LM3&qhUcHYFEklQPq4 -kZ8%*0%Ffmr2mNVi`d"H5lhV6PK#ii8"RAkrQjr8&JElJYkkX%LMTm`0prUkZK)d -JkdYX9ek#mdCpRT)EA9Hq"6+p5@l@jfS`'53aYL[IiNrP&PQZj"EA6@raHVP9-0J -j"c(%eqLc!hhfcSA#EDkce[!kZ6dLYrmS!K$SQ5bX$IbKh#&h+VR$`GV!lqQc!Rh -@6PL3!"eC@1ra"h*A41lDdE!36GQ'hFMIbGebMj+lAF0Zj'rPAX&B$[F`#h)MIk% -A"AV4VSD&BjKYf#ri'lPI(P"b[m[m*33"C`Ekc,!m&B9a1N8%!e")U!qi2&r`PrU --3*ra@q[H8p@kT`IDHE(pHqYD)d0pMTeBcl-Af)kbYVDM!ZG5H9!H8J+r-8b2f1Z -,2Ne@X)Br@d4@K#UGVG0M+%D)aSAlEQjm#1I$XP)*PLMJ!J#i4ak44r@T'P-99&$ -@ZF&ZT4q6aj9!"B@Q46a0RT!!*j9!lB3+)ZlT8`*pbZpcR4-[L5HTmP4%R[T4mL+ -21h!q&ZP2#cCMcTJ-m8#IM10hF(!PXq!#bC!!94&CYB-A),`#X8TG8-fc)P!dbA1 -#25!fIlENGE%dIPlqU%r5'&9K(@C,AKH,l"IN4583+YQUe-ALr#9j@3QX`Qa9kNS -pI8+J6pJq6,cXDP"2'XJV%APPqe!#bc',S`N@k+r+DdTHG6LD5&1p)0!,YZ1!rEE -&d95DbqX4HAe(,5%eX#C2EE%*Id2H9!)P&$J1mFlbPUa4!V@6"GC@fZRM!hhm,Sk -$@`3i$K[jE(PEeLTjff9Z,pRkZ%!I4p&Xr1a!U#kVX'eU5aQ2Kff,Z",B1pQFf1V -VB`0pl'pm&pGS@EkE(qMjZrMZ*%Y`eVP29Z0F*qZ93'f&[BadNfjkRMk'p6bE`[V -$#D45mSl'jZ-GemlGd1A[bJCpP$j5bEZZREYK$rqH32)#TbREKYf`phpI2P$b[UY -I0qQZM`Md%G[Em!2AKYfPTh`BN3prfJ(!I-TLk3d0`%IbXC+2(*EHdNI2$I6Fl9J -JRE*BqNKrq53LRqaSk3f1RSE+F[P8",j3mTPmVZ3c9mqK-P-fbKIkF$e(b8CAck& -B'RiTAbQ"(j'Y`9$S",k@2bYaEND)$p1c!celjaMeCeH2B6*#[SR)0hqCcU$GXE" -'bhMj9MBTFIC2L)r4X`)pDbHX63l@'"NRhdANZaePG[j6@')@bIIbJa*i3&RQ1P5 -Qb@ECSX4j25%Hdj@"VYc&A*!!1PRQLXP8d@+8D*Gj#MDB&B'ZF-`9PL4N,MZMaH- -KFi@6'P450LGfUESmd1@r-4IFU4,-G9LJ$p[&A0E,6m296q4c6$SBF"9qLLCXia) -jda22df@k9(N`KE*YA#,c["5[Q[,`(aQfhdUN`N[edT5AkST6)U@k*0!P[r5EKer -*X2e@+Z9HHX4,re%2kZ'[0#bXfA+N9phcPHG-S"#ISfF'HZC1@&"J@9Kcj!J[L(M -"pMEfi29NfrJi1G@,H%VK2cV#0Mj16[%b[%cPi8Fd,%JX&R9aS)[rdFBHa&+fMBr -(chKNH6@8"fFRQhQ"R+aR"(V'A`B3emC9!iKYBmqC4`($!Mdpd00rE@0[UikV+0" -&ZpSBhR5X,5i22PjH69fS[*UZM4I*FUq@9eY2de19"i-TfmD,C)PAakZV21L`E,m -YN[1mHPjpjF%2bS*B*'ITJN!Ar#3$8*lcL*+cj&a[YiLhfeC"Rr,U1M3AbU9H!kq -KmL!qX'JZP)YdIU$criB'"P)@c89bLGFSiMADdEGBepZqA5ShHSfp*XTcSLr%VrH -DHP(P0AA`X$,6HB(1fp@h@$RE[PdQehR0[1E+Jj@8cAb9A+HR"(U+m`#09BC0'dE -#GP@HmjG#hUYd,0#ahhS9bSa%VaiDk%0hpHSdfkZ`e44Y$6Bd6"*C`dK60)a$4F1 -MP[9#5mL3!(Kl,EcGPHIqc!-ESA[eC(d)kmNfa5'ffI&R(Pj,VjAb@SE+!D5ihfZ -Y21G*KHKpqZ"!(rb2@RMi'3q[MCkN22b-KmAiJ$bJ*qS*V1&aaGVbKjk%#q-R0,` -pp(MP34NAGcR5ir4BeM"IBch@jS%$@aBXU92e39jEVjhAhZ[JG@50[q[*mYT5LKk -M4qY4HQ5Jarc,25l3Shmh13cdU(rqai%HqGpZ8"PH1rbDJMk3!2,d#*hViGq%p2! -!iAr@+%0$RCDLKhQG23d6SJb[-c6RHQLJKrjLT+MK!*[PGB*`CBJHV!F&HXM2Q3) -pH+I0FD!(rFhT2F[,KP[0,AUJ2N!2d$Qk[qkRqqSq%'ZIUh[6qESA208[dr[6BVf -IlURhe6hSqM3pd0RpqrU!q%m3q(T!h#(5ecQlIU2!erehrDH!Vr[YqJ@"32Ip@rd -%Y5)ITA+L,4m&Fq)L(d9ckKj2liH)lVP,9ZVVIH0U'am9GRUF'RSi&Fh)@CklVLB -G8TZDV#pTqmlLGe[CIhK)b@f,@lA`PPSkPRVK(b8SrF2&,6pUq8c,+h!qdr+6PTp -qpRRal"KPaDK'M'VL&f0b*e2Y'09T(i128'0+RjkcI$a9+mTC2LCh5@CQKYIHNNP -hZPYhdefp2Efpp$i"`VmlGZTZPMrK&jEP3IfQZ`5kbmr8N!$Pl3@#h9[[TIH%0Vb -ccJldhMml',1'AjFJ$aUVmbk6AepMka2D"pI3qe#d0P9INEXLFbcq'FRql%4KlVX -e+GM$YXYllA0Z'B-5Gl!PlN4VG8IG`G[Ekk,E"`Mr"aYRD*JrTqKfhMkHKXYFKJH -K)1QfJ@llUbZVKLe@PVFh+Vk(EU0EkeDkTGipd([XbKRS0MYCYIA2"RZ"E[@EBek -J@qldhJ[dlMYG$l1m,T5Z@qMQZTQ1kUDkL@kX'`@kaHpdi1[QF4S1G,2I$IGm(Bd -lR[UkDGb$e0I@p@P'D4kSZ$%D2km8$Y`PP399MCrPr[9$0rVAP&0$YkHLYY2E%De -["4*GQA0VlZ+*ldkD1'(PT!Q,0l6I-qHfh(V8pmU*lleE$"+G8GL3!&,D,PRD%Mr -%NCCc4qkbkD$)i!Vm+mIdc2&8GeQ4$Fp!Z!MKY#YQ0-QjG@,ZH,-UelkCBHQcSq@ -@KK"K0Y#lH9fpEVTqS"[qVcP1`dmb4GIcZRXD@i`-VlYPQ,U"KK2V2ecp0"bUXVb -ZB*JkZVDZT@[U'MSVd(9fj3cdIpJf"EV@eN9US'[q[,3+G)fI&L+"cYSjUfGjh@J -%pp@C9K6+`h8'*+"+4h5JICl#49aXTBKm)TqLUr1CI!&I"[h@PEb-Ei-Hk3&qL"r -QTk&YfF$[mkG@Am)DHMY2UN&q-%URBdfD*Q1a2*dSH9+!rHCK@'UGC,Fm1P@Za2U -MQY`ZGqN8H8T@b5[bZ[EN3rP%[T([Y(MTAU$CfmeVT$&UC#BRYicNj'EGNR6NYmN -Y5%jZ@!'&NjZ[3mHMdP,3@1Ka&!k'DA%&Dk"6rkB2#c4m(EBUN`+GmV2`*G$HImN -&!Sfr,2VADKE9rkr0A`#6R(rI-pA3pH@KGH[IHAI$c0R[rHRp#+AR2[94Hp$YaqX -rqI3c[2NmqHE@h#X`M&V,CGcKFNie@c@Q`8YLpPG`U(Q-DUr(E)V40%EeN!!A#kY -NjY['8p-BlBEh$@,8-%D0`[H0Yle2Le%6%$U3!$A&@UmH8%8Y8YbEK8MYLAGAaZ! -LKhHiYdLq#p([$R3YBi3(V80dEC,SEJr4lC&cHfk-fNkQGLhY'D2fZ(Iik9`5Ipd -aM&i4MhB+SeI'SpRrP[R[jp+@U%VR'1eCE%Zb9k)N-Ia#NChICf-8m3TcTmr'[)* -+GiPAI*piEde(0h50peZhq*Z-CBYMe,epbj`l`Y4if51HBGpY'ASQ-k"6pSYhc2l -E-[4+C!Lc!(A[12Sqm5a,JDP[(&ZrECRlEd1I%mm`)&%ci$`JMRIJYUb$YP9NF$c -$N!"Y'BBQ-bb0iIFdN!!"pq(E-Z4ZUeQBD9PQlSK-cc`2,E#")3'Ejr$R'*KY-Ap -&[RrlE8L4Gr`&RT311,QaGBYS"(Zm,2XEEiJYV-LV`"m&d2RfYpY`[f*dcMMB2G" -0&C9cl3,TmBUb#Sa6p%+rh2j`&k@hq`l[EreP[h'rhFELIVZ0-pa2Yh'$SVaLr-` -&Y`)KfrLHZ0[irS9BHH!qH05J#IKj$$jSl)K5kd-rKHBE'#a[Xkq(*jEpm!i#FLa -")BXS$0rp`FCUR@*Me@#3!*0mpm$@h,#NF$'i1Dk4dV1aDM2`qi1YH")6h)U5q@! -TNh`(2aIlR4r'-*mQBYKr*f29QQf0KAlr(ki)ka6q-*MllB"8H-mQkaIqi-$r"`! -!$3!19A"NBA4P)&"33b"8Bf`i,M"UC@0dF`#3#9Z8!*!2!9A4!!'5l`!!,`[rN!4 -"8&"-BA"XG#%!V5`iU+qS`VB!!"%@!*!'#K8!N!36(3#3#"+i$-$ikjKR[Y4M,cI -+RaB&S0G&1Ffkp9NMSjabY4`3CY[SEqPeQh@%%rjiDRLDXP[cbAV5iqFQa`PEYi4 -hK&pN`)pXmTaXXXPJXilX)jY'RNIfNprNpT(*5RK(0YRRdH18jbR[I!IbJ9d1BUe -m&1@r&J"3eEFTGlrN1,NYiC(Mj$C"e!BJ!(Tjf4%LMBJ#0P%YIZf4M)LP*Y2a4$b -jAic%%Q)mP4(fK#@qEXC#KY%AVpf6(M0Y5``0G60r5%Ih)60M$rH20!(k0rVCqrR -jZkjbN!#e'eJC9)4($STXDLS6Xi5CL8h%Tkf3!"$pYSLC56&U`B1Tj*J`lAE$U"Q -hdqhK-+T3GLUC-%Hc)IJ96Nq0KQhSQ$4MBF2S(aH(S%BN8UQ$l+0T`m*i9SbPBP1 -69Y*QYTJ`Tbf4cX#'#k2rXBVIADVbR#0*2*6XifE'4BVF4flRkZ(@)jX'TVT(8L) -cPA4NCf1CH0S@CMUGL-G-1jj+AUBFQ*c+fQ)mRN%96fCY-j%3AHKK$DYq)FMblPZ -N+VMM%Lcb8l4kUFr-MZhT'KEE3YXLr0H#j3l!&iedFQPXN!!"6$YBmXbYNa[-094 -PS0!2+0)DHCDUI5Jf4+KQmT!!E@Ef@hD@S4%(-ULDY0f1!2,S'!5GDXKVS0!Q&8d -MRjpmY*k-G$VfNa[MSaNcFbMdDr6"jmA[PmX'qCefl)hKKc(R8B$E$FFRi6JLS04 -3,R2A+[be&$"3k!RQBH++mK00&U&!IX)Y![L$Y0C!SDbX)SrmQ0Ej8$4%b)pabYM -T61U!&E0,k*!!JaUdcV'LLUVP4blj%@NkVB@Dp94RS&"UDXJRPqJm,YC&U$S4(af -2*b`&p!&Jqj3'6!*Ym0-'#2$YR)SRaX3H1jl)1YlAi6qIkJd8F*&MPZ6Ik3)0"FE -K![S'I8hX55+q9#Ca&#C-C)&pCdSJIUfXX&-1+q@NKNL0+pb*jF5BP4&aPA6L6M0 -T1jVVm9p)&aNS+TSrT!B0"63hd29dp@T6P[L[R)ScE*94DbaZTc)K4pe&q$I5a3D -+LVS2U&&$!A@0e%AA)e*6D5YM(q,0)@Eea$1LA66hCbFQ65[4hQ00@iP8QJe[,de -RYKh"[6d8D@pf0&k-Ae#6JD+LmAeUeP"!Bc1e8V2)@MC'4)dL1eK4fP*Q19+Dm'q -Lc3D+5Sbm*pr9j(XF)qpbLmhi,k%@!i8H"pq2B,Q8@Jd8V[j5bhGN3ElYPHp3IFL -dTZd8JM`jP8J3jF"qN!$Dm$4Ci2"kQb1hY4bjBGULdaD)D+1Y"JUGP`hX@A3CA@k -JJ#GVP153!$aM8+JXf#rr4Q(jPKGPI5Kl+*Y+T-`a&PPH2Xa%(,%F*YeCSccb6BT -i8ELp(&)'48K,JDFMhpl`b6Fq6c"G[X8cF)B0ZpcTaeDrlT1[8df%eNbT')1'VIL -hd48'#Rd3iaM!A&j*9aNSP*rV-ICAdc8'#[M(q%Ej9lT@[ZC$b8NmbV&BhLXFY,4 -Dk(3Ya'fAVaUdhE'JMLk3!+Gpm[3AfiJZAq8jHieYZfE&YPGmmK8+4UJUBpR6CN, -9Hmf%J390p3K38,lXNbqIXrB+r0I*P`bkMYbhS%X6CUUGVTF[bN8$J,i$iG1%K1L -J'``85NN60FY62RRUFl8h1%Y"-ff5*ehb*'N'mYCe%bLAdPCjJRE)iek8L"'%UjA -*L*@TGQ,%S"f1K#f)LdirG@*,@1rX&FKqc[dq%m-ljUa+alPiNFGiNC'Af0-@r&( -jJN(4PFKlAMkRbHHjch2Fj`@1)$!$3A*4PI`,8RZRr$0fQ'i0)2DT,R,,Cq@#2#D -ImFPR[jK&ReciDYAbb@1IKipA2[0PPYE56Y,GmQRUFD(3DkQ(hI+4iB*,@Lee8h9 -3rSPDj90bRRUT6clT"IcIE(k+ECpRDhZjk)2VFh*@2L%IPhqN6UqF+d@R9mjq'EN -qqF4UI[MNierPQ`rU2SZ*YI**LV3YM[)U($k!YEMhkF((eP&Y'c2Si&Cbp4lE-rL -lJpT'UYPbi24j0j0V)X#"!EVrij-R(i8GMD8M$1pT`cD@`eMj(L1'*bbf(q1X9LH --ZKH@mjC4ILS8X#J50KARmA&$d)mlNA&(XFF39J25"[E+TE"VQX+Z5-I$MrkdVkA -amPh-L(6-r)K4%C*,[mM[&f'Ak)LPNhEA'9PXh[A`SmhhY66ZMSjlG[p-&[IVdeV -3e4+5l`rF0M!eX"FlNIrQ"m)G!i-Mr9#EQfPX[9hiaceT9bFGrF-GV@(rdHq,%H& -jDSEUQk*8Am)DJ$AXH5"F*firFYZ1h-KJDe)@9a30r%D1l+EpEDc-6#IXF%FfPVE -6660YV'lr1[$mi3lf0%dcE8IIhcH)MRCC!hJ0h*AjI6IepUQ*b29h$fa5b%2-Bk# -kDfMSaY,"3c&d4)`EjjLlF)kj0iJV!NiMZT[FZ,0i2"S&kbJRQLNDl5*4b1@#pe2 -8med5lRY*k&%+DS+#HT!!JQi2"6eZ%N(NYY!S&p@r66Rh24TjHU"M&fiZqccN(N0 -@2`DG'TqUS*[eZe"AjiN1)rfaIQUi9EK`)+R'-BH[3)e5jMUPc"q@FK(AUJ,q*Ia -&r'I"NH#H4BmLHLe9Jqp#(ab0mUKc`+'"G46a,e(eD`9br4Bk0HK9dHU%L&UYcVd -#"mM+#hcD)-"VmMmD&'C2V5S)N!"rGV9"J@ER!*BE-"hp+Je+p()$49GmT`(6Pdp -8'LMk#8F!0j!!%[6MqBU#XmH,S2[pj3E,Xr1JjbX0LV1"1G$*M`X90`K3IKCdFKV -kjkRJab0b&-*(0'#kiS11PNc2+clEc!e!Rm005p'9+k$2PZM+-Y"Rbh4D,M!pAk' -I+*kM(jpITE1$Uh4fm&4aK8k"r(`K-&ZKmdK`Nhm1m!Up2(@9&p9bYG'eSLQidh2 -DrB0l(Zb+0SRQB%rpICF%@m6'+1@dA#$IZ0KC1,b%h$NVj@(CHEDaf,M8@HKFh*K -A3F*r`0%N-91-qJ0+C#%rch-Cm2Y9*XM#[!U,j92,+L5@!mICZJ#2'@C8cGpF!Ed -#'%'dKUUj)VGHRPF`&HF9M"#UH&VbmNVRiUUZVk8,V@(mEm9DYj+##13UUPTrIqP -+baGDjfCE4hI6Gr4p1*fJeNlUEjEEVGlFYB@HQ8CH0"Ud4bLBM@@r"Hal[#6a!M, -FIdX[P$l#5`h`hirdlKZ"J+HcpL&fiBeX1MZ"qX2Z`CjHdM4pjd!2pK6Y3QHTd9U -FT8Dl`PPTY"ha@!+()feh2*CPI#pUaNFRaXG`d0'5haa+BEh9i)'kFC1fF-YPP*0 -bL1KLB$K[+Gi2JD'[`QD!EAGZiV8$`$cF$laI!G[XRQ$-mdYJNIAhUakDYY"G+2% -@`-0@Sl#hJ@&4Ne+3!1F$B,YBDah9V!9fUk2*blf21Ifm6H"Kc9*BLlCJjZJKK@d -$Ejq$qDi'liL$'GH"GdF*ZaYB`qYjjFGfB(j(4qfY`)Eq$`#3!`d!'&9`C'&dC5" -8Bf`J8fKPE'`J*L"6D%aTBJ#3"hL-!*!2!BKU!!'GS!!!,`[rN!4"8&"-BA"XG#% -!V5`iU+qS`d3!!"&B!*!'#N%!N!42``#3#2IC$-$9-Fpmq`EF+$GD&)"H(H@HT9q -$2%fZPJ01Vil3jdH[fk`MR2"If4UHTUbemrCkdMUkb5E(eLhKC"2qC-#2F2+m)jX --q%HfC0-f1AjN(aPXF[[)C#@m)rYB6i[b-fmlL!hN!lH$2&YjAKlP[aB!80@hf@E -lb#E(b'd*Ma`RU0J%&4Y2!(63fH'*""%&RbF+i"82f0CBLab`TA@hE8f0TD8pBFR -akDQS(8Y-4H)aZhClFLaL@h)d'TFM%eBm,TY3ha$E*3hi')l`Ql*("NBE!*rlIR& -qrj818VP6aUDd`ejfQiE&Y"a2a-HXP%b-bjR$Date$U1c+4YDe,fD9B,89PZpP%V498 -HY+h#f10L(d*3&GIMSRUNfY%cKREYX5UMpSeL1PCT@kl0CRFL191CLSRG%j@fG-h -+MCXfA9%YZb"lYfk'jfbA&$k8h+Q,'CF*FMpf1eH2VheXcH"dpfK#TUDjHl'd6%G -6XD3Y)mPN2"D0m+KFaYf6Np0T@il(8UKL8fNlJQRTJSBeS[A369S9rXqBF%Z'qb, -TXHeG)h*MbmBfIJ0JZB2SM##$A)*EC!)6GaB8h3Dj`9a"C5B+BimQPDR691j$XE+ -0+LCRl%KUYf@R'4Te)*2+5@c6@L[)Bf!8$+SJViP#6'UD)*qII&4$J@3bqJ4QAip -mbkmKK-H,edqQLF+)XbM`J&Sb+H$S-ald8j!!3Z69fSJ04eZS*6CJiJfT[!N"E3# -pT8VeT8Q9MJ('Ur`BFM3J2I(%5'`53`3R440I3N,P@DF-EcA9Q#MJK#1*e"IUFk' -qB*h2@D)'lhQddN5K"k5F+Y3LRHp$8GG'ISaTbNkQ%RZXU&e!Kah8T21GGT564hh -Q8Tq4-'JPh065"5B+lFC,I[8TVI+KU'UMmRKXehJXEQQJ$i"*Ua`2ASc6KAkk%#h -fECf1aFINGMX@6cX$G3(H1PTYSN!A1D"*rBdZ%LJ`BaI4MA5ph$i968a1@P1f$Y" -i""PMhj@3!2(BP)A86MLXK*0'R+D-FfJAmM@QmeAH&CQb(FqVmGD60&'82(p#$3) -&2$I3CVVUM#KEr&Iq&F+mJ&TM-6Z"b0EZ*0j'@Q1L+,RlQ#i@+1$ZBZULc4*$Pl4 -5pJaDP)TD2E'8E*H0!qQ*bBJ9EqqapPVa4*)EhPkBcR5l(BeIdp,@$NrXF3hH5kM -*4&(bq&Hk9+#!adYT,6A+Y'9M423SFJG,6TZ+,-G+%pkeY-j%8BU4Me41U)mi4R) -XX3j[-kdh84Jam$Qm,U-0*JVA3%(b3h9+IH"9(e*Y5m6DDbH`)%a0aq0%'E!ISQC -m3ThLm2U!$@`S"RNVY4M%Np0+E5B+)k9T!GT)PjXSd*-9`2edKAVIT#Z+K[hU,h5 -PHXq,XVBP2C01a"14-6CCA#L``#(XVb6$@F!mkPfkbS[#lH@3!$,T+K)*(EIPkKf -IHZGFJKRU2Ck"plPKPcYkh1UhIHTYUQLM&G-kaZ#K$Hqhk'S6K6'%F3`L"+kK65B -+hFpU*%dlE6C4S(q-VeCrTJjedSH5NhJAaf*a@h(3`X*L8!I-AD[H-ZPDT`8eG)& -kdkIHr'V(-G4E2'FRZ@fEPp[fKNqp3D%f+NYCpYj)A0Fl)R'60MNDf&R8kcleqYR -@ASehLeS`D3ZjEi&+!fDdNm,UK$TZ!M#f)(`DG+TY09&S*`h8U)lje,&cEVFk5`% -58KeeUD-N6!U6kbC3,UAekNr8V9lcSN5-)&bY9%SZ6l86)bCe1aE@)Bpkr05$(D, -Df5Z3!2fFqhd4$1qBMMIe'KFRH)b2-l,!29f2YeHpDP,[FZ5pSPi@kKA@HCPeAZ8 -)!M-B`Mj@T[j)IA5G1S)GTPm!42leN9XG9LqT3qT&RcVme5cke%[IV&SqGHKFq(M -9LepRDB#Z)m1YAU!"&`TAJ!E3*qaC3DTbS8mL32e8(P,cY%%pV`l50VTHcAN"rcH -GF43aS)AQBN%1dIASqh2U@I@-1U$q3$eHp9`K2,hUfDp$ekHH1C-J2RAJQi6c`Gf -rJk*5c9&Emm)ZhUKEprK*p"iDHVU+!Xh-S$[ANk[hm2DKhpdT9P2&ZMdRclZCA"0 -"MJc3r9mF2riNfY&511$S6@dLNV,'j&iVaEHAiTBi20bY%b20HcS89cUl&'EIL`R -JYD2ikC6!jN[BNjb2VbL5IYVC3@)reL6#QN"LF)GDE(AYT9CA@mIM6rkXVkPq3cm -cfMTQ(f98YUM&AfChbeDAl)JQTqbZ8bVIf2riNihh0G9[#iplYMfPmVZ0[5,NDQT -4R`cH0MJpZ!0,N[rQ"eXl"SG'"q!f-eZrpRET(rFNACfdrm!GDe[pqaq@Sp,c`Lc -90S5TYS$9!D[ErQ"VMEcpXGZfC%D(eNkTr,+M`GqSd@fdZjQG4C*aZl8M(8hDbBE -CCRDhZ`SmIfX(pc4*Xmhl2pNj"%@lk!'m1PCPIYp0[Aek)M)$hB0V02))maJSlaS -H[U&`9p%-!iRMaLASENPdE`KR"9aJ$$HjFFlai0!9UU'-E+4`Z)YN,T-*h8pKc`p -)ZZmPDB3T*#5&M"#&h"i+HG`N3`D&TD"-f2JqCGch#2,d`%HrQc`l2H3H3hJr$Cq -#,dr`cIjGU-Zc42Z`#@#l&6L&Z("2+FI0L)p0p8TP1TA+lP0U!@Ha(0j&[(QmTm& -4i*k'4KjDLqAJZk#$fe3@G3Bi2,#220j&+Rml4klI`UH!Ajfd6SMSAH[XPq-!@Ik -#ra!)mKEqGi(F(2DCCB%JqHI1#14SlL$!SJ$6S9F5+0#,!TUZqBi!djH1P33drCK -MJ!@8![eSYZ6Jp0%mk(jr8@"TEKldE%NJ2aFm#$VjFIaLJ5"Pjd!R4p!r6cNr2L, -()IS)!DCV2ZL3!'4k9[1jc5`!qN'F`$4GG`AdZ3*GY`cdZ5+GPR*-cjESar*Rk8I -Rcp#jJfISh-%6q@8k"E2cZH"FLFiM`5,r(1"PHR(U5PpBC!,K5YN3fZSjkIl423p -eK4YNBkLRpVj,3NebGCJb)K2-eLpdj[BY)RG1+l92GCkZcpF[GZBk&eCRGC!!m"Y -d2#R-&+2qS$DCbmlcA!EpITd*+MH[`f,Ta*)1LDAJ8@jGN!$($$1UjqpJ$PT"M## -NiHTJRU@AjM9-qAN0)i4+25hdFUYcfY9RhX)Tf$6rYh&9,BFLmVQ-bUV["q,GZ8! -Z*$HrI2&ST6A'$mA(A)ZI'ka3@$#@VrRL5-pX2HmGGH)"#['Z"1b"G$6pAGj(H,G -"rC24hTfM%(iUEFq`qpqRNqN*e)HkKhTk`6ZqGE#(ej92RGe''-jZ)`,1CL0@aD* -a(*4%8bbDC[abe)a[Q4JI`k&(E"XCZ+8ApBj[$bH`r)TGP&&UQ(Yej"EXM[V1rMe -JNRR!ILb1p(@i*aMcR!*[Y2TqaJ)h!+YcH"85'#*3Bqh!B%FT549KF555`3+MDUM -L9[#`1E''&pVGKadpEabm@`Zml`$VTdFdaMhSF$"I"PMB`FalSCdVB!I!DhXhUr[ -a-$#2mjp!B"EB0BkR`+q!hI&r!!d!$99`C'&dC5"8Bf`i,M"PE'`J*L"6D%aTBJ# -3"lG*!*!2!C,[!!'SG3!!,`[rN!4"8&"-BA"XG#%!V5`iU+qS`r-!!"(%!*!'#Q8 -!N!3Z@3#3#&'+$-$ikjKR[MelZ9&ZY#LHAKIP4NZYFQ!dZGTPF[TGp2PTYeP(11' -8Vfc0ARCVjj(eT(9ZXXQaG8XifB3rf4*qC*0RK*00"TX9f8Hi4jj&pT%C2r+EV)6 -RN!!@V8[+"qP!2SXe@[Pb2+2me`lBUQqcl$TbR0b@m-Ka-Yd%04Y2!(63fH'*0#) -+0"2jm@Th,eUT2j+ZTJ2-4)Y'J&@HcJT@YJSba'aX6`k&VDJj%)Q[Efc5`HN2Tka -Yh31e`TI['rbElrIRGPeQ)iXIdqM`3A1`ELalB'8A"8c85Di08D8JlBHSUP"A5hh -`jUlXL&XK0He(XJGkEqkGq-93BR!mBF@'"`Flpm*4l`kL(R"(P)13!ehCiDm9ldP -&alk5*,T09DkcA@*m++96U[0QJT`("k9kB2A"PEd6Q`B5CQTLh,4'BfNc(8R&NTB -C6LEMX8MBLLA',c(h*5E-XBQdC3l(8UKLifNV()qEEG#)EP0kME#e226[-C'@r,% -cR"lDhVE0A0HiVNPH(eK12cUMN8i169TN!02f&"5G1MR"A%4P"JTpYb+9mcb9He! -XDk++XAe@1$85YG)#$GL3!%(PT28SV6*bk4J&R5V)ED$3aK40)iqA2,58M#[@ErR -GeYLZ9$LeVr&Kk1"air@5BD$3ik)*h-Gc"[PXHF(pA[+,I$)C15Z[mCai-2!'D,' -"3RP!GfN*j`eDBRX3I+NA$XiK[l4J@f`-Fi33+VV)LmCL[*AmT8'9YJX(TZ%FrX+ -!UR)Kq$)[,4-AdSPrZ[J#,[K,X9+'pebU-P$!LZ3FmHFmUr(RSM-V%P9ick2P"JS -eD5jbmprTI!q+kLEbBYj69M+9f"f0@!@dhdB01YrZKiXUq$-(IdDD6X[KTTT@'#L -8'`mCr$Hk`)0L5419af1lKQ2aU!)k!4KdJHh"Jl'V`B2QHpSRB[%KFlX9LkIYd9b -"ek4D!`@k+%P2r#R9D5JJ@dIAd4CcqhJN-6B@(EH3!'94-aj'@&Qh*XaiE$bD0Uf -%c8VBX@BQKK@1N6'(%r'KD-U-$DZSZc8mEYQHDr'ZT&8'LT,RrkF,046`I#&YS-[ -2L)V&Ei)d*R#dL%D(BPBLe@Ll@i@hRLib8*6Fr4qYeP$!h@TUS`dQKLiC69Rld+* -8*0S45jR0CPehHR3X()dhGd6h4Z1*T$5mZ6#Gk@C,E620GEE(Lr"H6!d'LT,(6fL -0KJ)Hem"PRCQ1@KJ40BV5`C,6qL,,YY+!pa*DDk!Sa8L12pBi*c(bX8LXaGY)331 -&(J2IKdPZSR8'#NGh3I)MrT!!2h$c4e69')lZY4,B0-BRiR'L$0Mh83-qM6q8m2T -!0S*eaBdJ5*IUG#P-r)JZ-e$S+8AcdH9dKB%#29N%h%YAm[X'A9Ndl1AhD$fIGU1 -XDNc[5bILLI#3!*JXELEKH!aE`hV5l8h1aAqPUp`SR'i*+B1Z)LfK8VZFhrA`Zpm -QQ-kRC3EHPiCGBHY*Upram$Y8d85,*P5-`F0PH*YTJi&#lm-iqT&Q,A5eJ8,eFbR -#Eb1e'LM32m&Am0X8iVFm+#@*GdNX&YFH'beX2MU&B+k0hc33(+S&PA3H[q(K0lj -EPR4q8qEX,@PEkd,EA[I`ka4SSV*8e0SEMUYk4cKZd0@fKTm#212KQE1YhB#hR8m -Ce%l1'k&5LiRG4"emNNmB!250#*pDC0jQkM43+#He9-I(2Acm@lHGpP*34b[j03H -r4TT"(H5i(T5,D!hrKDlK9pdS%5-)efJUC5j-Y4dM"PeM@d!!8THAZV$G,,Ah#Q5 -rj(jR'--lT1+0AjALT)ca#8&158q$H,ZTad"4LVaAq'@0Aa'GPd@L"qm@IXQJ,3X -5drbLaY-LmD*BH8P5#Nar!&YE'IqCYY+er!)Q[9F$L$9a+cRjH6l'8rbFKjrrEP` -pI1b(EFc$8prQNjZIqcjZIA3Yk8iq5Rd1&%iIp@'ha$)Q@qib"cUPqDLAbJ-m5H[ -i@Ak'qZNkIYS0q$m4rUbdrKPTElm8ek(c6r'6r!3rcSp4PjZI+L5XQjrm2TNpr-5 -CQ2(`icr%S!IZrT8QLrPTDQUBf58,I(#hPl60,r3pZS4m$F+J2@[)XIR&lAf2lG& -@8-A&Zpmqj`CbM2SP9d$hIR(bj"'dBfhKA#6VA(rr*M-m2Q4LIcGa!dJVF*Z&a6* -LTNHMFHN9GR1eEf(ih4J!@8f+RiS*,0f%rF[qj'4MdQpE@dJlM(f+X2Z3!0DlJfH -$MVd8G$5e2($N`FlkQV9G`QKU1I4V3Fe'R[e$GX3-1Xb@5(,FD[Z)mh9G$abTZl1 -qTLFdl1TjL2-MqPiYi+K[j%rPC#4(TD$hKRZ$,Eep!pe`QcP8XhV3p!klNSj@1[c -8,DZ$hX1r0!G-ec'FV(#qULTJeF#UYpmEV$3($pkm-623YhUFm`Z1HKrKJ4iDD4" -Ri@6F#VDN)dNV@AZS3Gb0,!(2'fb4RLET8-2K6hIf3G%UHJ#[@P5&hhRpjNie%CR -Z6EdV&A*!H!+8YrAhEbdFF44$4q!iFADkc55k)i$6!mipZT1FZ"fjA"S&+LPMeP% -Se%CQ,T-*h%8Kemr*G0j"TKkLJ'C53!p3`1QLJ-Y*CJ!VP+P4*U6rM$,1fc9bGF" -(Pj0F1ehN(%*k2`UIQTbji&[m1e#ACiRfcmJZV)iT$Ta[j%SPPkdDjN`VFhBrm`a -ZF$QmXhMcH1I"BA$RSC'(eQ`jq!lSi"#@4Cd"$JrL)iphPXVIcC(M6r#T`Dm+@MY -%e$jfpXY*J#amrUm%r,+Zrd-J0iP0Cd(!6pl*-`)jQM`+X#JJG1L9"!VdSS#L+li -Y)25j%b8"46pK'a!"CY#2CdX1jSrR3IGkL`*cNe1JCdX#q8Rr8G$*LcZE#2JT1`N -kfB,H+FTjm4(C$Y&(#!KGm8'(T0#cLLpY&J(3Mq,LTZLU+k"2&ZLUCD"2&ZNdPa0 -kYN3rN6p,2cjeKLiG2%1A$Tl+,p$*Rjh+q5G,G"N*%IPkJ"ISaDNVI5%Yi`XY0QX -$lDkhRIIIIPpEU0DX#h48hAPKS0jF%D+-P[&RDfCDFrYRN6[cc2ZjGEiQAc2EQQZ -G@C&935+[hrE%Q#P"[AjP-THGNVRdHldU%cJhTF*LlY5F#SNjrh&TR9r'$$1UjZp -S$PTqM##NiHTSAU6RTK4-q5N&)i4+25hdXXfq)kZEFZ(ZE"6[mrpGZ*BXC#,LZBc -+PYi&a,ecKK`)ERRP+$*+&qM[kEe5Dh2k(8@j-hm1D0-GKfTNlDM@lUD!V%V!lNj -(dMq4G84@'p5r'GLmF`$#$k@YIGKpkBPd-Mf+qS90I4fiEp$*pYi1f9BqXeFE6EG -A'meR,cEDmPJNMTZ69Kq,T!@r&,AJ'dH(Kh!,dRUfGGqi'I@1(rFRd&eY&f@BX8Z -60RdMGK"edrmTX&A#!rBVEAVVrFj4`5TZ!QrpdVX%mcd-E+$!ZdHElX3DTV!(`F- -+bQa5a4&Y1Tc"rX+992%dH&LF4--0l8fiB5MX9I"Z+["1`ZYppTm9lY2J0GQBjd2 -Sj@c-q!4HNcEQZa`DYpKrArMQSAh-rLI"A`QHDA[be`(crJm!)5%1G'0X6@&M8(* -[DQ9MG(-!N"E4!B!#BJ0h!*!$!3!"RD!!N!B[#`#3!iB!!!)!rj!%!`#Y0P!-X)6 -[T3#3"3@H%3#3"3'RIrrArrX!N!D6%3d0$%eKBe4ME#"08d`ZZ6"PE'`J*L"6D%a -TBJ#3"`M!!*!3,`X!!F`h!*!$&[q3"%e08(*$9dP&!3#[Pr(PX)6YiJ!!!4i!!6% -D!*!$G3!!)QfB5M6Q!*!'TA)4!!LbdAJqT3$Ldi`fC,5RjQK+Ai"mIT)55NR(rQ! -RhrRBieJEr!(4ZNIl*!6+H@RGIKmki-8R!-9[k,6f!G5lBNkrLTCcYI[RD%XEcYA -ZQU-YUc9A1cT(1l[bA%fISeALZGUYfCUp2jR1V['eF45UEf%5!!!1q+X'1FM2@@C -*qAQG[4hPGVfac3TZce[V1Qmc1cHcbkm"fbYEXmkLlqhef55ihq[YK0Z%qq'Hj+" -1(Y`2ph8La@YL)kqa$5(C6q"qi6j)i1f$Qq`MQ`&M!35-[miZZpCQH1EK+EGhX`d -*lmJq-YRNf(kfm4X#j$Rb1h`bR@kc,#XQppQ@[@LZh*GCeS5[L6eKbm-lBbaEcdh -@10XkF-"e2(!!*f0k3#(LLepX@9YIc#FqYM9KA%1k)j&-qaP96N`U-0'q0ADGpqi -m*K2H0V@SH'rEPXXRX[NJ`q%M26!f8CIHI5L&-6`ZNq42F'VKP-@YcH5'42++9+) -jPFh9lHa0`*E)AP66Gc8chf&091q*ic1*j0@*(DRqr#HTIeeZIh[9rm5QrEPmUMh -HPXMP8VPZrh%VGRFdY`fN*p9`RY2N1c"bU"p0LXepGrSER`*5H$CEEA5"EaZM0YV --YrA(LlPek-a[Q[1mpX$UY4ZfUGqdX*l4"BGD+CMjYA04`'#!eRNX,9TSaZmj%HE -qXfA09hX988"%+bChMGaMj"iVYi#d04kJNRZ#h"2PRJ4'bAfLh&2NRLVh0,P2NRZ -kh$2NRLRh,,PRbce(lVPbRbch2,P2NAZqh+I+$GLI*RHYh+I,IBEF#q4H+2HCFTm -Ppb+jcjEl(,R2PAZah1I*IElFGA*I)2F5Z5q8qb)T*AH$S,YM@5rhik5S8R8$ZpK -lbUrdTA)Z**XBcJpdZX1K*F"#j`Y[HJKQS5"6"-1*hhL9f-XIh9A%FFmL(@ISL@- -AU*mQP+"fI90YBf1m0Rj"I2(LZVIGcdSZPE1mXA%Y',+PLa,pkC!!MfIFC$r(RK$ -lpjd0j@Ij2`U8`(%Z%Lm$ZXAbAaKED,fQCT'K5HGCpKBhVKYaHM(QJQ*Hp,TTF$Q -V&33jX"3A$*p!EkRYfA)l*-UbrPAZ#@Vl-,fUYKr!P64pFTkXYJI!NG4fX6bQU+e -"(P29eP`J%2BqHCbNY[qN0F6f+RR-80Ylj6&6ECq6abber8JHXl99U1NFY3(PFpA -f3(QFV,CemTLRYU3m6P(EIRNBq"IEFq9aUYTH)`rULBdDR+Df,mQM9QdrPFITbZc -ST628KJmpL)dq@+Lf+q4aTYSH+iqce,CE(UDcaAC6!@eVrTXmcP%E06KAEG4JXGV -ZNXGjMXfdqIPUSkCeDJ-$,P"E[6b@U#fK1)i0R#)1YKI*Jpl"pKCj2%KYRjE(JpA -fIAP3@b#&a"qL0[*HUMCL294YMj6(-V9"VLp4fj2Pm6#e[93HrdjYEjA(`pAf'D" -9EE!d%9%iim#Hj@UM2eHSMAcLDYXN$fU1$FUq8Qh2P-FUYGdXMm[9pLjjd+IB2Uq -BLHdRmPMMf-D$LBp3'cd[r-(BU#pBKke*(Q!10[*@IMAq1I*S90XEj8&IB+2''p3 -'YK%I+!DA0kS0A+#Hf+M[P@VE*Sr0DRZ52,DSl6r,Bk[Dk+HVe2CCH6a+EG6edBj -Y![Mq',949c!+'re$MYM!Eq'0aRDp2-!3E263GVAG)Jm`&Y[Aj8&-E2pEH3G8!Jl -3SMB`DiIDk$&9GbDfbS-Efp2NX8YYj(UefX"&4$CXhj!!K`Sh%hmPM`l(0JP-8R9 -X%VL684ZpmALelC&(9QhJRmSlNqJE&DdQd6GJ0EDIbB1BFLE$BIDU$Eb'ef!$8q! -Af1L"Dp6f&(NS,j`-jX'rX,eI(Np8flIN35r,-C6U@VA"6j4$RJJQJTrBk'Ib`ND -pRUSfH"9pLZd0mU#2X)(P6eFE'(#$BjX#"[`(YF&2RU%fm1C'YG'hi#FfFS#cB)- -[rNHeI8)Hce)E2"GH+@FUf!N'BU2[U3mfm"6qKBdqIjlDb1hjDRZp2&kJYY[Nm8+ -er9!Hrq6BTS'Ap#mf1*A4*-3'0hL*fX!DqJiE048&b0KH*`m`%pZRj2&Ie!E2qaI -(GK+F&[c"4Uqr6'e`K[qU0[$Vj@UMPekKYRq6ab[9pR&j`1q``DIK[(+Q`b0IV6D -i)Mf&$Cj$I'cJ,r`8'hMa@V94DfU)$GbLAl"p34ld2MEi)Va$cJakm8eUSeIHV$B -i%V`2'lK#,YM!1"9BCY#VEeFEHEj$E4q4ac[9"NH%6mQC#8GrYpVJ`qp4'aJ'KQ1 -$Bla2EH!QH)J0[2L!fUMl"pAf-AR!0E$"#fpeE!KXeSI8"[DMA@#$Ve)IE2#ZMkS -02N!Zf-!EX!8EZG+Rf2!"dl$pGhPm8QdSA'#&R0P`8(!9'l`A6SF0rRDlfZ!BGkL -0ZX)TX)%&k"[BU#2F%aZFK[l&pNYjI0'acB%rS30JJm0r@@e`bkqS$Flc9E@"F`` -HB!0(lP3E[3&(`iB2q@,lZ6bqkGMQSX[!4l#K+AaEEI$HlkJ062fZfZ!N2@TUa0! -C9&`,DUZVhTf86lD*9YV3Y,BaQfTTh9HhNcYCRD23+4!["AZK5NH4,JFL#i%&X#' -XJ#P%&a)%8B@J3T3K$a"8L#Q%&#*+Ld)m)C`363JQa"*##C'%3%)F)G53!%E))L3 -43J#aJp""X#"`%%0)#331iJCKJcJ#k"!fL"S%$@)')B1)3F!JAK!ZL"B%#f)&SB* -)36!K8C!!$NJ6K!"#K$!#@8%)3@#"6#!X))!JI#$!),"!#K%m)'`)(!JE#"S38`3 --K!X%#dJ"!JA#"))%3JeL"!)#iJ0%'B)&XB*33D3JD"!`L"3%#Z)%JB1-3C`J6"! -P#",%#%)%%B)!3A`J2*!!'JJ1a!C#!p'$c%"L)#q3!"D%084Ma'*%BK@@MDL-8!b -*4(K"I!BI%@)4(e&Q%$%3"5"'#,&!,L)+!MQLGfAk")%#`4b4(B%CdSLJM'L-k)C -`$%''r#0m)m*!cK%E)(f)64!b"(+%@84@L#d#,-)Z`Ld#,!3834,d4YK&q%)B4@" -&@)9i)k3L,##1)2!Jp%(q%8B4Va!e)*H)S!KcL$53!$l%Cm4+4%V),D)NBLHN'P% -5-4)4$RCSfile$83SV3K[L)Q)$BL-L)Z!MK4ma!4%3m4$4%+%-N4'4#0)9B3P-3!P8!M&S -i3TTUih8bBQ)YApHdZMCHZlCeHcD4h@pYkQMG9pZd1j0*bf4FBVZmYUAfYHEVNPD -LV5fGj0f4Dph@dYU@bQ(-YZChmTEKX5a4YZG5L@`5Pqfl@eT5f@fYDE%PNqRfpN4 -(-kDG#GFThC&,Yk8`YLI),#R*Y#B6EGZbU4fYiZbkjIGR8[*ZEXfQNRNRGLUElH" -0(4`2eq,%00C-QK+eY+86HGF0flEf4(lRYKeYZe-dJ(K*A40YC0Lq2CI2YREX`*4 -UGelE@RCh*-QM[6@AG&,052b,@R)iC@3DFT[E'8@MNfj'NXQhL1(a1@NNH@HG(XJ -P%afij9ThG#6D-,KT1`BR6E(PdfdQ(TEG*Y$qA+TMMaMbVHe8c$beYXQ1I*[DC,$ -4,IRZMYCF[VPJh1HDLU&hjh-G#C22-JmBkJ34,,PV9lH$"B`M@5XSEVUMpST8@mC -Uf1b-*aP2-6BQT+aYaVSKGBdPlq@jGQY,I2fU9Ai1M5Y,jQ80qf[,16GX,6KB(X9 -Aqc+aENbf98*f1PP0UpG[fL,P01r,fp,E%fedUc%hT$TfHmC'1M59GFfE@cZDdh[ -a,UCdmG*(e'@bZdUjip0@cPaFr(l"h0#iZ@4f1dD0fM&BLef"H9NQNhaP)EG+N8d -R5"`r"0A)TI+lfM0e&%G(&8D11fJ&Yh-(VH#,lU!92-dGY)+$ZB0@m#jhd!Sqj3j -D`B[F35[iN5[98!ehd!V1VB0@KP[VS*AKccTSCI3'(E3bHS%1@KNY3!HY$-rA35[ -$RAA3b["R(E3bI&J(V5`'8(63b[T&J3rEj+b$9MBq1QKP`eeed-U'UqUJP8dIk+# -9$Hr835ZE2Y""+a[ZU)0@0Ta2"keXDUq$9MBDJ`jDf@J+1QKPSahSS*@02U1$9MD -kL`jDfHJT1QKPSk2SS*@00U+$9MEkK`jDfI5($PVCD!XkD'@M'HLJPFe!J`jDfI5 -($PV&`!99bf,dT!jDaHJ6(E5+NEm1@XAJl6TS&B0rkk"9$'c33DXB2&N(V@*`C"f -dLX'(GG!U"MESS&8-(8S(V@*S6MTS&8-ldN'V',AA3DXBfSS1@X@SX3jDa4K+d%' -V''+`$PV9J(FkD&8$MZLJP4Pkdd'V'ZUSJeCQk%d(V@V3"A63USCHed%V-`#RJeB -eD%3kD&@$hUD$9MASC6TS9B2@TB0@0HK@1QKP"Z0k"eQM2JkeTVISAc#&AUF[A'd -*EZ,V5q!,h-,ASZ!1i$Hi"%H!'i"c[Ti%rS2lp#Yi"FE6ar3iH%(rJIqq9UEpE(S -C,+12kAm`#1bRPm%T9d-$bhcG#j`$1qKKF,fU6B("[LlQDQ*J'aJ1GS20i#qi$"k -$`iU9%3#(['4dZM#8DiMHfMGHrhe4UXl5-C+)YV0+)+'-#Z[HH2e2[RRJ`+H8VdD -d(AJCA-bm"3pNaL#Q3hH&8jl`Mf`lih5KKDljF@p(*63ZcUU,QZRG'LEhd84C69& -D6h(mh,hU`MR&98)6Y,cG`fLFRQ%dFrTAC!M#6Pf6f*23I6aeel6UB(IKA,@kXAE -0mL[4%56ZK)C8GNHUG[h`&U,KQTYe)44K62hDblFNVfjYEXbQGfeZ%TQj"1Je-He -VeXEia606GG%6TA-&j+l&6ch(LF,,Uh+j,Ipq)J$@6Ihpr,NIJ!#c&1I)Z5FrGJi -j)"*eN!"G0%MIMT'&AceM,i8628#%IYH0aDbl#C0"d`hVeqZZ$qI8A,jKNbi,XH` -TRH0R)S'Z@VefTF#"VHqB[Q[d28EIBr8p6YrMpAf#[LISHk+q*qPlXVj2e2F8I8r -9pc4pRk6[kEbPN!!ce$j6hl2d29[IFr3p9pmRkhZH[Nr4phapRkV["qMl0(hAk[Y -dICqKl`AkAUM[-r9pPViA&GXU0VNdaPGSNV2eIBkqcpAhBRfITqrcLmR8R0#4fQZ -QSm6SGPfG[Lr3pa*pAkK[(3BC@&H'&(#2Q&m9mK(`+i+p2p!D$U#k3VXVXM-`J"L -2f1i,l3`Pk)",9-)jfP[X%V1GIT+(,&TFYN`'qA4!*TVY'+ilaSSYDdMPXqQpUHc -9ZGUQ[!bE*V,0,VGb4MZMcN$#E+i60B9499NKU!4`Q@iBAFC+`DC-+YRDdKTeaKC -X*XhX!4`3G@#2['Aff2@),X1"Q`8(Z[P!BHP`C*TQB+m8(+LaDYJYUkYPelCfA*h -5jB"(cj6b%J)CXUJN'ZNQ3MR(A4IKRI['6D*Z6J6%$!TY(!N`5a0*FQ3kChVhYTE -YrRa1C-9dMX`04!"N'"0@k5jfL35Seq(YjfCpKb%CC[6"[(XQMb)$-[PGk6UY"eI --L`X+,5Y9C-M3'L2h@,RCq6aHlK2NRL$h4,NRb6eClK2PRL,h9,QRbAf5h02PRLR -h,,PRbce(lVPbRbch2,P2NAZqh+I+r3#j6j1l9Zl6j6j$lJ9b,j6l6,R2NRZ4h'I -,IBlFjmUp@1lcj$jIlMUj,j!!HiRF&jVKNjKXqA'AfNHqR*Q,iZ[V9bkUA95rI10 -bH6DZMQr896a4+FF9P'511`T!8(,hE*914*fJT#Zd)Re1a*@J&$dKbd3c(+-Z4!P -)1,qAHCb*Eef'&l8c`qaY+&Lf3JC4C5PXd@0PFfXql6ZX5RINLqD'eBe0YI&dFqV -b9%I&c9%AC'9Q4kUYiX['$pN-klYPiir+C"j6Hp$PB(lUZ6Q4lC!!jDXjhc@aSc9 -C'dpNDXe5%`RHRT(0XRi0#b&8!+Qk$PDS8Y$9'fVACf3eDqXeT96BUe,0)Kl[bN" -fQ'i3Z1bZe,kP&aqX2PjGPF1T1e[eU&fj,jp0q'd5hjh,TpYV(j(D[cHGEIBpPbH -6+HQE4YQBklZYf0hDeYbG"c*5I@Z1p6(Yfm[&+bT-CDIZ-MNl9JmfJ10iX-hMUaV --5YC#TCh0V!Gc8-q$54L5dY9HH2@9Y$L&9AD5CE!9MqjH01YeZjTI0Zp@UpD8hTe -0TTS5,5P**GA5f8,G9GZBN!$&22RDTP3qheRP9C*CE8-LNc&q,L)BVl@bD,L%ILL -$cSUI5TN-R-RHRibXrZRdZV+KY!'i'eYmjc+mq*jG&I5Gbd8XZCD4bIFXG8V&XGc -L&@qhbbYqAPZA#Yi*Apfq"I!Tq5U)q6jP0Z&lPMU`bl'R-$hYHE$,IIFZ)$hSh&[ -1%Ta@(!IEc3I9LTr"e5kRDUR,k1TlPJ(@pkc`,Yqh4,dUMY9bq35XF`Gf&b*@r%Z -J@('Zi',&[`b0&Hm51PDFIB#XqTDDYKT!'k(U1Y!,CE$XGIF!TX[GJFb+@`Ne+mi -qF2EipTI+KFq+AcH#9L*83,62Ik$-2T4@I3meCK&3UkjJDSpIAaH8N!#eiP`#eiT -c*lj@h(f)VIVfeE#NG(3ZfHVQRT8!CIjCmHlLS*8!R6bdiPlQSKA[%KqY1TG*8M@ -#bcbU[S00dFP2Hrd,T+l,AhPUaDr-95[H*ElDica3-)qh9K`2FYG+L#lqfKGJX0` -P(PYe(Qj6Rmp@I3fRlA(XEiFbYkeiPrPYaE[#F5[q*CjEGHi[C4m-kdKB!-4ZL(i -SG[f(`0J0-3$(ES"q3(Epqb$CGqr[GMp'Gj2ihN'E$%"c18)9VE`)AI$XH[B$Y1[ -I"p%Ppk(L(B4Ter838,Y"KU#k-d43rMkipYh$&Zk&E0ql%l4,VS-0dJrFVRmrG,[ -qJq$Y4ZL$EpppX,#$%$i#h`&dMm$f)FJ1i(S)UN1B(S6S)AJHKZCK@1k&j!#1Kk! -iJ1%q#"k&ha(S(B(G)FJ0iAB3D[YJGJKL!hJ0S(8B9SFJG4"1qk&d4*)+"+N41HU -3!"J95&&$3P3S3`f+8%-5e,!!05`rpBT2JI3d*$`&XP1Ik$3U1Bd)6L0bdj!!f"4 -+6B0#8jr-0#3b"4*6)$!0bdY$iY+JY&34PL+5Ml1Ef-a)bl$d1"Ci4-,Y*KiEJEH -E'-%R-QdhXGR$%9fhQpKKK+fTk,69a!iI-2T!40b1DVBU*DVr$K-eFp`rUH'H@P6 -@Q$Z4rpZ5RcqV[m@kr[1eeK2[@$L6IcfG(pYMcGRCh-D["plDY(($!ZQecc5XA,I -*rG-ATrpLcrqCqi0RGm5Hrk[5TVhBm`ki2`85FA"kDaTGFS`Z0[L["P%qrq`3+EH -SPXA,mQ6K-NIrYlY`D[Ml@5F1)9M+(-Ba[m&e1!iE!eRZ(-CKBSB&d'%F0Jqb*$U --!ipQNA3BK`f',*X1il$PN!#&e'%F0L'bY$U-`lC%&PZ(FGLSb2,V-!jE&eQ3!"h -'B6-M5l6$1'a[C0&f')F0Mc-1af%,*%Zl`cKXLQ5aGaL(6C)XrJlMX'f5jH"K($C -5XN!mM-2@5TD-Kh(BE-NLmM!1fbpC9Kl'B8-Q#mh$1'c4C1Pj')G0Qba'$q1`MC2 -Pk@%F0RDbB$f-`eC2PV#(F9"H@03HaQ%l+-[F`cKX%'AKHaL(,D-XK3rMX)Q8aI& -K(,D9XP`qM-0'8aE3Kh'JV5bT$q1`'C9&pQ%FmjZ&Kq1`BC@&q'%FYV#b0$q-`kC -@&ZZ(FGMQb[,p-!iEAbrYMq-Hm@FVl'@(ik!#,MmFKqfb+`l(iBqJiSIMm,Z0km- -irb!pR(mN%#E"12b5qFD9@cE@EHrr*8rRP2jaZqqB2(EQfrQ&q$mIjNC-(VZ'-8h -q%hX8p8`H)lrH`MpjK`FU%FB)km%[@9c9QY'rBrjEAC[65IkL13+Jll1jl(hr`cf -5"kFZbCp!r+fZ*Sm4BRY[(T%Q[h"NeNJ0MZcClZL$rX&brmLH(bFBfI2M"#0lITa -JC-q2%icXqA'#N6dr6M#bjmF*4[Em1-()RKmR'0Rci`3MHhkFB'62Ma1-l2PaJT% -p2di`XZI(#8Efr$M"b*iIKap!iAqG`MM"D*mI*aMYmq-%SheqR'#dcim6M2EjFB, -42Mp1-0VRa`P'qr`i`@LI(bFBlI2M"+0pITaJY-q2%icfqA'#d6ir6M$DjmF*4[[ -m1-&SRamR'1hci`5MIAkFB,62Ma1-p[PaJY%q2di`fZI(#8Elr$M"D*mI*aMYmq2 -F1pSRA[H1pSRA[D0piRA[D*pih6[D&q&rBYD8dGq@R'Gq!r[i3H&GRXRm4G6hmQK -S@-XrrKmkXZQZGR8l)aj8YMG'3q2D85AphM`faqZM!HUkS@P$AiDrcm1Ga%MQFMq -el&mh@p-qdZ`&'$[Ef+U6'2B0kme38Zc(Yj1'NmH)YLp+ZV-8IU!lh$`@`r!M!I) -B,XM[mKLHI2YrHB56"[IPNGVRj1%5I2Zbkfjarh+aaRkLYG#qBFeYP[fMqCGGpj+ -*pR@aci[p*fimq`B[Mq%"R0&kH*-c)i1"NSHZbamXV*1(r00!4%!Hb819$HYkA6' -2!)Q1jT'ek-1Q'ppVqR(VdJrC'kFHm*!!G#X63IBkHpeEfZb'@jE3T1,r'iPcUlA -4rZJCCPc)j*'cGJBil@clY`a3HpPei[5@q2T4(N1-950-*RTL)LLhXfhdGrAPh`P -'q9NZ[cXL)!p1R66*AqV+C1ISIae'Ic"ZU@a[M$m`lX%m)J-BprS9DqkHb@[F2&U -2L!rQ2P$92c$hd6b1-2I42)i`pl[cZ)qjKhNBj[lcQq3@c+jjKB`*1-cGr+#p`p` -IqI3LFfm5Zq(V6ZGkHIb@ZII9idr-IE#`[fIZB4j(Q(YI'RpNlQ%HRFcpdPRh-IG -,CeDBHfU(0B66$!@E(aATBHjh'Tb1r'$F&bqpZMI'(aMh3"kFL!$',6mrmX#,DSY -r-Y*j6VbI-@eCHR&rM2XCdfJH4jM1hARFah6#2$*@1YPfmh1Xf$[1YQCYIk1iEE2 -hLRh@[*[&GRf"%8LMLF1UpB*iHfrqS2(IpGTA&r)3CK%4N!$(%@E49pFr-SX`Ma% -3PMc-6lJ%-C`m8MPVmH)"CN%5UCb#TpL"XiS#i#(R8"iqKF0FcZ21alPE51VDL[p -EI2!8&4ZRBIZ42,fpm`GNbfIppPfMH8`bP'VSGfLR'1eX`cP6l"[@$9Eqi2%VlfP -RN3"ja0YNSi'cf'!J$hFI3D$b'XdV%U!H4UZ+"-M$eDU#2)jU9@EIab!MN!!TjUH -GGB8bJ*PEAe&Q"1pK*V5ilf1`([IdQ@S%VCQKIN8M'16f6KjQh`H,+)lh[G%))J( -ke@J%N3"j'#4hpR6mYDiQ$rCd(1q2#3dMrpXq2Ejf8j13!+&8bl(+XeE$U1#3!+U -K2+VUG4H5Si*(!Z4Ke'YTaGa3(KAeZXS99IXBcU06A4[-3jKd4%!H3PdM![*Sbaf -UKka4+IppDMN2MpZ,&K-98!r4BU)"mK!i#r))mDb3!)GS"-Ibm&6RR9EZ,rMUe50 -M)FB%r9&5R3Ik!idT)L!2dCL1p@ZRaK3&N!"(2QIp[FmQ&ArkYLIJ4'8%GpNr[[( -E9ZbY@kaCGel[HFpqbPY,&5-EXI1`Ira--dm6Zf3Z[,h!##)#mK"'%"'3!)FJH94 -!(TQ)J,VZY$+CBhN8jMi%UBlPdBP8Imf$8jFBaSq9rN5LjP,)BrXGAKlT+)!m*K9 -r$Dd(mFBEeE$K-kq[HGQfbi`+0Ir"$r+mjhppi2r'**iTe*L9@r+HDKJ*N!#(8HN -L!I*`9ESJMkT+9mKM0@XYA9AX8$fU@r!UH4J9+K+JVQC5jAJH[+GZf*R)j0,0qr[ -jd&`('@jrH&3!-N3"j1'T8%0j9,F@9$V48k(qRJHkG#4!A4h%L`,)`d8m)6&(%Br -5pL"H8LCHKZT4R4E[c8-B984!(X+")`,b%!iF&C!!4bBLS+l-8"j(FSp,(kY(L8X -Ibk165dF"j*%eUYJKjL9V!Ja3(qUch(!HZQhJ8"jQfi#-1J9j9,F092)`F`ddrR' -m0i`b%L!2`bLGKKhXMi0E!LTe0E12N3"jF)`kHkbZ6(#Y5hIdDKlZX4XD'NIffpj -pc(c%b&S$kj6SYld'`6Qk'cTLDDr"hdl%dPk$61E3,S'`VN@YiG#jCpHjYarKq)N -!fBr3"b"rh)m`J044!IX4`[%)RBq)"1LJk!$Q(P("6#-"N!!c@J'TlMRKFXJ)%%d -R`Q8lC(!L#,5Bk+$YN!$(6X65GXLM@Na[)P%%@Xa`$*hl1(5LYlC-KLZ[V'Rh-lL -Kc6lh-lM42)i`Z0%mMM#iZr1iMm'&HIb@HIAPm5IQ09L3!0mcVc#2)mbV,idr-Ur -42(l,[(S6L5MBj69d+VZmqNmd!#-`H84+l2)+9hPC*d92D)[ap6F0E5VdN!"Kp0p -Lc%k`5)!meZc+YY6*rCHk`L`L6M6+D-Kr#IU(bI!r'mEFYI8*-SPlQJcZ@ZfjI"% -"aYbe@9lM(Q0CNr%X!Y@BZlE)eTiC(a8,RKf9R'TH+SqcaE29MhQPc!l2F@0+RM8 -rp#SJQiP2`I-k*mq#jjDjPP8V1'$M+AQkRRV1PRYb*L[lTUEGqQDaZAmSB&R-)bp -a2"mp4fba!L$)[FEaA2)0LZ9j[PlZ%ac2Lcp$qTlRf`&)ar2"+m8feR@d*mVMBXG -crjYS&mm6%+Yc2+qG,EEaRLIpSRQqCbBfch02`E2Pkf+Ei(NqLASiRX[ALBfm(Fq -R&$cIqN+a6I)mRbk2'ah2P9qL8ec2Q"!(qjQ1jbAI%SF6AFqaTmTMRZ0j)eJ!a6" -Rh'Tjc(3mEB"XPZXjrF1568clKL%Yk8VTGQ%"mB9LRGZHci%GfT[5dmqaV1F,JCT -m3R[HF&r2mbVTK*S2LHQfpRaEZY62q$p6(P-N*UMLaG`U(A3kf,'N2EqMM"fbMIA --RdZecf[2j#4QdI24dTULk0LrEPbEbe[6fUQkfG4Sr&pF3+p#c#X&mGEq5')q5#S -!GRX9f#!B21D@BU89D`3rC9[N%pj@V,6RZ98%P5@,LYQiRJZq*6,2Q+m@+qh&[2+ -edP%2%p1(Y6X+Q%BA#NjVjpDIqJbaQ9fdR&f#lC-[-jla2C[%i9pGce@##,&Qar0 -5UBEeEklRc9,6q%l(mdA-r,r'kiiIH(J6ra@bN!"84F(i$(V!mIcZR@*lR9HE[5# -@irNcYL5"Y%l-C96DmG`26Vr"mla#(KpekRR4Xm8Q[H5FFkE)BkN6mbD`%0ae2'' --$Kq)[ffEf1!%jP`KpE5rjRMH$SkmaBZjS4$c&qm4QpRFC$`Ikb&ir&U`9$VC1AX -NYc%1KiLrJ$qGJ"miq%N0RHkSA`!lHBHAM@aKYlBlRX[SlhHkRS[I9DMRZbi5'hB -RjPeJXq2j[(m4flXpcepjD"brjFGLSh,QR$Zed'[ASCbmer8mMhlmX&1"'RM(qec -20@ZN1fBl-4ZH*3l[Gch2IcaC1jk[HkMB2Z"9l@FH`iVrXm5h2ZKkAL2i%Y11qKC -+(0MS91"dH5ad2,ra'l(GkRR#UV4Uc9[%"JX`ja&`MHFkRMqJ!X)fR,2LP4k6LjX -YFKra-%T`fXA#HI2!%GIc`UG+QNk[e9mU0ZYMVZFPdN'+KI82T2khZClIqdS"#jm -%@RcFkhCiS',KEA#G6hLH$r'`X(iP+24*ca01je5k[RDTf$lPHFVQ@"F,hrNraIC -Tca0XGl!`rJA3$REU)1Z62HbSEi6*hHlaY38&A2Zr+&phZ*i2&ckJ@&Kr&5cZXel --#`SaVbIQjca81EQ!K@m'p6r[HYiN(-A&`TDALm-A[+V0+(6(8q%GAr5bZGc$`RL -+[S'G1Tj`%mA#&"cRbejY,LPJiD[TI1P+MING$`[V,`)G3&HR1d"5lE@PF2#[H6( -rMiH&m64L(Rc&R%Yrk@&KrCAJ#$cFR18JUf,KFd%me!-([HKFaF,pF*e[ZTi!X)Z -&Yp$Yp+J6mpS#&MiG$H,ERLGGT&9VqPpLSlj1"8!HaF)XUYCh25am9!%,hrN#3-Z -brMm!$3d28N9"4%e&,R"bEfTPBh4cE#!Q)&0S6'PL!*!(1mB!N!m"U18!!G(0!*! -$&[q3"&4&@&4"6%C"!3#[f%,pX)6`$!!!!CS!!!YU!*!$T3!!")%fNF*0!*!'CE% -4!!JFe"b#'($`eCIG05NKdCrNL`SqJ+E)6!pi)*68-j63U8d#!UAH950UIVlBrG4 -l@Vd0N!"hJ02kPZrDRLEK1C`6`#03`H[RM+4`Z1Aj6J#9Vp$lmDqrI9S&L0dfabQ -YLkVT6TB$UN%jcd32RXA[h(jUIS$FZfBMU@,Z+AP6r-hpHPDq`P'SFer%hk09+dH -6r)&J9iIlBUE1Z4*qLY(F-IHFNQB"#djAmJ!%'F#FF(+EE8U1KSmI'A$###-66PX -*Tq3S2qAd#&rMK&eN`JR!#V!#V+Idm1I&!3Edq%V3a`Nk1%%k8&hIGFDTK*2M*q' -%45DF(#I(bA%bi8H3!-!T@F-,p(CpTH@be9ARhE9@-G"c)F5C$G%R&BfcJ9E1Nh* -YCaTMeh5PQ[`LeTV1TDU%1$8q4()VNNec6"ZAU*8E@KQl*"0*bf!dj"aG*mJXhCe -YR&`1qXC'&fTaUhf!@AE"$f&bHR9$`5@[0%Q[DR1V+k+c5%TD@QK%N!$J6mDA3Na -@XAXjRH+r+L6Eb%@S%0Hd5iYTK)p@ULN5AA%bRKVREMK''@(8"15K8UYYc,R9mPB -63&M)4E0"R"jSE#MC+,eH#Ji'KPj8(ih")))%90*UT6P4q1Na3Ml0%V%MdQal6,S -5hm$SR@&8%,E#ik#2i68iXTTGZ$dMb-Ci26L1AQIEST8hH*6`NN@8@fU#Ha#B%GT -dB1LcYeHJX`326rCCT"[VlUM'EhB*D@#3!2-*ZPR4mbfLi+6i&f0bp-KS534p!FU -I"@U6UR[Bi9TFe6S`Z5@IN3V63*(VBiE%hNM[$EjGHNFIJfjSEXKBe55NbE*#,P! -kFF0a,C*T!$c06XmrHI(&I4JSL`qb1!b2,DDrlpJ`#i--5jPH9-%!*YU$@bNr`R0 -iB+l,ib%+TV53!0NeNR((CrCK22YFSKm$@pXlUbV%2h-f!Yb!GJ)rA*RRmpI9Mf# -&V3(8R#Cir3NUb0"VXr$5'i#5q855cV06r!VSlrr#TPfi*P!+h'TXiF21bh8VUG@ -UPYD%&R&bj`cY8N$+C58QNdPfXH)+,l%6bQkYi4AX[K`&j"&A@"mNA9l1%#@Ej5q -2%Cjm16qM'Id[Zm[Uml1,Vpp5-m4DMDi@$kiBkq,U%I#rA%dQ!Qj'J$*aQEHKJ"6 -!"1p!UdqCZiLjlPI(&VlU`0V2G%`BMDj62a6Kc@!B2faT(Q8d+Q05NYS88552N!" -r&f8+(N49F6U[)BXipU+KjT&bF,SX6Yq,2MR94`c$S-Pr@ee*TbGAJh+[LZSJG$j -,kUCKlVD5!hTpjGf#,TI`Iq%ll#BICI8$H1qjQjZfDiVm8l`lqJ*E'pN,GDrEbci -*Ef(D#B1rXMlZ6Em$DLFm-2KE9'(,r%jii"!2YMMmJQ+@,5e)iYA&bEIh1$kb+1Q -99$GVcb2kqBA&f2dA[j%LZ2dE*"$i!0+Jr`G,J""D82b(#JM,$Rk$mUD,"bckLZV -Vk)5PjPN+)`alM[[UQ"I$B4S3AdMDC)d#aKKLGbE@CEIX6&c-6eLQFaEEX-rN9lc -bj0VRa4#9R-[ZfPI`1eRQCj!!lFIcRmUPri[bSI2j5N5c0aM[jHM$KjNmPS11UD1 -PlM3fYP8mC'AVqRAD*pe[6E&A`E@!YaJ-81U1F@()m`ac,8UVF#8ajCEKS$P!1MD -Fk#(',39AQA`HZCISMH0e2rDmrLlKX$,%bIlchKFj3a`0Z!`LrErF)iCa[3GN@`Y -('2fIQjE1l,U@VEJfE39*I2T8fc@ITIJNp4m!N!-0%&4ME'&`F'aPFf0bDA"d,VN -J*L"6D%aTBJ#3"`Gm!*!2!F`h!!(TaJ#3!aErN!4069"b3eG*43%!VpP[Pl#%ldN -!N!EYrJ#3"KH*!*!$DJ#3"T1b$Z[RpGR%Dl+`cXfZGAXjmPGqpJXrSpZ,EGV+*Pl -+UCaqClR2@#YENrh+EThXpGZH,FHAiiZaC5*K1hk4ECe2GPlfjN8@[KMEK*-G@6a -bLjIQ)YQphj(&b('bm'AL'GQ56IDjX*EMC,'"f6'J!cMaecIT(16CfHFeb(fakmN -Yj"Bl4YM#!0J#3!$1L9pH1*Q-14`1&qjV()jRrXAKq*VAiDMk'pMh12(S2TE,C4+ -6jl@ibm5f&EGEE2IKpSMYREM,aIC4h"9Lqa,Z5V&p!rFd5C2j9)RYeAK-&pXU2'D -)E4-H-mAfCMaQL@dr(V2&pK%mUXAfD6aUa2B921D)l4!HFlA0Y352H@+l$BrjBVX -EM`9Lbq$a3f*l'ai,aIBK2#i4ffI`Z&4XIih()QdV)hjH*EE,m9JXYR9i-(IDGJQ -qD2Xj2)"(CIX02)J&fSJEaUIYlr#i3Y[Fa-0Va(B$(PH+V3@2Um5@`10UX6fXFDp -X[ih(Y@,l8cbZ%pYcH#c90JmaXdaXYq#aA'c%[8pX$q"a[GJqJ!IV30ZRm&JKYUI -aZ&&Xhm(M*QdV*djZ&Y[YH2b`f%*i-&rDIK+2@m9'I+m8farM3Fc54Nc8DPX&HB% -F44YcBekdYH*aKpJkm(LGf0k$"hQ'YYr$ir9Lq`XmkX6fEhLXeVC+iYN[0ZD`4Qa -[`'1Yf0k+"c&1fiIa@#qf,q#a3@bX@Eff65-I0BL0f0JSYL!HM@)Mj`A%4Rkp8f` -Iak0*E%rK`CLdr4-HGfPE&6QV@@c%$rQ"YMBmL![DL!Pb,'h[aQ1cf*JIip$fC6b -fL1dIm5"2NUl*Qq3%fXJ,a!*YV0FEaEB(Mh[%4KjpNpKq$BpYB[Xm([H+lCYiN!! -(+!'S!ED,M6`9&K[cDaIEEM`LBYZ(a`kar3SH1m9'RLEIdNC0%"8YBUBja!Re((8 -Fp4Ye'r8-p4je'r@Dk$5P"iP4kK(b,r8BG4Me&c8%qBdkLca"A88p48kLIU+Z*)q -6[mREPJiJ6j'[bE(NCh)jG3$jQEa-2LB2Nhr*Zq4EmLcjPEa+2L@2NMr*%p36j$h -b(AQ1r%EH*#q5hmKVj$2b+RQ6I%BH)hq4YmKAj#Rb%hQ*I%3H)[q3!(I)0q3CmLr -e((8Fp4Ye'h81p4je'r8DG4Ve)[8JG4Ve'A8Cp4MjMIU,ZSYkLha+I89G46e&(8@ -0),V5B($)M3m"eLq)T1lRbYC`,*4+a5+CF$UDbMV@4G1CV,FPXM-H5@3GY5&IXL2 -VD)aZppE(8mPdeR[,bSf13,#YB&iGLX@5bB4h3b5@FJ6D[2lVr8ZAkN"YhQ!S%`l -&P,8jmS!MZ(CG)A4Y)*,H'I%f)FHZ1V6X3XlG2[jeJ9Y@lZPf#JEpMQ`i&JL&%6! -G5ZreKFAHe&,AD8XlkKLf4B9PG[@*E#5p)a51d"J)C9A+JCC'Eh0()KZ04j!!QQp -0Bk0b8I832emq(SVSA4HkjZESYTAYefT(4!Zd55JiU+S"#Ye*D$F9-BmZ9Y0'N!! -B"8'diUl,a"eEr%hVE"JT[abUD!C#0"LLNBc[%ij8+[`K!BHM&Vl,@GJB%JHDZKc -KS"`C%AB03RUZp0h!S*PG-8EGf1XXe96qfN2Ea$eRl%*Z[emK&d'CGZN'fY(-lEa -3bAJbQqaMN9c!bB,daI+f*$[5iBLMC@mQ'iPlEEJaM%C'S'dEE(R+f4!*Y8I5[P4 -Bj+XjiP!48X%G9L28K&iR!eKG3DZE5(9SG41TJ+aZ)T@4e8fN`V(L8ZPCh83U0UZ -E5'9QG41TrU@Ek'$(5lU*MJIc+[9R4DAb[%r8+Xr(4,AbI&EU`m0ZKh36(AmVDTE -R@k*UHGM0NQkLNh@4EU+618Jhd8N&+0e%*a@XG"1G9)V56A4518ShdFRZNA36RHm -3p8MEqh-iFciQf+(YF9'AY$dTkT-feNqkLFjR4)h5GP"8+@hXE%NhdFAk56I4a6T -+0p(&Z0*0G&'"5MI44@8Zh83A&E0d%ee8bp*0G"'AdNedXDl56A6p%Kl56A4p!Jr -T*VVBeC0ZSSYG3qNQZPJrk5Dk[SZ(G"2,L$hT*TDa&Y*0,'0YT*YB4Xk3!'jL'9@ -qG"-0#iGi)iE)Hq3QBSki)QD)*f+0059@L"eb$IQ2R%QZ)8H5(iJ0eTam3Lb4,mN -R9RH&I%+Z*(m3cq31eTlF5)iJ(a$Mj"&b*r&#h&LG"SYlbC2%(MQ5Z#1(NPF+h4h -L5cKSiNMRTL`V&(m8Jmc6kb*-UPRc(fHhr[#,+"T@(TDhUH(NXLIqL(9,Sa#A9Y@ -)C`+"',GdLhQJ$00acm3p#rGX)JVh$0b9Z#Y`9q&f1j`S#@kqG'!A2FV+q(+2BG" -5CIQMNXMP9)'AZT6R0-Pa"VSU@Y&QI&1#eP+)1VFFYT(rl)E3@d,q@#L63E[LJ@L -U*r6@qU#hS@ic1iB@p[+PmV$),(Had%H,h&9DJ0bMqedr1+Y`kS*"0#bG$fe"kqh -#B6kfFC2c%HFdeipdel%R5i",9jAFj!4Bb%f+X+e@TUh+V9kQl8!*Sf5IjD#kQZ3 -KMiBXHC!!r'laA4mA@YeQmUDPeFd"Kpq-AUSR3PC*qH`ZVBkJZFcTZ(5`9m0H@Mq -A+3,6+4@iV-"-MR*KPKbrp"+VCFi6Up1aH,!BdNGmX4KRL,@cG%#-VP`2CkZkj5a -P,UPQ2ZeCZ5S$GjZ#pEj81V)MH[mJRZ9PSd2J3MjC)6@"4d%mX+0Y"bF2,,8D6X8 -iK(Y0,Kq6Jl3dj*p+KrZ5i8m,a`r#0jk1GZ`FDd6SNeG@e,5jlcdrb&Ue8e3RDdh -MqLhK2G(fB$UjZkd&fVcm#30!AEGYbf4$kIrYq&`i&+@U@AVm[0`Y-aiJm,r9rTQ -Ukck59hAiDR#lFAY`6mGGKEXFG`AZ5YbcF&IMRXeB1HYJNm4ZPNPRPjiZ0,R4f*! -!cmJ'Yb0p1CF*MJHJ"p$VR+kqNAU9RSSQpN65Cr1BfrI"Y604ma[6J'8mGbB6-J( -KD)a!)2J5pI3HIX"R'`(r9SHCV%CrC$Prq0@HAaR-!(RiQrCc!XAS`ApT&RBdKMq -@i83B!d!H$E[61hbicp@9Rr!#EAkC3()H(mdYc32r9FlQdETf5kY[HqP69qHIrm' -MmYL9MCm$2r'KmYKG3Z-8AP8HBpc*'3AMKaff#ra""YiD6FQ%QI0eE8q'1IR&!)$ -lG#BY8eR1jm(MJpJGBGQTZUSmMR3iAmT$#hF1%"L81i[-%dSR%'L8@8A$ThXQad$ -PJid6$(-m$f1!3QPDhA#-1EZ'Lr3I3iA5'H21cX%SShNXPGrf&r)S&H4d(U-%r2d -maTRm4"k4qdX&Q6aDQCl(Uke-akV4031R@)p8D,3VF6U2dS#4mEVbfk59a`J6RFi -M0DT1aqYUjf%%81iUMda%CSRpcc&2+1kTRelGNjIk6bEEB3M)JmF(N!#FUbY(Uq4 -ElJ0"+X`6bYe3S8b0!-aT9Q#UUD1C!4rdc58pRD1c"elUk3cRB6ET1TrUa3bKif` -[CL+2NlfBL6a1pQ+1jA'L&c1HKhQK&c0BMeGk-F1&2G1,'FrMC#pQ-)fAHc%6HCc -Ua3`NBL,SaC4Lb,c$dF0KL11jpJj-2(+-(cfG)5)kfp-T-ViTS+GM$"QcC!qGX51 -B!-TJJ$N'L'N-HJD!XrZ[l[IQEZKM6pm`$8a0+-eP-S0-``#VMQZ$![F,,q-chCE -I0b%`3eiPp'N%$TrL&!Re2V$[H8b`R[PX6a+G%kT-ENG0@bp3ZC+60aeBq1jl$ah -k-fXbVCRYF0UR24G(XF+b!rX1AR[Sd'1RTq@Bb!lR'(9TKD@D&6iTNkZ0E+HXHZ) -691R8(0kNS1XBi#E5U1R5Q&jZ6djeGID[E%8#I`kcA6JCKa1%,jQ-`bQrQ#)ZITa -M2&!I6KPH2TN2TaEl"LI+rN3q$LI0cCh-Ke291C&EmKRSrX1IdpBR*Xr#Ra2CEjf --`kp1R!)q'XFJI-TGr-X"R9fIL'DMS9MdJFLkG%M[4R,Ur0qI#TerDb3GMbC#f9I -59hm5A'S#YKXI*6"Qh"JhfG*C@lXcNSLNSf&M'b%S(LJcb%diGGAUIR*,4iSrJ@Y -PZ`Z6'MXi$i%(U!F#N@`kH9mN[5IMEFQ'%ZfKG,YXZ,1hPRX-qI8V'BmR%lA"MZf -aD0KER`M(1YSMCM#k8(V!r5)23$8Bb8M!iJ%2qd5eJ@3kXLk+Rd,H&EkEI6HCeMS -'LJFUlIpQa8'UT61[Ijf[3U)'Z!RSDPZK`R&LhDAZIiSVI,*4P$RP'%"qS"$'eXC -I4VF6D+PI@k1@VNY%XYkepkGLk#UF&C(eQ$M(X*Jm9pU6`'"fMZabCB3j*Sr"55j --K90$Yd``%p6QAHe[@V2fDZr9DqTDkr!-e[YEC9-lBp-aQ8hjZiK!k%GKrF)&JhZ -%@XFmX)cALfGmC19raH9#K@TIZkkUerSl-YPNh,XaX[HqC,TGE8*DF+m,Kb1C$1C -,ChIeqVD'X1%"Yil0CU1*REhZr(Q'EiDT9*rckSjSV"hXR8eMCRHh,lmUqC2YNI@ -44*rVQQL'Dh6&YmG!qdImjCI6%8q1FSf%HjD@VG9$Z2%a0S@+p3E@hQfKG++[MV, -IAlGAIE1h+B9pBI(YScFIYF%20[Y+p@j2Ued(Lk4m0`Gkh2+l0J#NL8LX*i"-"Mp -DAA%r@Pj1+4Z%)Pe(S*JIF(E%%l1Vqpd'LUmRLJm8'&2,MeCAEHXdaR!k4T(QG)! -5eqNB)i5R)a4C6`FBTVkFIa&dZ5$pb-Zj$q"-m$*#Ki83Jk3K)IU)8EX@f9%('+E -)[2p)#3I)8[Z1-kD18U,0cKLM-"JQd*cr"+#(U$6RITK2mlj&T"5C93FSdU[q#MV -'Va+N5,!5SF5`%Q5%BL9%N@-P`M$*jJ-83CQ2dSr+[2m!p#cJM""YCia"LV&Lp&' -Yq"Dj9L)-NfdK`'JK"qK@R-Ij9X+8#,FV5!N1`j5E$h!-hN1NQrFrc,S&ja()&(P -A)K5*&m((@*F4LT4,pa,I-X))fG+rb,4d(kCCblX)3LY%2`)Yj`'%+A5-8'XZ`## -4U!"pT%V()U25ICK1EHrKXJd3+6h(@C3a5K5DMe!Xqc"j@YjMS"fL6F[j-'IDRN1 -i+,)Ph6ZT8V,`+[CUM'B-$cp@c*5R['qG"I2,Y)E1$kekqhLSLMABlb+"K6f0%lZ -I'`q1qH9$+qLaDhjfepaTqc-T[$LI06GhHMJ1[lr2Qic$rihc*q0`([H#b6M(jh% -M$ZGaAmGLUTL$FlEKaARF0dcQVEB9(jphM6LFRcdaCaYa1$plBXkffKeeFXifiR! -1q)hMG65i(M*J@A068f["U@apmbDe#4"Ye5el-pP)A1B+4L2F#+PbAAhM@QSRHA[ -NA5l[#RQV10`p30k@[5UIS1Y5p#-NZleH$$(dYZb+B6dZYLEKVP*$b1Q58T@m,IX -XH8r,Tq5FLC5D@ZUmQ@4(1QaRJ9UA5E6CmUk4GlAiikpS(b$Fa`'"+LP!i$h$f!! -)q-f8pb3J%-99H&X!J9h"LS!31rEc9CP`crh1"G32Vk#ZpZh2a6Lc56!ci,lm24[ -R-cjhi9HlS4H3!$Q`#j!!%H0clhrLi[M'5aFp#K1mZYCdU,VSI9M6SIbLG@&0KfR -iUX922dHrVKDqeTUR[LCcpE!9NhQEEVmFQi,143A#CdrccB`SimXa`L`p`4BHQjK -US-@VF9p1Jc8#i`VFVbNiA)Rl+S5XXLCLU"%CK3K(aQLB8Q"ahIGJBCEMB+I$FfF -b8@T41!1"i%XV6r8HI0&`U0QX)aY8eHJeAFiIlT!!AJH0E3E)`pqd[h04Ulk$hH& -Cf0%BrPKQE12h%hNdl%l[m1%q9eF1JJZdqGHB!I$4h0*Fh*VpG"jU*rVYT4Q4Ud1 -a@$+Cm'k)a)Dfh9Gjl-V'ci(IhUPrG`Q08hJe"qb-[l8qk,h!(f6JVG(8a-li8h8 -e6qb-cq0$Dff%CDIUU[*i)$V%,kIbQ&JBEC&j3ZN%!SfVaq2JEkfe,6p+1eMjB1- -%`ac2`aLJ8*T@0aaMcQ$E4$d-&8TRM$["9(T)qe"9V6b@,M8&j&%Ub1Nm4JRiqhQ ---rQ*22#Ci`,fY6)pMeGEQBj9!hR)Q2VK`ZSmX(@!)5#2m'KPaq[+JAY@(L0-G$U -2e+Jk(DqVRBF43,QV2$+4R4Ii`cbKZ+FQ2f*2J3PGPFPf'!,bi2%"*1IUbV'Hq5d -4"S*8Q#H8Zk&#Q4S"Q01X`&46Cf,TG20(6qI`(Za@jFrdG)Ec-*YdR8reBSE3FEB -A-j((b9l-4"iRHc((mMM4LaR2`lc3LaQXabZpQ1(#RZR&M1GaXKFcQ-E,[CL*2%l -eBJB5-4(dBNSap*iNT4KEr%d6HSJal+l&)%D-(cfG)5)kfp-T-ViTS+GcXG6bbme -pX'fH`j&p'eNlRXRQQF4pX*AIBM!5X*bHHGAY2VMP)r##TiZHLCkm+Z(TZ!DHd8, --Zc&![a)TZbA2XQpBRP[r(Y2Fh`)2b62RH4F@[jS06kINQI2FXK,6lTrKE-*i9R8 -%C#SKUSBFUq(TH!LHC,5F*hilc'$4&mDcQAa-I@C3'ma#6&E0MYRf2Nccj`Mj'I& -X,0N6XaUeX5UGVmdMk&2m!Y#a,*l+G(VH$86jR`"feX@c1r19eQF1jlTHQNT(GMJ -mdcKLIj(PHGPQ42FU6rH$C'"l)kXV8!&AZijCa9f$&eZH9ci0K$bV24qm(3j,l$` -E@!cYZIGjTQGlhNPdk$`r1`Ffqhr)(2kVUp)alrN(f$KK8RY5jFh5-ErpUl#TZC- -mYh0CpXrTQ*Fraf,C-Am-MjADFqX"f04S5ZAj1m5D92V0,+2PHFG2!ha2kjM,bBT -Af6'"+)RTZBDY5AXBij`[N5Ce0Qpr@,1C2SrF$`M85ma(iF!pZA6-lpVSF,rpJl# -T'CJmUbJ%YQ[2Vrd(E,B'A-8+k(Ukrq"MX#fc21Ib-90l2R`*E-[YQ0r"BjkZ`1f -XY-rbI$eA*G"BFhrU0f'lh[CFL-H61ZE1$m"Q6`*qp$0!a`)GFarie,(#M[PAH(a -5aec)2HeZY$`ICTiD(Ck9hi,Y*X[cm3eJ&8(8M9q%!lB!!drr,RTCB#fEFf@V!M! -Hd&fc1mqj1Fq[)%qbc`h#ZChl*P5r2mqjGXc0B*fDEbTQeCcE&I1a(%YH83FE0a& -6TaPSQ,9"B`#PdK0-eENAD,GBFP8!$VGDRPr!eKF@5eD`3`PG)APq,XH5'cm2fff -@jr`2jeMbd9q%cGiFBrkRFmKpjlGKHkhYqBFjPRcq5C+MjEQ)@N9B%UZ"JZMXQ%r -P@1@&CYKHChNZi*)-JXr,eT*-,-rY3,[&NNZq62ME-DNQK&QIqeIBL"hY5Ei8P[a -hVK&KGdEE`FB@5bCB@eZ0cU%#%A5i@&ZlHrNUD%0K58mGP42VSr-NfU@Hcaf%cHi -8,0KNXk6Rj[I!YYlfT&S@PNcq%@aJ*['NpK*&XTRBV,Fm&h0e#Ff5lJ0N"qSGGAC -")3P,HVDbD[D2LGhcFbbjr8f`fGhUa6N0iDRiCGM)(cVQRpJXkGj2MSCk!Z1"jAi -'('@cT%cd"RpL*G*jE-9B,'PlEJ*kUPPG5jPf6J&ImN+H*HfBV@!l*Gb@#8YfaTa -,VD&Cd[e4lUV@C(Qq#k`L,1RC6+4BHmNj'S"pB8RheeQ&Zbc2Md1(@b`C)Zl)4ZV -8%*qLPTj#*m(4BPH!DN*BmJRU3RZ*ZcP8PX+5qqP&p1ZBa+0Q58mCe5*dVhMHR@2 -*4ZU`0TXPL@l4N[G#G6Zff*j[cE&N`cYJB`lUm"1dX+6lFHV2VAE-Rmr&[1eCf0j -Jm`"eSI$!Ma*4El3mNq!aB8RhVfq$`cdf1ULDK58Vf4BPXfK-8e@+P[`YmL,MDXr -p1CEmi!++&lXflmeTbEpNM[C(f`ASh`K,ZVp+E@2hQ1D4)S3P2G6YGXIS,L*FY+6 -cA54lbh-IXV'dj"HCLIhG*d-0V9R5rG@[`fErYPp#65-DiVdF3fhrk[STF+E&NRp -12B3q#rSUL,FI,1QX#6CL99Mh2l1[B[H,jK%G`ALQS![&NkVCmZaN[$RX995M&m0 -qK(4TrKm!!!d19'0X6'PLFQ&bD@9c,VNZZ5!Q)&0S6'PL!*!(Sa3!N!m"dFd!!L# -6!*!$&[q3"%e08(*$9dP&!3#[[Z!5X)6Ze`#3"3)rGJ#3"MCG!!#E#!#3"KXA"[L -,4EB,ImP#D-ZaKHdMLi36MPri`XP#Dq&&ZqAi*@'%,8S@HR[YZ)00C4kK!ql9@Gb -9VH'C*kG1q1V4SPf4ff`Ii3XRYlaNajBM[h[*FXCflm8**i`XaeV)[[KLC$Qfm+X -M#eQ1h,CM,@HXKI!MYf0pTRX3DcRI,SrF3PDXm!HmfRAYBpZ"hF+Z@eJ,!&R)E#' -hb5E$K@bb@cGCEG5NXipb-kmc,bFfciP0SRCpY-kADj1m,Xqm"RC1mVYd[jQ,ATq -Gk6A*5HIRjA9mmIh&3AlRZr$&FcPR,QpRGKjCI2+lb#Blb5DhMba(&V+3!0X#!!' -FGEVDpAD&2`E!SYGY9Zbl#'[KYr$&10Q3!*qh!GL#2q#"jGQJ9+pA2-r,)HZph-$ -&b'QHYfSBqpdqL[qPZpC2)Zrh["mDplc9EA[(9i$Ipb'U9!+8rKqm4lqNYm+lZ!G -!&1Ep-X@"qN*m&Z2mp1Q83[TUri"r8HlfjAG4%LqFpEe@UqhiF-[A"p239-AhPYr -d[*pVk4FZRRI4U`Ve@V&82rG@&@4[PIr4h2j-lhK-crZ`Ib+hFX8kEah2F+rRIEl -JrH"5VPC0MfmCD$6$hHA&Pr2#5el6re,TNb@mYbF2Dc6af+9D)#eiDb'&PN163RU -QX-!Uc3')6#a(5%ej,YmS4j`1&H4BeUZ-TSI4NKlamY`&ZC%9PhD,N!#T"VSi8-& -5Q%(k9lL5h2-Yj'XF(amP[*IY12h)[iM(0hD8IVaN+FT+5iRD`[DETdU9c@&a*Qb -1MqI2KkV51djr(qLrdcrYdMq9@dTVp@@ADm,rI*II(-A&j[qPp+qqY,IL%[*`)LN -iU9,HY4Cpl$0CAXKdGm,RGD2HP4[d(eYaY8`IZYEcAKeJ@)cFR061#l[%Tj!!P*l -Ap)rNVXKpX90bGcC+(aJYlfS@QhXhMMIVYi5P1#L8Sj+hj,LfA*[)"rPkY9'ZK-e -PejXhA)[MjR"6@$[YGe'j0[m-()9Cm&Xd8ilVTk!@efZR-&U,8DPBHIiCb(GYX9N -VefDMCGqPa6h&ji,@lleS-@i@6f%f,84a[4Um+Gal@ldjFmUhX93+SbJB,mCcTac -c#qA+c,24c0c`TZH5"(l0jDJB4@&eecHI&-kG'35hmQ-fVFYIGGAcbD&FZh+MkIS -#!B9CdDT8lhJXq%@2"HI1ai*EkmMehr)TCf0VILLUNPEE`mUbimT`hr2[ZUVBR!h -MB$+-ip-2ZaLdBB9LSj&icY``rhb9BmGLP@0AVR)P2hVfNTYqB[DM+XFZXXS9RUG -Bj6Tpr8aQhd+9+lmhe59f,98jpLe81ABX9$Pfj#TAmLX8MT*cC`CaP5Zm@&MP1Pb -lFS1UA#%V6*8Vq8@2CDTFb3e9VYfRR)eFjGLa81ABX96P#Y@M8193r`4lEC[$[B2 --qCkGE-lh,G'jJU-Tm!8rVZC"r*eXVH4FS#5qXq'#[Sp2"Rf2GPEAr[+'L2QqC9l -R1lF61pqcRGRjRL9U9h"XTdX&lh)kPGKGm(!Gp+lSfje-KZ! *NH!A(q-f+(+r -JTdPHk059R5@DjhZfmccIXdcdJY*3U)%kqDAA4HAS&-GXQ3M''R'j@Ylh$5STUmQ -+KEK"3l(GEdeKf@GCX63f'44#hU6mM1daKLA,""Nk8T5q8dHBA2N,8EEc3!Ubh8r -%b$lP%#rmcf*CF#lb3q2C39L-FiQA'pFLX65H)E-X1KEC@Y(ETfY&[i#EmB1Af'@ -lVk'Al+[jTI%T*UMa$$1dj0Me-%(b'UHHl1eS*(3iGcpRb)f,MR'k&GKad8r4ij* -6qDQ,"0Pi&KQbm@c[h"MIX(96G#`r&c0Di64lB2e!0&Ij9M9Nhd)aC-G5,@6IX"5 -bCk%5XL-A`T*I)6&,c[63*EHZG`k,B)HVAc3+VUS%XNZK!V)M&m"f[r+6k2,(2Kh -9Mle,aDr6YqXCZI59r+)%-i@[j)Dkeql6qF+&UXH1KD,(MX@DakjFmNTqRHp8,(M -Gh+qEpd@FEarIkqCkA6`[jRKPIYI&l4lKGBp`ZK+IkqCbA6bZQm1emlIph#hLE4& -Rkq*V-9FVml4fMYE&clUj@6F[FhCpHScVc1l)d(P)-GSR2c%Nj`rIE8*Qc)B"Ykc -CIJXTarE%p`kN'0'6hjmL+mhf0D5HSI`KXYV#KejMYM%SIFb'U9UDP24Z4+Nef`d -SrFb'Z2ZElIG4"TJ0XmLRQHdI815!XV$p#1Ade*E8f`ddfe#8-m`f&f@3!0P@@Pl -!GMA+B,1p&'@)fAiEj5bcLEQUa+9Qqb)+iS,YZbMRQ!eMHaMD3SSKRZ&Q%a2ALF[ -0eS)b`Q`E88DD$I0aSmaf"mTSXld,"EN$'pkqhQarMd*6E+Pr3aQAfY,+XI&Q3`` -6c)BKXiPQ@iXbb@b)@mb05GY[S%`aflY4TTVY8bKi3pLqML*(e)6YqeC28$T34fD -B$HmZ"YLNE6E+,,1KhX!1ffD81@Dl"DA"E'p#3Cl#pXFSmmb'R*Y[0Z6FJY3Qja0 -TJ#kV[*86fm+'0fSd'q,1Qfd,#NeLCZp%`53mE'p&@@5fpk0Jm!kf"e'@Q1dl+"H -B$EQ1A%Cj4"eCDME%ID(C%$FNE0HK,$2EVk%X0p[E8&DBl8p3a-bpY2dYbX9QqaF -8e#YGIY[-KKUdbQc)Yp9Q3raVc)Bm3ll$KYUfcQa[4N(YKHdM+1[0pK$+"V2K[5m -efhqLA*ED+P9rAf!fe+E,cBEmZF*Xm%&pJ`hMceHDl6A'0@"$RZ&pB2XXbP9QqbB -+DM*XU'hAT,BUmB4VcBDkKPb'$EQ+r))0X9e[0V`hYKr!K[IHCVEl8,DEl5XS0$P -ET6cEQGSNK3%IJ3dFJ%K`YHVAEV-KYfQZY9V[GD2CEN@jb@`BSAkKf6k)3U2Je3q -Jl$AEpe"HP0TUa,9S`,K'A1)PCN1p3jf%$EQ0Yi80EieiBEXGK3ClDpk(FT[C2SD -#QJ2E9e&HEVCr43'Qq2U)qi&h`)DkJYS)'qVb+mf'Z[-UXb&RIYeXd&pYYYp$!Bq -!l4-S[fNfF%6N2Q`r3!'r%epIFEAAQJfmi8kcSHlIC6E8apHC$IRrHV2KVGpJ0Z6 -C'mhf!46`#0LqJ!)H"a[b'h9!I,AL`-#%$E`"p4mfj$GU-Qb)qqeQ3ehj(E-K2j& -IX#&qm',B%2FlcICA+1"ZX(d,"AN"flqMJ&Z*VjrUfA[-"Pi(RJXEF[fpCN2YITr -C8,2q`'c)fcmd'plaEV0p#1@2c2DA++LaX(d$"Hm$fip48)[%eermr"kcSFk"jm) -'[SFk#4[i$lJBE1!!L"%f[-H(cBBD!"i"'plkSfC$R`#m"MC`#p3Lf&$c2QkfRk# -J9SK[J()#Q,#"'rqCf9#(Z[H3!(4ri!IJZq#ji,IJaq$&i,IJYAKIm'G`FI"0a)S -F"am"T`%A38d(*`H2"Um$e`A("GF#Td@Y30kLAS,,iSh3#d$G4Ld$j`Ir!1p!VU" -QSRkKCS0RJ&q!9i$IJ,q!9i"2J%H!2i!hJ#q!*i!IS1k!$i!(S2kMlU-'JJHKeU2 -'SlDM0U#rJPa#2`9p&13jHJ2SSi#rS@m#NS1kMli'kM"i(rJHqMV)Fh!mm"'3!%l -d9Y"635m&244`A[3iG0m(046e3bpe3(e&6`#m'(`8A!Rm&r`C["Rm&r89I"Ie"C` -FI"4m(0`42"*m%K`5h"&F(K`HR"KF'&`%h"HF&h`)("#F!I85("Hp!Y44p!E3%`# -r"8F"0`%R!4F"ad(G!KF""`(h!!F#a`(h!1F!ed#0"lF!T`#A!)G!c39R!&F!4`! -h!#F!9`)I!!p!r8FY4-e'V8D04Qe'c8G04fe'68BY"LG!c8FY4Je'l8A04De&M89 -Y48e&,8804He%c85Y4)dNlZ"rX[H@8KULQL(EYPkJK0alGV&(X+L$&JmNPFSYYV" -&IB@&,L+8*$+&c##cb%VND'39FK5b$MQ!Y39GLem5[Vf2l%iLrHi5E-ELeIQR'T2 -(GkZS#"$P)dYUp*U1"'elYD0Mpi"e&`jmj68CDJ23d9dCM#cUEUd'#CSUDZV[(YK -AYJj%m+hI-KjX(ET"&6")(9kPSpDUq#plH#P1A!4-UUTAeK'V@)-P&(U65l`3TX+ -lB&8kNk*Q,q4NbK-F$L9q8fAd1kMaGfLG5kP@q(9L`0)k&r@J&jiV',r-mR!2Mep -ZLU&4#8AbEh`f)0I-Tp-,XVB3aXhkE@&c2JU5)CkfbbH#+rheKqrbeqmHR"i,*ME -2H9F%Np,brCHp`I1h3EH'Ikc[XUhHE$"Yl9Vl643Vk9Z0'k,QKASm(l+Ar0&U2%Y -M)(9LZ65*PP(bGG9'"'ESf8M$aPXa2XVFFr,%JcM3`)&Ja'JRe6rlTQNebIHqGlq -hpkQNTHCGpAYprNHfU6AaS(K6)[F(lrIfINlM'ZVl2(*fk[NPN@ArPG-U4c@Tjjd -D"D!@YHJpL*VM2CakALp563eVJ3Qb9TGklK9PTIDei1)J`e@Tjai4AQTQ#dr3hFq -NRPp@ki&Dfk+[)CS)hTV8Fil)1M@k4EF$EB*2T*iE4DHTl5eb"Jd8b4!6ZGH+5&) -6A(4(40XLDHrj*G&fDSQ,IJ!D29HQRTp8Ji3Dj-*6Y!3'[5VeR#G+6Zeb`IRa(MG -AidL0(MeB)lph825pip5!GXp'03#Q911+'N+K*pUcZQi82'@MLI,Qlp4!S5Dpq0$ -+'TPkpPAEJ9VfP!hdDUp6)i`Dq)4aTfAKTl%Khi)pA25j!,DVZ@!q"m6f+k5a(ZC -bcAc(QcC*H!mB0rA(h#jIAApqE(LN2qJI(TSD3QhGNTqb'69AbLHB'IA(#Krk`i+ -!96"M)-FHD3DPq$hCm4-0+$94,)D5Ir&DrNT%[&PkH(66MY*mH8Cc`'XRf8Vibpj -Pf5GS6ENQYR058p)CX2'eDm@MD!J+FI!CU*XUApHIjqc+T6!RQa0-Y'9+Q+QqG2, -Fc)!IrkUlQh#km$dEch5jIDk3!0@Xf3Xd85#UC8ZY(*H,&ABr,'i@CkXKLmL1ILF -E1LVq9@'c@Ui9iqq%$ek&GDCkdiF3lHY-h306%mFqAQIkb*lXacI+DL6`(XbNkCN -bM!1KTD9Rdm!3+a+P-cJcX1)5i(qZU+',20RHK'aQ6r,$[4GNq8hG$1rJf*!!q*l -"I!EhfALI`hdU$XPMNJQM`3S0d9GUf$JEeX*QZG5cVHALTG26SJjX+rCZU`'b$XK -Tfd61YSUe,63Dp@Dmd5D9A@U&`@[4NK)M!`dE0aEUc9#VphB(2ce`cF$9[GE)JGH -L2j!!%am)HNjYFE%f8fc1-29"ZhrE4S0mUZfS9ZZeRQ3P!S09LKFq9JF%Hh59m34 -C"c,LKCYBdlNalYh@+T+mX)*I(6NL0X(Mb*&R)R%2(%&bG0H+qF5T*XAAe3XeR6k -I+f)&`31p30l49E0'!65dCkU1*cq9a*cG1Qk-FKjmMmiM(Tr%IhErQ-YXVBTMEL8 -)l@!`j`XFrkUl0h`ikhB`Z""f`6J3)K3aGRC4*(hUAUU$9@IBHBXGZ&MMK[fU@'L -(REPB@SEGZYL0Llfh@15'KA"i16"fE$h&cPMXHF9q@Hb@4Am4bpZ`Z"&lCV'b$U[ -K-(@*[J6f[Q,[,[E"JYTM[4Y@V@'r,PEFBEm,GU1#e@-r,IB&B(mY&VDKHi!p[pM -$Lrfmf1q,RElBdiY9EpMaLhff@)D((F$SdQ)P'kCrpFjI,)ZMhHGbcbpfjQ)R-IE -@BTFZdJ-lH,'V'$2a@15'0A@J#pK4Lrfk@0#(AEISG@!&R0jTLefhf'A,qhZa+eM -[lX8HB1`baRT"l#p'ka8lM,%M'IZ4p5jN%$[XS-(D#EeA@HpEaUjPV*VM2F[BrD[ -h0@#2!hBfS*Z#P3hB8iZpa&LBT2IjBXm`lbl'LN$H@iaGa)rXBmBZClf,'EYMX41 -BG`&MlbrYQIrTPreQ2eSkl8QfElJfZ)0Ei(-Km"$4,ACrl'Pj&[Hr-V(h#jMGiAJ -%V3(l#IBa`k$[`T!!qjJ&`ZKN3E1VTME'@HU`f)NQ1@eTTjMHi9lbdcYi5Rl`!Fm -Vq6QUeK2cYf`lTlr)'f6L%`9AMHbB'QL8AYU1,Z*3PpHdKe&qdfIL8"qD02)pGRR -edQZH(24@c*c`9QrDQ6[@HX$(lUfK*4-`Nlh[D9pN-XcEGh[IdUimq$lGTke0TQT -EYqFR&QTFMq05kY-@pjk9ccKd9H`p`j8%m+2GC(3pJ3'R@bN%$ZV@QM-iAKF(M(a -P"kG!a"N(AEGe,Kjdj6DFLBII"lcc8KFhZR@lAX!aHB&ZhKk(JmlM5mrJd*8M%JI -GbE8Z(R3`Ap["k9j**h$3%EhKI$a&UeYZ+LLS$A`64fPr)DU[lSAV1ce+phZ8qYr -P@cc+IAbq4H6RIAap0`Rhm4rTZHYq1hV[TAiljL2dl4jk"S2Zl(%eI)9a6&fKNA@ -D"#"EG+&(CQK![,VZK')U3mqak#Y*m'&k3er)K)N9I5%6*M"dc`iY9EU3!%PH$%) -A-XR,31K#*RR4KjihrCa9!RbiqSJZC%SmBC8"(kjIdKFbiEhdK8c`eaFbS5,3K8b -H-TdZC2+8`A3KNkI-T!ZC2%h2d)9-mNSRZT!!bG-d#Ph)j+QV4aFbHCT@S3ZC2%f -Ed)9-RUB`k'!&6qp0r4K2&j(3K8b51G+&60jI@k@#lFY@X@$$"6Pd)C1Rbi6S3LE -[+DYNX2f(965N-h+5'J4*j3aGb*681p+&6%RKdS9-5H8hAFL89-@L#jQ5QN#L#jQ -5QNkKjRC5NdCd)905Nced)905rA1kN!!T+@j+&c)P0F&$&c,*bk,S3UDN,MqK#jQ -51Q'",Q4+kQ`'ZT!!+DP*D@SV*C86G#&68KG3dB9-mK)TZT!!+IQd9@"GbUJhN9) -0SJZC8US4G#&65RP)&c+Pp+E8H8XT0VU3!#QPb5+Uh#P0j0#&6#P08G'&6#R9!lU -3!#QP+5LkN!!TT9%#ZT!!+D9V@@K,GNUAVY#&6#R91EU3!#QPA+F,Q9+I4U'HCNV -R5Y$j%@RP0adFNGCEdSN4DG8Q1LSLV9T!Cd5NP9Gd1%4DEd5R3U3e08E(3D49fqJ -FL,6HNJk!5'Z#Ldjq5'Z#L)j[51X#'$Uh)De,AqM!KV41K+!,QG,+AEU3!#QYUir -S3UDd,[+K2QMkXbM8Y8Tr"B8ZC**A9G'&6"Ra#TTFbSJ2d*4B4[@8,Q6+U%j4PcD -Mh+8,Q6,+0lU3!#QMGk3,Q6,#T3ZC-TT!S`ZC-TS+S`ZC-Z)VG#&64TI08#FrS`Y -Pk%+QM%k)S%CSjZp4k%+Qc--S02U58CfQ#jNbfSa*&c*P9C[T3UDXkMX0e'G9lqK -#TUcbQ5jNbLTrU,Z@9Cad)90@18SA-Q8eU8)A-Q9e'3eGb*39Vk+Gd&R9'1SGC4p -&S3ZCXVTdLLjNbUQZd)9-1A%5ZT!!59jj44Fbj94Ek8+QR1SAAFL88pfK#jPbbP@ -kN!!TTabJ#jPbHJZkN!!T*jj%&c,PG!81AFL8dmNGG#&66YFXdB9-1H8@AFL8dd9 -0G#&6lMp3k%+Q#[%rZT!!U8+mKbjNUP#HG9mRi%cie"lm4-k@-f0*F`D*@fh%K6Q -*(d"@)UZ3!0A)'Q3IC&pN,E)IXMpb!2)dC"hbG14!j"R)3FJcNB143j!!Cb(24Z+ -)iR13!-13!-14jb*()%FL4b&()mFJkj&MNH13!114%j!!%j'6N!#6N913!&14dj! -!dj(R)@FJCb*R)@FMjb!EN!"cNI13!214#j!!#j(R)aZ4H@36XKQj*$hbeph4jAB -EI1Bm!A%,k&9DH,@P8JjR!YZ'L40qKT%@#BlP`qTFDI1h*8j)$YRE'!FrJGp1"Nb -#N`hN8)XB@42iMC9+[643-Q[6A,'@'4I9pQ5fjQd6Q@ea[MV6-BT3I@0,,3kE#if -ikl#PBebdf$8ZVmIPhAXcXcM$Ed[R'9D'8AfK@HS%ePB[c@I'9BbIq-E9YI*LalL -RA-Q-&p@,HUCGi@bif%Lp'U1p0BXbAicD!HHC@0aP6p%dAq`N4"-@#PXmHH2Qc03 -bQTQ@[GP--MRTA@"FY0KSTYCQjL'9aFqS4AZBM566c@&TS3d3T"EbDRQarG",3N1 -lS"M0Q8AFJlUMr@`YYCP`F@cA,@fV5%0kmTDaYKiN4mYB&LCf0QM,lML,J(*(*Y) -@U`KiMGd@&@H[$pTDE%EfAUhcXfEB&8CKFdrEE9FlY9VV8APa-VB-%3Ca"D)I#"+ -F2)0(@e18bcDUfp@UET0QkL9[Z%a94"Bde4Yk$5500V8ed[)(fid9(QH2%XH[MQ4 -V$U2jZ0iSc#SiheRGmLJmGXI0@UNBKD@U(YkXULMABiN[Mh8Ye9l+U1AeQK+",f0 -08#E%IPYehD[d'&ELqN@"+a*(eN"j'k2HF*KJapQfHPcAZ*Kbf3)!e8LJ6k,@kIU -R))0k5(Cj+D1q#PX(*01TFG[NPL!r)&Fm64XeBeeQP8APkQ)TP(%Cf53KS0&%Q%4 -CYYfX-$BX"BUREDNQMbeF%Qp8RGe4)h@fLTZBiEG`-NmFj*K)6h9-l-L2AArp8Jc -Lb%Ffbh$e)MJ6,Ul6%*0V"E-1Q)`8-+`Q+*J4P'DPL@5rT*m4X)Bj%[JhMiiQ9XS -'lG)@cq3ck&,ZE+VASMS8BRHmX#ZT6hZ$E`4m5H*3M&N3)P%JLNL"8iM'ek(UYq8 -VT6L&J"8%)Pe3ZSb,INV1HK90q`Y6N!$d1#XQNh#SM#MIB@Z[+GqmBHE+EP6+NA1 -%RJc2UGq,d0@6FVBZ,MFMRI'T"Y%EdQ9GA8pHM'MBC&*jJaT[5RcKa4BAPpjXcra -bP69jm['PK*5PUTa)!B3X2*hTjfFZZ#ca9%&4VNl5JjUR6[&2M'CK4R-4XJ@C4)U -cb14P@KNNMX$-)5Z3!*A)+Q3eXJEC"pNA@B[XKqb2()!m$9Q(2"dj%(N'FK$b614 -Jj"$N@FLcN814jb#()BFMcd@13)j%MN+14Sj"eL2()XFKab-R)#FL*b%R)kFJTb+ -R)DFMcd213-j%cN,14Xj"0L$R)ZFKjb-A)"FLcdFf)S1l0a`!Ppr8,29JA(9Eap3 -%T0c6``k*Q`rIFC+6cDlA6++ll9XU&PDS#YG5&F5GPU"1$VG[Z@fS#+V#GUV#Rd0 -Sk9*54p[hSZ4q#Di+,kBUI+R9HYUQ3PeXhrrZai[hUVJIEV05@plF!9G'iCda+9c -DUBE0%jL),ZpD`c4ab8ppHJ-*Q"P#,QhNG$YX)-&Z"SbjPMD3!'$A!QEDH31*hMk -#[3VP$55Pl52BDi!p"pKTJ*PiC*8$BJZ*mq$VZU2"rE+Ed3&bqGN[6JG!R8qPZiC -%fDrT&EG(A03$9pbP@I+#'#IFT9RCRR#ACU&G*UlD+0B"Ilf#1kd5b$SJlR6mkB9 -4BQ0-JrII#1kZ1L$kKC)Ar[cLX0D&A48f-,A85T@&Q4jKT%(@JFF[6m2&B5kb)U$ -V3%92Z)[$8!HUHX*G*)JkJ)P"c*UT+51KLjRHVl9DRp!@fm,R$i5lhMlhbpjlE-h -'YQaXS+EYf()H#l86mcMk2J"XbmE@CQc(TUhBMSE2JC@MiM(f)Qp'6N9Z3fj(lN$ -Z40k!h)AFMGb$["(CM&b%A)aFJV`!fB*FLV`3H4&b'A)jFJ@b&ANaFL@b$EN+Z4U -j"VN@Z3jj#A)pFJ2b8Z4Pb"FJ,dGHJGb)["+j#ENCH4AbDZ3eb'Z4@j!!eb'[4fj -&6N014jk(R)'FLCb&R)fFJfa!cNA13mj(,N!Z4*k2E%6QN8PN#MNC139j%h)d%V@ -Nb&QrHefVGIcdA8M11-lUk[KF&,F'*Ee,AYPA0cLp%r$%Ka-"'KX0ZfcJ4"c,#U0 -f'82m&9IkGRh,aNIYBSD6FDc0fd81*pjejH6%Q3L2ab&[mEPbcLY&d@%1X,MG@lR -4,PB3AdAMbe),1ije3IM)%9hcN!$`5fp*,X+3!((dV'lY[3dSL'1mAAMaUcJHIC! -!aq0ip2bP*q)i%-La1,!FHr+q`64IlcNqerVUB%lf1Sj+U0Pl+&Nf2C5ji)T055i -,hiH3!$Yckpi@q&miPLbXNA%FZ!MTd(ZJJ56MH$3pRVK4DD0G(['V1*kpG8PprSe -+)JjELCkiGHR!Kh6Yr@3FZlfjFh@DpS[,3UeG5h8DbmGlBfeI80ljL6hV$S#pAq! -IZk*Q$i#&ciMMm%80a6hVA4q@PVX"iX!RPp(rr`qRNKbm5p(p`EM&bhCM2-QiicL -F!Bala4Zh[R,-E(%pIpIRq'$ZdDXqbG`2aR'%Z4q-i`Kc2a6(cjKlEabpc"dI-AI -[mBI@p`"Jl[[HifRQ(MrXFHEH'mF4jVi[M+HBHfmF2FaGa('3!,`VjRl9l2rR[I1 -$FBYV(,SaRQ6F84ci(!'-HffjG[A2")XEVMh$Z#[rPc'*1!j8KU1-k@!F4jM1S6K -qaR4kicKDbII&m93PlifMTqL*1%6H(f,Q[GGCQil%rJ`4FHcBC4FGGArLL*5$F93 -@rZYXJ)T#)@rh2*hi(UYi6@NQ(STMkmYF8F5"LilPk5PL1,hdZ(j'E`lEPjDHH0H -6R-(RdMfFr&JF[C@c*mrmr0Mc8TSppP8R"bcZVc&pNqlMcLpYSkX8GD(+Ap#&ZLE -)ZSp1J$LD+P(N8@*%!BRL%,8HljSiebHAA8-R`([)ETm6)!lGlE0a(1[fA4YA+pl -SJ6519ac9Y@A*(GJ(hVSqYqUY4lQJBXBMDdI[b`A(MJ-TjS$lI3Erqh1[Ir"$Z9A -[5&E3bMLZ8aE&lh%ickM,XU9a0Pr4BT'&D(mFZ-!bS8-e6qDpl,)i!I*9GPQF!(( -J8q8XmGehPA')p%Km,cp`qmm"bZ!9#Z2I2Q1MrF0SGbre5+cU26(jd$6fVV1p+IA -T(,1Ij$"1J$L@hY,F2B"mlPh"5Yd9-i[f+h1KdKG`S42j%A#K%rRU$TJ9NecSC2e -!"9jIEV`bJA2iAGd6R@Yma+QHIeFC4mpYY)IM1(Kkq*!!hQmcA[BlaR6F5M0H*cr -(dScAcXC,l,6hA9d%8pjL9ZcNj`#C&GYA3*kD&BXUY5YJ9N`aGhP-H6G)V[F%FhG -8-&-R319d+e5U`pr"`klF(cdGKmZQ(2Xj#(SaEU"015Frap+QR'1pQ1j!R!3EG`j -mY((R`1IHfVM61rkIk1Y9-IprK-'j0rB)('9Hqq*iQRR&$h+FHIA'iCcBMh#-HA8 -(iKEBXk$L%!HKl[m3K0KEVdM"IK`h!#13!(%i*IBqq(FMlKmCHr5V@EUIe&9h0b+ -f['mm2phSJ[N`DlYdk)BKbGVZK4ebHVhYmSRJ5RrpiE[mpEX(TmH#LFechKA"T,4 -mrf9[i%MhMl0#rBYpPfheCS0TZj,mk1G#k2'9hr5C104RHR-l5UpjFY"E-A2#@le -TCqjBk`%IZlH'QH2JlV'pll&*c&6JlEZpEqP@6[JqcAPUNqY'@VIRl3jEKa,R58+ -LF9FGIZI,9pHI(aXHk3rkKiHQKP"EYq5Rl2Kp9mU(#P!c-6CQ9pfVVf,6a(5lcq+ -YIZj#F1'iH-[S#2"H&bajBIYbF((&![NR68qCRMBpBhV@p*cT&DCAQPjPHVAT0DE -h-Ef[kE@Qpc1p[qRb(A$PV(QRe#9,Pif,LaJ)kc66PjKHCrVTTJmdr3c6"jPqTZQ -$64pLqPQQRfhk8022-AfBkF002pId%DD20(f8kD00(f0k[HPM6GI[10ld#DC20(f -5kC00Rf,k901RQ6lGp20-Rf(k600RQ6lEp$QQ0jJqYjYVk9HrF$PkN!$EmdbIErS -#daHDIVlTMDER6@mbr8,6QlYa9k`jFrBfP53FY%"kUJYEUA2KrE1iUF`*&MbkLe& -e)IlbA'k+3IM,FLEdE"HRHZAb1GhdhJ*%jV-)A1DTX'Xr@DZ%,ZZ1m(qKk6,[K5l -c9HJhQBkV,4lrF*p$-ZNMCHab26IFaA+TRR%Abk9l`PdXph$lBMNRh'9DQCja&mX -pIUNDA5cR,,Y-Um,9!Ap8`*m8F)a9!eN(+R[#A5chF)qjLqAFChFS68RhNbrYV(@ -SZ$ZaGHfhIp0l%jXhHHb!G!I6GUf(lYfrG0@)*hYiKa)'21@ZHHrSRrEKIkprp#- -lrAIrX1jpFdcGSI6i05[b$U@S6RIGS95Xdilb1j4F#XcG$E5Mh$*hI-6F[9pB[E- -(!(0h5pfKG$,[6fNClP$D@$Y#9bRU3T@rS![eR30Cpp%*%)Hj3bQ+Sq[HRQ*A6(B -0R3$[)EYp6S!ir$Z8pXGaV0XREkqjMqe`qJiPldlr)HcL$LA[`%FEhNErd0l0pqc -h$rkXLSQi3kQfK[r,r%1e6rS(RJ#2Ekq*hq0`RTNlP+)iZZj3+XCKlP"krMeNPm8 -*N!#[XX[L")J$(pe-mrblbMM8(8V2ah'+D(1(NRYl%kHm,elQk+Qh`bC1bGbGE*X -i$q6p+4A%*XjcrEXEIr[-*XklCljIe0R%L9[,8mQYj9QlYIbj*hD$IELafqXCGh0 -lTUImcHfBijFhYaIUJ,UUHN[[X)[DMp5"C-qiQpZchlkjh89fK[q6YpF,pZJN+`+ -k$P6dK,Zj(AA!)AGcZj!!Q#0B,88kbADb3IPSUJZF&1UD-cKH&fFdkLdC6PD`rRG -Efb"`--Qfi3b1(jc!QBakUm1CJ[SbKc-90C[Kj%kpYm'CKTTl)5m-cR68#SH$cGk -9$QF'DTA$`F4BYF1CK9VMF'DMpR%iFe$l1Kc3L9U(-aHeRm1CKpVIiFa((H"`&U# -HjR!@SYBj(+c41phK0+)1G$MBd(''`m(QM%%1Ca(UQ3i(%qb$(Fi5e#%1"eZTch) -i,DKR1jbPU%-G$[B"RH0`X*PPQ-0CKMVFi5a(2GIKV%!GiA!`PMV5i9b-1XVKV%3 -GlA$D8-FiR&@Sp3jR0HTBKl-'GCc$@BXkhZ'X3jhJF#j"RHK`eU01FMJE8#FlR%Y -4TcLFbe#R1T`AS%jc1*HM6RFi@!"aRX2"iXXC$JHce6-G$QDjCcNFh$dcfq&JEGF -FKi-GZJd1"j[EjMSFc2l2FcKE81Fl(-b8,h!if%qmd1&JSp6j$JHl6aSGcRE8[-2 -CJGVNF,$0SGRKh)#kb1&JbmGLKi1G"%XF$PB5A1"`X(1KaH(FK2SDemGk)HTV-ac -GUHU)jfE80lTqeel80jh(199(q(Uk`XbUE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jK -aE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jK -aE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jK -aE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jK -aE&HBF@aAQ(&X9jKaE&HBFG`!A@'1ahD&'FGfK4R(GS8CahD&'FGfK4R(GS8CahD -&'HF83k%V,&J-L%``"Ej[kPei!5+D!MFi)'64&,M"%C3URJ)h1"R8D!VFi'!rD$3 -&ER#`365D!MFi&DM4&,M"U850TX!06K9U0!9ZF+T4SbP`Je1$'Nf"'j`qU0%8Z-( -TLaT0J4ZF@Y4S#YcJB!Pa0!9ZF2UM4P2J"QF!DM3&ER"13ifQ`!e1(@Sd"@j`6NH -0TX!0cN$8D!VFi*b"'Nf"'aaaJ93m"@j`cN50TX!0cQ$8D!VFi!a"MDE!$FjCU0% -8Z-%j'c@D!MFi3e'M+A#$F`jU0!9ZF($66$3&ER#'SdC6i!ERA04S#YcJM%#0TX! -0cNM8D!VFi)a#MDE!$3kfM846i!CR$'Sd"@j`kP'M+A#$-aBeQJ)h1103SbP`Ji0 -Y+0%8Z-'CJ"T0J4ZFLDM4&,M"QB3D6B%E('aKLDE!$3kfX%46i!B(@eLL+A#$Jbd -Xd45i`F%@PQJ+h1"J#dXd"@j`X)8PQJ)h10M#%Nf"'aaXBBQQ`!d1YV"%8q!'"eY -BSLP`Ji-Y,0%8Z-("&TCS#YcJB!Y,e1mh1*LhLkE!$3lQlD)TF)1$HEYS#YcJB0i -ZQJ)h1*LhLkE!$3lQlD)TF)1$,II4&,M"`9aH0!9ZF$"(&r6Rpme9##r-X`ApqAd -iTpi)Rq!cMrARK6mJPQ8ib4Gad*m2q[Ja$[Vc34mraJRlmc%1q[0"[cr'3Amqk12 -(11M2"hhm'#IXcmFik-m(rIiB"rhjS)mIik!r(r6aBacdji-qISb$rRc3aipad*m -2q[Ja$[Vc34mraN&r2ZMMacMSc`Gpr"JRl-qRAX3*qr-a6YLIMh(#rRb-%rERBjb -`2arMK2hj'#IXcmFiBAmqaJRlmc&1f*q2FF,qI)`6pZGMR,!r(q1%rINB*qc2acK -KIcl'#I[c-8lBRipa`[jmM"2fjf1FX$mIii6pq4J(rIQJlalMS$mIp2&MR,!r(q1 -%rINB*qc2acKKIcl'3Amqk,[(11M2"hhm'#IXcmFiBAmqaJRlmc%1q[0"2ch'3Am -qk12(11M2"hhm'#IXcmFiBAmqaJRlmc&1f*q2FF,qI2T&(26RJcjdM)2qI0$(Mh( -3R`rkq$%1q[0"(cr'3Amqk12(1'&r2XC"IclSpmFik-m(II`B"hYc$[ERK6rfejb -#*26Rpkqm1M)#bcKf"*Cal!JXipJ4@-Da)l#-BdGJ'FH1`$+1(B&P($X#bcKf"*C -al!JXipJ4@-Da)l#-BdGJ'FH1`$+1(B&P($X#bcKf"*Cal!JXipJ4@-Da)l#-BdG -J'FH1`$+1(B&P($X#bcKf"*Cal!JXipJ4@-Da)l#-BdGJ'FH1`$+1'f!%PZ1a)l# --BdGJ'FH1`$+1(B&P($X#bcKf"*Cal!JXipJ4@0pikT)`!ZZ5qC,XZK@d6[l1Pkq -Z2cmf20)Ip!m263fKYQl*6kQVje$jX&"XqGLfSF,)`-J1MH"dIQKrb$&Z++5[pJr -i&q9ZAiiNqrfKcAhccS"0crlDN!#H6Fq-BcFp-iiEB0-caf-h2611hI6-1(E6-q2 -B6Fq-BcFp-ilGp-`iGY-cipK0ciaM0cdcMYhdc$Kfdc2Mf%h2M'-h2611hI6-1(E -6-q1i!6BpFcafdc2Mf%h2M'-h2611hI6-1(E6-q2B6Fq-BcFp-ilGp-`iGY-cipK -0ciaM0cdcMYhdc$Kfdc2Mf%h2M'-h2611hI6-1(E6-q2B6Fq-BcFp-ilGp-`iGY- -cipK0ciaM0cdcMYhdc$Kfdc2MZ!%f2A-mGY-cipK0ciaM0cdcMYhdc$Kfdc2Mf%h -2M1-'f26-mGK0cicM"YMdc2(B6Fq-BcFp-ilGp-`iGY-cipK0ciaM0cdcMYhdc$L -RHJQERT2H*AhR"i!(pqkDrpd84BFprfYhH#XhkPj'p98d[Lbe22rVIIM)[bEkTVF -NZf8F621rNrF0T[Pkcr'jePF(Fl,A2F`XaYj$b5$S80S1&CZ5A"Dq$b&hjYDp,I# -rF#aCK1GBQ[pe#FcYARZZ6Y2FVLc8fV98TpeEFl[%Z1-eDZi2aZd!fU,Q@'$ZEU! -YDTDjib2QlMhqd2SH!-cGrE0&VBHjLcJ1NRGrqpR*[(H!E$rEYdAiUHeRqlF41`) -BGqqUM-TH&CXbR"-E,Y`6Qb#F!"XFC)9a5Qa-U#bmZ)G0I4@&3PlAG6X![XFUAP1 -DLBILf2Sb9a4aB)[aX(bpfLKA6MqZRp'E`qrZ!2IIib4Rm,Pd$bFr&NG[jHc*-cm -rpVbbE[hJ9heqAAhIT2Zimd[Ek#T&ADMb&h5KVJQblU-6)!kjC9kY`BlLd0ZVECp -FGJfG!1mKZhe1J$KdYmr'FDcE*lI$Ah3JMH-94jN3bH9fB"pikrVFUVFHCFI$RCSfile$I -@MYkA#iiG"e*XIqMh'Ic[clhq`3rP9Ve$dq4Q1hcm(SIcM,SX@aTRma8Y&PQ)pXF -KYm0MEIR*[*GG&LG![XSZLa-J$RbdeIhjGj9aL24)I#mr6JeY,Q9)Rp`q4@[jhh3 -i`,BSlM+8p-Nhdc-EJQHP2%eI-(hbaMYBp#im8r,FIMSSl25Zah2,%ZBkL0l0Ik- -$$e5FU41CTl$XB$)mYcq0dhLqb[0Z1X*-16a&R0U6r0q08Y9SXVXKq5GrJ5eBMV` -H16,e[&HA-G!#CI'pY)-jr#PXZ1Y"I5,@a+qPRVGTC&&ZbX(RkFD!TDRRK0r!KYX -Gj*Hj"f9+kVRL8pK`VB2br(B(-h85'ej"4I-6P0QTjkfkeJ!A1FJ[U4cYNhUqjdC -XZ-&"IZ1**Qh4l&80`Y80mXXpKP+AH[Ej3fbiXd&&JlSi12@m6l2%Z+a"IMrqFmj -1@*Gk[[*h&E2r0TMM6UHHVIq1$GFcU'JZ3aQ8HVEm(6EFbk!m8HXTSpi[&0!NjAQ -V)P#H(p5qHYc%S$,h!bJ2@ZCLFcqZB&"jJdT0f6&EliQl&e3dVp%E+Xp2UHiKGq3 -h"FlL2Cak[PYlYA(EJ[bbBM18(Hp8R,KQ38AcPXkV9DXhM2X9&#BfNAmQpC6A)1" -L"9A@40jlDe,2pp9a`)d++JY446k4HRj$HBD+)ErTZMYK8Z,TIH@Gf'"ARQ+cGp, -HFm#ri)"Bj6IVdhKZ6MfrrcXii0B%QCijhRck,aNQ,NX38P4MNDQc9*F'9H0)GCV -UB2VNp%(2Icm9VrCJ08ikqllR1ZB&EJ,6!h1VhP*lM[M82r'HU+Cp`83&,k`F6rj -q*fqqrK!fh+fJ2*'Y9(2(XJG#AUUJ22qQJhRlRGK`Qi,br%DRjMji+cCFSb#rqFS -LURLE$Q,$r3Rb5reaTqC@UX,JiJ6PL9T)Q!rSrJ$FQ+!m`9'SUYbZ14jFPD$H'rF -@8-hpV%CVrF-Rjpr3UERI8[5i(%&K)PqSUQclE@bi&8&jBQXreGbl&61Z3j!!Ab0 -[f(Gck[PQe8kICkFqf+Qj@m8Im#)UQVC1cEeHH+LKb[2PRBaU8)A!P3I+%e@5DZi -hYf,$A3H+$B)l8Fepp5mUKrak)ejDCmI[L[NJGq3hPPUJDqlR9*R"l16A5VC6cI@ -H[NhP6([1Q1jNafIr%KXZ-T!!hcK99Pdl(K#8pP`TlN8epkh`5RPeJIcDU&1kj[l -MK"j,Hki5KkDDHkGfLq#b![R0HeG@Fj0hX440hP)J[l8hG@VZ2hd4"ea2),p,k+$ -SQVY*Y46h%XLDfr#q6Xh0I8$KbCVl-EUSU("A@-dPKLPBmal2[iHkl0GFhh-YZpP -ZK`(l09GlMRL8&k[AQqZD'r"9I+JmQV-L8h"lJFV2(h9UlYe#`E8<&mSB-TZjc -)2IR09,ZDDZiV9AZ3!2'U$TLDqfQGbBXE#Y3$I,j6)3DU&[V62EPrl062&k["iAG -M2(A*U%jr8CMq")kRHNjapPI$a6qjFc1Y(eechrPC(2aZYrHj6PA*+4+mMhSEF%H -UZIrmG@cqPLUF69#hdqSdpZ,KPJ)9$ITP9(0R+pY4+99')I0dc88PmkIqkP@A+D0 -Z8FAd*klUpHj8FpqZGeR@pQc3@e$04F&,E-[L"%1NM,T$V(Y&&JdB%Y@S+e4[GGX -S-3ere$ahZjMfa9NdU)b8(9[d,V#VD&lAHE@r8%F$R%*qFmAYUHC18Sd@I5$eA8i -9d69hM5*"(LK--$QUZIe8Ej%(kJ@`'B4UlJ1U!@[ERYI6kp%eplir`f&Gfr-11LD -kjNj9[`05IKqQ(ZUDqcP9-Y(2%C99G*!!CRfXbh1TGb-UkfFmVda2bMYZ0GIhA)1 -erZH9#&4cYHH)IbD[aSKVk*VVBlBYdJ`5&DlLTQSmHkSI*AEEh!h[5,kZfSM!$$` -[)4Yq#1Y0h6Fq'XAdI&#M0f5F#2d+kSJ&Q1[K%0YJjpi"AJ$XbQIRPhb5%LfbeII -d183EQ218492--qKI)8484XUepiU9#Vj$,i!k32RCmMJfe!p9#j%[9!Y[&!0!YLM --qe'Z6$frXNH&`Frf0f4aTLj9"dQ[`NKFUGUZiNaGr-[Br(89+I8(+-kr&Zr`Hk# -ALVe5R'rq"faqPh@QDTq+-h[Ked33r&U)ESQ+-hY-HH-2cDEZcZ,-hLJQkqqXfD$ -DSH,-rYKGf-4XY+J3)QIZSL1@f'a9KITqkC06'ccrRI#YIZfUiRZZT3[brRH61rG -D&QV2%Bp41qTPe9A&aea(R2I3SI#ZX8VNpaFP0dEr5E'Br2eLTEUMlpAJGF4LmVm -LVZ*h9ImIh5bURrQ@UVIZ"RYIjh@TIZE[9EI1hb@8PN9P4rk$RmIQphA(+EF8mfR -kUAZaqE0)BcqHFBMmNlq+cHriMU964F`Rrq[L%hKA&Fe,-ZD6Ie39`TqC'#rZU*K -2df[&9G$h8CM)9TAYHE99%PNhq[A8D@)qqI[9$I2lqH2&CJRcfkU5IJ0r[(L8UK$ -j2k+H*V+CK1q"55bcDD9k-DKY+M[HPQ9(dhAU6U#c)EmVP&qUGZ5I8!GAj$P9)R" -(pClj4p3hfjZp`)FcETcrZ2LG2bJfr[k-Vc80r"BfriEFmH,6P'XIK0%NP%IU"A! -lL1*VqCDLZDAYH5AXL2KDdiq,UD2(,EpVC99mV@P!A"6p-P9Cd@P6fG'd9P8&3aI -bq`&FL[KDrV"Bc'eCR1K8Ufj$rK2+&23cj6GI&9Lp@Y12L'QM2b@r694*kMBdr55 -pMi6H9(jh+EY9&ZB2kYA[D(YZ9#GGaGPm5081R%*9#2!"&@Icfm9[hYAfr*!!Q,q -+XrQ[e*G"cC'em#[UUe#fIeAE%$!eS0J5-Qp509TLIr65i2VD-kc6Q#bSJXQKRK( -Qr`%!N!30#e4ME&0SC@aXFbkjFbkj,VNJ*L"6D%aTBJ#3"lp+!*!2!HR'!!*2j!# -3!aErN!4069"b3eG*43%!VllJ3l#%l`d!N!8#51`!N!BZi3!!Dri!N!C92!B!a6) -h)e[bY+hEMK`R@r&E`JQRA@jTYYN4IQl+*EHCVAeH8GPkQpTah8mfi4422CR+$Tq -rm8rjq4djlLE(1X,)*M`**EH2E(,mb)6Y)rX)2m)fZdeSqmMam`JRa`NMV)[m*YY -1k`NlFTa`)r`*[`JRqb4d(pPN$qb08+$$(c!eZmlbY[6i18Jj*CcmIX,*FE,*FI, -lb*lJ1F&IepQSXdPfAV'ADefXcR0l0SKYZZf-RGcVBJZlcGakRGFeB!YVd,1Yfqp -BREQFpMD`JEf$cP"JAZIeIZGhC*m0NLa(GRiDBC[FcSrX1&Nmblad1A+,PjfpQF" -B!!&hkhQGAAEjf@NmZYRPKQbch-m)Jl`MqpN#`"D!J2(!Pqph&9cA9NUPB'HVe,* -[`(jHU3rUm'r3m101AGAl+GL[+hAa68V0(r&A$MQjNeAUlV[TH0l`a"rhN!"G0XS -`5AVMi3jZ$H%3bpr@@qZ01VFr2(h(Sk*5kirqRk)0D(06Ye4[bBfNQdrEH,)DMP6 -%1!XPcGI*h2f6U1bFR`cc4K-h2IlPd#M($r16N!#SLr,G0eVTZVGZfA)bD0RQ")! -XE-9m!VhA`!BcR8p5fC5!3,jlj)b&26cUYdR!R5Q`8pP(-rl4ID'DHf('GBb#HkE -#MF$1CZeJDP[P[p)#SET0HdBl2'ZK@S)bh+c8,c+*&(fDB,B@*impp*8,E1l+YG9 -j[VR"f[ak2[b&k)plZRri()mc2jGV4d,2lcl4Ah[bFFi+bP#i0%Yk)h1X3cDIP02 -i(E$R8ZflfY(8(k[B%pIaJ('b%R-UbmfLdb4BhTCCIf0R`@ieMD,Tjh,Tmjf3!2Y -Edr5Ie6F'SH(r#d#NA%Z03[0Q+f`eR+*YqZmN-%KJkBP0dDkKI!lp,f4UA0iUHlD -TS`rD&k*P$ceqbi9@8)VaY@8Ib[QGZ+bV$L3")1h`#DY)I+AfE%UE&CAQPQZ8qT! -!6[kVb!3+YF+1)C88#`FA,KM-K@f$(3XlRSa[J*dA@,Mjma338RkHV(GP6r'pmlh -#0q-fP#lXc2RZ4V-3kKNV++KMS5XYTb1YTpfbCa'TLX(2AR%03XmbejM1bFJPPV2 -T,eGUZUA)EL-S'2C8UKUpd[!GbqN,MNF[,&UK1h(P)YHCb('aFC-aPElf`-,0S@p --j0I9(i4Z@ErHh(+ckaFRSZFA#QB3k$NM,%f%,ZLhl1+V14fli[V*jL(b"#X`JX! -Xpll5#S6hpKD"IFAY@T*H[(LUYD,JMCh9eC*"@QQ[G"-5UU8MFP2T#1mY(B(Gc5f -RS[UkY6[G'*64FZHDp[(3NmfY8j9HBIKpCUMRc6!m@HT&Z,%pBhKH&,Zq0!@3!%P -N#4q6f"JHbi(D"Z8i@qpLrL9XV!Dl"Nk#&4Q6'!1-585#Llf99`K,BP086))68%` -L%da-)Q0),!FQX&+1VVC6M)I&`KAKX#HfVjN8$)X08X$#FZ"Jc3T)@)i$##Y"[Gd -C`f!5QD"J%TQ#B"%D%Jb8L18Pdck1IbkUK(dZ,XDp*%J,RX6BZZCc,@&G'ZKDd`8 -UaMQr`6IR6E#YA&'&)4HABTS,62$-459BjU*L(%Z#%Ma))Y2@L,%VAj`LETAL+Sf -KH*8[HJ'VNU#qZK3`+SN"RiS"jHk+FFP&*CMNSP)mbVGaJNA(VYJd4FL+S598+JE -(d&5*e'*A!Qf"5d8S)99[Y1[+BV4L9M()!&Fa*%'[[Kj3p#N'TcK@M%l!V"LD)&S -a0)De5Q5#)CA`hYk+8Dj8[b,89B-hGTD#AUPA#XKALGa8ZJ)'9J)"`TkS[Qk0)E% -BQZ"L-63&aa*H*!KTmF"%,E'##FhNd4ekeJZYXVAeK$"L8'CCIqK"K1b*2$9c2%V -dkf9j2@1L1&AbQ@4D%4Sdd8UJj*N%9G*dj#"*XFMe0,eLN!#NjJ)UD4AE+XQY"ii -e`Cj)bE)B98NeJUG05&fq)!(VFR5+%18,LL"4$Nr`[K`G3hj[F!+G[6FSH[E'@UL -X0%84rMI'1`C3LBp)3$NZDHebG0cGIF%$"E2YA`lm+3+N2,,rJX&bar5Q0hK,QaC -)6QmX2+F[X,mG%VC6MNi)6cQk41$,m6'(l`hZ,f9*EPU`jMA*aiDQSSq0kp%XE'K -C3E1"U94NidTL84b@bM*aE&kBLD1Uj5f,4XA)@$CbN8iiXK%Thl*a*FD9K288Sm$ -&E%J[bE2"2@*J+E4D[T,1&BIeYe44kiUM91e+3LU&648['jG!R@IL2!9f,Ha6BFq -"I4,XNf'C`AiDl,Q`Cm1ZJEd3pJcB&m0H#RXQl%YJA`Ul'[D2B4N01arfkE#8HMd -X)deR`Ci1qdaBQG)12J[lH0JR`$i4pP@`Pm0H!AXPl-YKA`Pl&HbVB9m$qc,B9m" -H$IYDf0I"[Kk@1EFh`Vi*pXf`Ei&p+qcEB0m1q`lBGm*H"RX0l,YJVi@p$TB*dME -BFE$MB9YKam"1J*d)bcKj#f`$l,4SZLe3@f$r",B*PX'Vjm$@`qCJpi1G$,Xrl!' -`8f#R`YU*f!0K(b#6@3`KbTbHQH4LC28`f-0Kjm$+M&C`&Hb$BBq!24*f,LbcD!I -$2Kcf%0L,BCm,qd$Bjm%bEGF"1`[f+0LMBBq"PHQei&VBHE#cBDI$2Jbf%eE'N!! -$cYFI"$X6pRf`liHp%IBQf2I![KG@CXD#[E!IK(dhl!f`Ym$H#RXEl)GJ2``VmhV -"IYL2`Yi1qc(BMm0q![D6X-c`A3ql'2D2B'A',mM!RJ6lD0M(`#k$lBBp%CCacY0 -J6i#p"2B&X!YKA`Ml)YMjX!YJ(`Yl-Zabf"@`Tm#H#VX)pMMBPE#VB"m"qdKBT[c --5*hAi9![qSmk8A2kJ&kRYm%!X*IDJJ(8P4T63fT*IF&1F"GFTXjJ'Ed2jY$Rp!D -B$SD"(q!%@!4fdH[d'[e(,i*lB!Zp!6D"(r30r@Ha!lbJ$fh[d%[J#(J%eS"2B"U -B!hk"Vf!HH!LHJN2J'lh0S8r"26!4I!8l`6c`&i`#%m!!-!eX"UIJ%H!XZ!Q1JJe -J&aJ1jS)0i!Mm!Pi#Gi&R`%(!'l!DlJ)f`hr!II!GV)HAJ12J2$`)22BB('QbDE! -0X2["6SHG$0X-f`Bl&[BJf*Q`(E$d06dk1aVkRSAbKl!Cf#cX40Kkf"aX!f`EE#Y -X#bbG3IFFHJ'EKMU6"bIP)CE(d!rd!$J"AS!IC1"h114[XBYkf2kh0H034qT*lDL -KAq&3NpQc@Bj$B0YK'f!lB'I"(Laadf#R`cE$cSKUQ"`I`!)'(mcjhpPm,m"a@eI --%A4USqM9C90f@PqheD*'NTc6fh,kfXBEb0IZhfT4(2bqIcG#[$1QZXdN[cpJjrk -*3JllNm@"I-fc#0Jc+ZMYQcNdFD5)LV5k*`@hTB6QUfYUAp0Gf'39U9bZc!-+2#& -l80`+KHKB0QXC,GKLV@@%pLk3!0EL&mS"Gh*3-5`c3l'!BA*3,5a@SEVBI&"2BC` -F9&)B+JGebLTr+*X`4!kUT@A6+*'@MD1Q@I4(1820iA`1&Jl2q4YB&![1Yf"45MM -r$S[#3RQTSeQ%*6i8&G35I#K0q2'KXU$+i%1YSIli8*&34[#K6U%Ni80&3XR"KiU -,BS-203lP"Kq+,+S02K4$mX@(!JMQik1@U$AirJirU&$ilXB2+JqqIm-2DJIY55e -4TI"4#j3aI+K6U&Ri8(a3Zr#K+1NbN3b9(e3SI#MCe"`ILLfU%cl34&@H$09Xe#P -mp#J+($l86K3iI035K3lIAq%(93hIRILK*[Mq#6qSBIKqK"rk#hJ")m!6I23KUKS -qkSZkKXmUD[K3Ue$Fm+&JSE,K3kP(QF1(!XbGq-!Be$Ym+0f+T&R@6*A1l'2iJ@A -LZ`XrU)[irK8r5JlVL'ZSI2MS@rS,(r8#(r#KX+(-i81C4+R$"di3L`q9('84(qS -ppF5(HSrUL!rm3rA%Kj+-)SR[-rK"%FAh&F&HI1!%+LLq(q)(M!+L`@[UJ!qX"!I -`J8dSTIM!!T4@I239+LSqkSLULJpe%884(`SJIRbSkkL$q*K-3&h%4bhT6AcJ")S -X2[!Ep4(I"Z%,q-"XF-P5#C4EI1!iUL3qkS4DLBmq4`A'4jhS,hc8J[VJ!`p3-[( -"PTMSm08F0MqYYK`VY!`E8dbl8r!!U%ZV3p-[@ii4[TZq2d&0fVBYdDP"i6mc(Ge -HD(9UCARZ'!CZEV!E`Z#pk5f&623@@%&kbhdl(`[VQr)k@D&,9BY6m5b@+(kVc88 -CPmVM%eJGp4Y&,pR5jKAB%MCaE%[BqY,9'%"2&S9*h*)NLLeKIIh0,1A`fGPrNGT -6h$5CQ8haCbVUJBU6)ZM`-9[#VY-He[kF'KVI#PRT63r3m86-+1aNNS-NX*rV&0Q -C4F8*BkLS3mE$KA,lmX!mJdGQf%m#@QF,rYQT2bI@)[SB)FF'f2Nr%j!!V,+!4l4 -(SlT"aX9'P[0X!h2!CrL'[d9PeSYVV4Q0&p[!GUaYE1m`!lIIahKi%%El(1GlAK[ -%K6N&qPHBJAJN-Zr%Xkah)jcVV0ibdTe6G#ZqS-f"1[!NSf!Lc5$IPZhUVJ-aR%2 -[8JbJQrq9kBjq"f2BCdGKmpIPfr4dj4BTdH(d58+DZLh5R'0V1)*F)4T*AQX@pEJ -AmfYhiN)(Sd@1'hH19bMaQRPepA9"b4j*9MTJR98`3XYeN!#[H105,9d[ATcG[[P -+!@bZl9IUf+&KjVH$-3iS@((SXHdDTP6F)eIQ+d8Ab$@Q#maXZI&%r53jZ-CCC#a -FELeC89b8VS4TQiQl[4*Y!MY2V+b8U2DfXZIkS8lf[X#`EGGe8-ae(R%M'UdR8T` -kUBjAaX'$H&3mk%jR@eV'FT!!3I2BRH4X#A"R"DlDdAh&1db$&1S#Z#l0V4phfmU -S8bZ$Yj!![3PHhJjNFCf`HU36SMK3jS6fpXKEl+am[2@@N!"-)P*SN!!3pCI`VLp -p[5[1Z(!pC8Nh2pJq-@d5"4pk["*4P%XSKU[m-J4T1Eh(`"l0''&Q6hV9lSe5S%V -QIVL"K%ZqFrBceT%0FHGM)c#!Y"6ZLjV%A8&pf2m3A`(UFD[&FUVPk!%iQJ4Da14 -'8eB$Hk@#N@%DR$D%)`8'U5*-6['j5+ZLG-3K5c2@Q8("Yl``ESK#3$lRq"DED#( -'e11FLC[L+K8M6AH93dUm"QDhB!ei@hkc3i+p#pE%V1"-e`PFfk`,`[lHJ*c[(0a -r8R[c6DB64Rk6d,*m)h`qTj2"4%QN@hYJj+a*YHPX8h1YAY[8f0Q)hqkfG+H-9[P -5cQpRGB[lkDd+(X9UN!"FBHGGhBS+TdReU9CbjI34A5Y4VFK(%Q&@D&-q%PSrF[d -@&H`h-aXp%`pj29$+ab4IL!bClYY4qA+Pa$NMUU82B4V@Kj!!B65C*E-118`DQS( -4`8NYkCSaicV2'8[Ih*(1R)F(B[V"9c20hDq4jqH)I"5[Er"09#6+jKF65S+b9Tl -lriMZ*Sck%Cd"CHDLImpbE)$N`[bdQ80RN!$8$*!!mVS!$K1NCR,8AXhSU*'3!!L -!FHlNVNaRV$PeKfrQf)l"YQA-d(G[0[e0JFj'DmpIhU%[dZS(lp2U0kcUbZSGV59 -eKClRhi,D"5Z9YJkEX!jkY'E"f[J9"ST+"XTQr&5QhM+(8LYh2kPfl0JaBX2RlZe -44imH(EG[`240l,pKeki6GpaRUcAY[5[0hIpJEhr``B5%21ha4p3GI1L2p4,J`pE -FJeNemIl'`[l%R@I-q$K@crfKV%(`Z4hr%eYYEqAq4c`4@rf*["e&rJeE,ILG6If -eZ1(iAVCDblRUMmp3(@UekXqP&TIQY512AIAER9prr8I[UqEGImqZ[YR4Xd0jf$e --jXe1BY(Zd0ckYark'6BIqN,H+*3lQ!#3!,ArB9*Hhcc&PXl)AGUr%A,[EA32'0) -iF`pidc4c$hM%0Y$U2@(e(M#VCI3HZmDXI!qieMTj6j`hZ-Ifd9Sqi1,ibAXZUGj -M0LVrY)j-)cem+Zq#JleSamhF`jkd4mlF`eD"*D2hp)dAQ,Imj0q190R$X[8H2p$ -b$&rcmFY06(X!*MjDaeE491rh`8emL!+D[",0E&6CHH,pF(k!ZHKB!3d(9-FXTA( -rUTemPQ1QX12M"9&!T42$$jcFEZ12k-3q,6VUa1,U1l-96rE6jV@jC,QG8kr0#`e -PTqe2lf(fGd3le,RH*mcF`mlN+C1DCC`hfZ[8mjUUh)0@1[qm"LT4l-apa-`pD+8 -$@[1ZHb3H6AUNMK*[jM"UfVA%Sb'2e&[LkBZ4HNXmZl0(kmJqj`(0[(!2QdF(Y2$ -#2H$&D4`!-2Y$L[R`#Jjl$kaM"(mNLThE!l-*KA[Bf$%`ke#iK`dI!c--KA[Bicf -LQGplMiIqH-hHcq&&f-B8R@4,FS&i9ULdjf`6XTIQh,mGVR#'-AMRaL+6'Jpb5&I -hdlk!Fr9j!$b8SA+I$q!&X(k5JmKURml$%,"pAJmRILD3!%m#,Rd)0,(kZ!0YM6c -)H*ifNr#i,11*0T0`G11$fdcbZqdMXGqHdFdNkIfe[(IA*kj(rlhhjVeh1m[Q[[% -(p0rZHr`(GUJ(Ulfk%81#iD5j#GZ@kT[iGNrBZXfAr41k2ZLGDJFYNeF"&ADU$5N -AIJ$fA2*[9Lj'eBEdIcGlV[VlmpjElpr8`hq3!2IZI@C$2GPrAfdA@jT2pC6c3"5 -ZE5Z,Yj&&eXZ`VEckjKdIh9D6`Y0+Gjiaidp6mG4T,Z`$mAqm3!ZQe0U4cFSEbl5 -`*hCdM6cV-T`lqU)HQDPCe0EHc1F[k[mXqHq3!2q$UcGRDNkm`%H#Z%L5VZFr1aN -+&fB['RqKM`bYD9E0FYPNr[-35[e[P@6-2I,I*[rM*AkFh$pGlVIj6"1rZ8rZDC! -!rlCU-HUL*c[NRlQLTC2Efq@rSATE`r[(RYNM(D3Cf6+E#XLG-k4#TR,LRmPr9SS -8FQQHce`+Vqq*hXkM"C!!bkE)rp468kck1$Z[cr&'c%a[d6!m!Lm&NcJb(GQ*+[G -`aFLZ8lRRClY6!8Ijj8@Nd6hQHB$ZZ*fMFJmML[Np+jPApmS!ir,,kdUMHl+[lT@ -"2XM[[-PlA(,3#rRYR,Q(r62(cpc$ATj(cGc$Qe"'pX$)2HcP'GQcSUp%AC[![ir -&4h!J2(!jmhrcpPpLPr4U[NSj1EkDp3hHPE2e[B$Y543[jK(dbX,@`EE#MS'YKmh -"0X!f`EE"MS8G$kZ[1Hdj%8kDe`XB*5*XD1Jc(G1h#Jh+Y&f[M"GSGAVaZmAA0q! -G@[+XS2`0AV*MC+"kiX$6M+5b$Yq'!mKhZ85ikD0)bFl)HrZAphYmkeqR[,l3TiB -1)@82QBSSiB!ESr+R)B("!AP29fGe!m$b%#rEA1-A4`E61U2A2(DZYT`'pHB0rLi -F-"06ScKJrXiVPpd%VfD[i8$$Ah&!f+1[M#ND(*!!9apd0[#*VQ[#j$EGd1#![0Z -hXk%KirTQLiAANEB[V9YHYbaT$4&#$cM!FPLQVmfD9"YT(!mFh$idK2(M'a2@3+& -i*Q,8b+i+MP$K#+##[16r)Dr2UrR3cRiBfbfL`SQ$(ri1hXCr,0qilfmllE,[)im -+Fm%9IUa8H@59XjrY,1"kT!39ZM$[RaNHrY@K"$G-m&#mLIE,!b-HXpNSI9J#-Eb -d*Sfc$bHS2P`KQYM2bF5qG`K!2"`RHV"5[,R"e`B$-!PK2jkic3heLA!6qhFQaNh -XJ`-H[iRpl[jHl!GZEh-+GRma)B`dr(TLhdF'!KB(r(!6qcFNaNhXhaP0l'I8qkG -IDMSehSMkKm0$9RKpJ"mJMk@CpYARla&Ufpj@TJC+CI[Z@*TVEdN)b'0PZLNCS+i -RjcXQ-pbCaiVQlXkkhT)U"%'pd[k`A9fdGR5MIq1Zb,I!X'dAVd!ibE3VVlX*[hT -2j![cm45EbH2-FrR+iaUkPU3A,hkp1f`H$ekF&*!!ajD#r$b2,BrDqApjE%jNHaj -RErE8S3HfaIekdp1PiGq[dZLIp!6QrLlDV6V-VHSb6(XdVLP'2ETKA`hLEpB1lHr -4lVTiH5@2TrbhAhP1J-PM5hZ3!%Hh%43-qh4KScc@m*N6AS!mcMaEf9TGH8k-c@- -)LEER-Icd%pUeGN`HkeAT$%j,'HB(C48"Y3e0FAT91M[0BlKMd4Y-jLbhd$pGY1% -$rhK'i,r"'VEQXEjNpjkrTl[jI&8PM`[k%`,bi-a"NrbZVVc(Bq39-Ii2aLf9lE[ -M2XBpQ)FhJ(%[@lefqQNM5h2VTq[Kq@$Z!e@pMlQ2j,'0ZBrNXBfjhj2(9ZCHbk2 -'h$R+h-2EjrFN!$$hMIAi&A-I,1a1jPl,BaYchjM',jPl,BpKjLjjM*!!piLjRph -hrllhIM"ZHFe5hahh-Hk"2$LH!-DpdR+@I9cI[1+D5FEGp$CMNM`f)m1pM'NNMfe --jjimYM+G@Klh)[R'2(k*j,8mKN&2mT!![Vq(QFqaVE0S99!N0R@)j(&HlmBcH5c -Vh6LG4e2QM3Hc0fBbkGDr`pr!q4RLGF@GH%mHkmja4FQ$&j`bChSq4Sl5iVU12X[ -FN!!380HpR-&ak@&1[Mf2'R)1pjRVM`[1YYR26N[d,,e0'$-f8KrA1!p"94T3SDS -RVd,G09"4(ld!HA6C3D!!-3)J!hN)eP2Ai)a1EP4$,d!pM0VR"FM$URe$H@aAqji -5PQfe&fq9)ip,X4%Y[%-l![rNcpGV!`FpY8[Emm5q[GZdRGF46!l!Ne(14IccY6f -20fN$cdFEe%`H6f8A$GCMY-p8C9RVRHjA*"B$4*[bi&f&!CqIZ,I[MFVL"HKASl* -i!I,J4(!@r+HZ*JpTMq"rrI%BecRhd,-`NmQpmp5jmZ(K@$AU%Fa,RTKmk-VHH9U -ELSlYXD&M1)`A))r&'rd0GE#rUbZXe&maXcKdUP`S2ANZp)Iqb(1K2r5V2f"@c(# -K[IJ"!TpZHG-61+0ep8mSeacP9,q[UmPMq-@MShQ-2"6a`15h'DqKXjhTq*9Q[2B -Hcp+-erRH@ACDUkZ2B-TECXAf(Jr)V0K'!2RPV0J!8[X#CX8+cfVZZk3KHB+jHbU -BU4F!1Id+5$9kDSYb2##DMXGP8ml3m4"S-AkJ66PlMfGT8mjf,DB[%5r"aTh04cI -ZE$lqVBdlYI(rS#DTB[jr'i2cEq`4Z*GjEFcM9maVX#!lQ9FY$qr%IS6Yc+X[%Er -!RS8S$r2NjB&$%V+00#)&Qqla!c!#NiGABZr$2[A$5cr@[6G!H*[R2Y(#5cm16)a -lk3GmS&RQLaVaahc4Q2Hd$r0&(VUh[bFi)&lI'L8`1*!!6BbE-r[jI*([E-kX-6& -ZcXc-&hRIjXbLq5*Ih*aCLjSerEUYi6-ZhC,"jGIQVE*RQjf&%iY`IA#6Dfa*@h2 -qP3iqQ-1E-4BhhY")feC9Dm`V6*CIhU%[dZS(lp2U0kcUbZSGV59eKClRhi,D"5Z -9YQirRUVpqCS&De@IhT@0%Y+hGQIdeN(aE%LYh2fN'KiHMYcb(cjhEmqBhpR8AiX -EMUr@G#6RUMmq3h@SeDSrPeTFQYH12(E9EhGqrI8I[DqDGrmpZrTQ4mm1jL&l8r` -[,+(RC,!L8bD$cHGp1C0UdpQQjPUpYUQaXa'rh@hTcYT%PIVVQrZR#N`+)L53!"" -UpeIZi3heVC9lFRc5I1'Lr$h6m([#j$dZ1EPR1RiAcY`c!lq,+[FdM0pc5I8HAS% -bBDU1KAYQiRI*k$ep"%(ZkF"[if3qm6fcm0X`Fmr"q'fDZHF3r1D5!qlCTe)iXT0 -V3Q@SSAeK21C`k0XTb-9,iMH'Y1cV2T!!"ih'Fma4Y3*ZEZZAB$GNAq"HYLM& -(ITZLal'dCr[2,'NIcYT8%8jDep5qTVZ`b5VQI(IMq[aV,d(`TVe8q16SGE[Q0,C -qKEr9pjGNPQb0I1(45k**"!r6qdXHXRA9f,XhT4mI0I95BBRG`(l0,,P9eeimM#% -a2pK,K5XiAAfTF)V6I[1A#RX4Q,XIk"9V3mbGBeqXqmdMp3N!c0d[p9,K[Afr6m[ -`8Z([I[XTX08"&DTkmLV8c-'+qZJ&b+2b8Z&+(Y8AfDDUQ&%0[3$e-'UI&b!2UrB -0jE&Gl61[Fedb-2T5iFbF9$ImmP,Kc,c2(9)r6eflp+Af!bRpm01i8PiU21jRL2q -ce,8,YkIQID'qNSGjRHYJ28ElV2*5i8SHeCF+ThP8ALUmTaj'CI%#p+Y4@E`!HA# -+,aAH8eH64r*5i6ejl#2D[&6B-lH*-rc0Vb0Iq2@lG[,I3l@*dr4[Y)Pc6E"*Vdc -8HpFfFDBilB2Ia2PljZj$fX3CVG[h"c"hRpBQcT'qhkGPf-4jmj8rJUVdLif$H4A -UM6XVkU-A))rl0h'QUTK4$Ed!p6"URaFJ$k[f$H@aAHflCa2RXEHIfX4jl+dR0h% -1eQ1dcqlIa*RQFImQcM32Sl*i!IV9U#aHJ$`iZcGaTR8eHIak%fHDalk9cLE1aD2 -!eVJVm[91q,rfRXJAjJm2m0r$T#pZH'$Ef&kRN!$qRKI@Q4lGX+m'm6GVKrEhD(G -G[,b5KcGU%qI2phR&QcJV10flLE1%dhlc6CaH"1EZ"jV5hXEF`p[Rpb3!-(I[d5E -1AdaAlqhlI9U'6CaVR)HJ+JfS80@69k(Z'ULSMek!2#UE1#Yjp'iF,+PL4MAd!Y6 -$U(eHJ$cF*Xj0H@aAqmcfZ3rN4MGaKRGS4q#A6CcK`%&2ADAYU9faGjZfmcU#L@c -LE(-3rhaYcf@2D!22iljiqpaJ28ElV,+*Xj*(lbE18Kk96CalkQ&8&Lp![aU9a3Z -3!!HRZ)Pc6ee0(XNQcMejl#2DE1,-`@E9((VNN@DY5Q[iGiRpB)Gh[)A!JFiqdc& -pUj!!f!B)B3SrGF5"TaR*E4KJF!!q8+p5$I%Bb[*qMibbXp8dLUBI*+N"3fKMMMm -mJ3-L9Mc$m#dc33d*3Zjcb"!(cJjppfE6ha6SqG"`LSCIK-`0'Pc8N!$*Yq[TKY@ -@dk$H[-(IK31L&qEH`J(cGekjl$S0ZIjHfbVSE8l"lLmQK*%'J`-0Im8"BBpH-K# -`10")[I"-,&YF%bDh5BEKTF#"*Z*!CmEec4DXh9b[,keEAVFXD3d4$"pSIZrBmZE -fVIfkMi2cjRCr(!kB[8$a#GAdq*S(jkbq-3L0XeML36KKp)UA0HGR5hd`KdRRaBd -h00+f9EI@Qpd"bbr[d"GTpB2hDI8E9R9PpBl@NVT#cr0[3Hf#P8TEYeqTMcjDXf# -YkY1lXY*jjQ6deN(aE%LYh2fN'KiHMYcb(cjhEmqBhpR8AiXEMUr@G#6RUMmq3h@ -SeDSrPeTFQYH12(E9EhGqrI8I[DqDGrmpZrTQ4mm1jT%l#%UceV&#bl#YVHGfGf` -m(J"'Y$SdrE,P'1'lkCZh5IJ3Z)5(i`MlRjLhbTjYkTd&@emBP+lf[-+LX5Z)LqE --@[EKF8MI3BJXGPKe)!'K0Z%RFG4hTICX5TX9eH8@+"RlkqKQH@@`IYkA-kNfR@e -UVY9VQaSl'r(EhCEZV%eLD31,!`I#@UbI"jX9hmQ`9ZeLadkpq&i-blZR10I!STY -`2JAE+,i[`cD*lapKQb9PmQN4hd(iD48IZ$9'I+IMCkcid%AEa(FjIKJY`(FMIXD -,lbra-d&mhm$242(p$eXpmQ9Birh%abkYbH*EM*rpaEF@2l*hbrKHJ*mTiRXpIUD -+li25,rMZ`-m$a!I+6iYp@IE'G2(0a-m-m4f((j8+XphiSIliRSiIlX(h-[adL1q -Gq*NP[NrLjf$ar5eq$K(I[q"(SDZ126aEI04&@8NGHrT"iMX&2kTBelRi18amj(f -iq-KlM[KJ,3m4heIa3qrJqajqMSappHcEZH)Mjk2%p`MmQ2I5Lqp8r"`M2NLYUU[ -eGq,RSH*lKq!2[SrLjf(Lqa*qp2%6p82iHAMXba&(k#Pmp!2jiL2QNH*EJ4rP4$R -f0bYfm&f-RrRLZ`Sr1S@EqaCq9"r22B)IRBE0X3B,aAFAIR5k,2F5INk-I3h%*Yh -mf-!qH,6ib"qF`8IrkAam!l9SR8CZf)kITH)$EaiM[[IM*e,*JMRI`ip+iJe(mI0 -BmIfcB$A`#`BX&amB32hadEINMSqkdiriq&mT2LDD`59mi0pTiRX6IX"NI1$Iim3 -(rMeHI0r&ca0LAa-arSRL!a0ALimqee9!6Db&,ZKTiUb"k[Y01r#M-`00c&[hT6A -GMam9-TTqJKrGVp9%(0,0$FhN%MVIdda-T0ra8@r9rCZC[qi,Dpk#(jhLE[ibIR5 -QX*NUj,RLSmEJ*$lkAVAKjTIa!fl,D5%Id)Qe&Z+GcNkdX1G9`'PK(AA'Sq8fr$a -,I'r%ciAL%l8Jf#`qm)Eki2X(r1MSC#Xjfjq+MlbI)ck`'%c$"bim9hc8QRcaJ6' --LZ"l!hiZ%4pjdqri[S#I&iV[QrMK6R`r`!qm6miBmV&,a3H[H)Ri`%Vk&api!DI -!4qeH,MjkqM,aL4)F%2rab8VQi%[Lqdrm[#VfM58hJrIKSlId"GeML9YALSrH!m2 -aF4HpM1mQr1M1[l'2iHGUmAdE2kq0I@hNY+m6(a`-l-8(6k"(m)'$p#NqqSdDiRX -,IYiX[NrJ"cqqVq(RVH,l-AlH&[['N8rUAX"aj%[`(AcJ1j`,(aJ%TmC(Rla,I2# -5DmAh'IaF*lkramqlBppiBX0la!IfAbmqqZB'mC%VZH!$+pQ#M3pFJ'[JSarJerK -Z`3ppK1qcq&'&IMah9(j!I2q&(hL"R!RNfpb*$djfUrMJBlH*$q`(cr&4l`q,MaU -!4IMS*I!"(c(`3AaJrqhLJh0m,2C0*1IqZ2LS2If)$qi+GmB(Ce-9EL,j#AU&TqR -8$AA`N62#[5DTFK"@ThhVKMl9U9+,`)UEYb'bX'1MEZJcd$UQ)5,,519RK31LcND -NXVlScY1!+I1!Fif5Te&M6H5TB-32!JVN'%P@,[)dF*lf&bQ*4ARDb1MNb"+D24p -lN!!c"kR81$8e*$E1LL0[*kijr6`NJp!l$bIk@B8Yd-McVSSMAd&-Gp0P'6,FaA( -N3kPN@I8YZ)#DcE`imR(NA&D,LeMkQ$LbMFcI+R14eR"%(2PbmM'Vd`9cb'`dcjZ -)P&De#pT`Cje%[SMBVaUHA)&+-#Q1R%,%9d92$PamDKcjXFIK8he2L)!S0j0kiXK -A-hY9qq5!lh9aj11*bkVp5AI!A!k))dmKNUX5+!IFeilkm-2`U5iSI8-AMSdM2d) -QU#UKT!J(rh3Fq5Pb6G8-TB%+(A8#kkN+SP3!IDBeM[`XApZ[HU)dZY3cI#+1[*' --5Y9&U3$F3l[M[Fa6Y8Dj$f9$UcDCl%b94kN!YIQ,1,+&[&ae5"(hK(Q(Pm54(b4 -DU#STR3[hqfJFq@eU%DT4#P6!bZI%N5(CVLU@)Rm*&QDNRY1T'DPq+H+6-,9--Bl -m$k+3!+UCJISqY+LM[KK(6U-f)0UQS,%`rEQXl!(P-#"1+`l@$A@MBUH#McHmVaa -'@h*Fj'R)XC(-q1KbD&09XC%Gck"r-cpQjmUG)(JbSe"AaGa[%4088D@ImjKl$2A -,r#JQ#SAHH6Q9$&9E"AcKm)UjAk6HSGUV("LP)YkjC1kUa%SAJZ@+%*1S[kSZ+l8 -"V44clk"US5UYG'%"FbmR,eI09L),Q,Z"D1''$lV4paCclbBI9MeAlU6E&9@H6FE -YCNiDH)GLlQdrJ%qehN#p$-A@BZiel%3hUaa5Ke$-[C!!U+3kX23RADLBqbbU1DS -+UmDR(E@3!2UADX452Y4CaGc[8)e3a9L+40D+Z9G6ae,p@1j%+G@1ZTjXAp9NLD6 -ZLP&I)ZDUYL`#XU#+aGb!@+K+Xpb*MU6Gm89LQZV1%NQP,AD!'kT#5bRJ'SUjee% -cG41r#c'qC6(h@e3r9+'@Y1"!LVP[TYkXHVANLF+LQ(XVle2e@Q44kAD,ZGqQrZ) -HmV3DM-pLlVQr4B!Ufi&@KKjR-AFLX8FdlEUKpDMjA(JFjLV$&$BV1Z2CB#5j9B+ -j,[*dm-#CB,0"[@#ZMHai'KbUJleL-6HCp`V*4V9[$U2bUHUk($3iaGcEb!G8DjI -XBD*kjq1)mhBD+@JKBLRQ[TVBVMUmS-S24l(`Fe6"9*8A3%$c8B3iL(UQfj496p9 -G-IG5pTfED-p`2N!apaV@e'fcbR)L3r2m#T959I0&SKAYbQ,Z!mJ(h1DB,"8b4CA -h-8G9qJ9cZ8-aG`)Vl9jmF$Akdf,ZhH6J1J8J"ie9-IFLGSV1"%LP[cq+Z9hdZ3e -k1I*DlDKR%BRFpV)QpSPLlN[*HA9k3'4qf,9LlVZT-HSXJ@!((%)lkJjU"6TC)*( -JQQ,8&@3NG[3qF+"`@X`pKbLV8`Gb*pUHGXG&e2"d"N'k!j9GUhB"F83R%U3fp*G -LlKH)[cUI)!+kU2X@Fap'(UA6#Y+Se&-aG`he5TeG%)5%b5RQ(NJ&@#FC4%BAIQ) -ap`kb#jeV%2&FXV'Bqh'bHCeb#,42!&8XjKj($9-k40LX-*!!ZCa1X*LVfSf`@G' -&cN)0``("h(bNB%#'#UN`B)1j6Zma6!%HC$%hL64X6r[QViNE1QNK&8#(9m`G5dD -MFaH#KI5ahRN9'CP1B3KBdDf+Z4G3fG'C$+NbM-SL(MaA*c3%LHKl4BLh8hqfUjZ -$TH5#LVPAF+,,V9F1141KQ$Z$f1&f04a&Y9Ac[*JFh'f$Z"MpBM(hJCb,F([aMb( -5+kTmJ`MTaPH2T(k[Q$Z2R-2Z@!rRJB90,X@4AbFlGlXmc9b@BZlhU35jr5pcUD) -VjVk"16[Gm%MLV(E8Fri%RpXC-CIpTCKlqqrJFj[Rcb"q+ZDqLE--6VNmQP0%9Ue -$9h+EUqB5qa5MEL(,GTVQ1Z4T-II2UA$S")Td&(a0Zq09R'e`Z`VQ8Q(3UKh)6YI -T&+N0(&Sap`M@aHQYjf-+a@,Z&839YrAM%ZVcLVR2T%VP"T'2MTLreSEZF*Y,AS" -D@-cp(KQRcVM)%)RJY-AFk84MRAJ*Y+p"(l5BZiV+SmbrL!BXfGj+hR#5B+kUSS+ -XSSpFKXKF56$A4Di!FR93q6K--0G'GK`&VRH3!$0Bc(9hVJ*ZA!pqdqbA`lja$IK -8)2&98(Bb(bYl!Hl-4ki%ehS*TM,#Kh,Y33Kf$K,TT)l36G"(9HMmRFY4e3iLh+f -S!$f@9m3%(@C4khZl4$VH[K,h2BL+a'b*G1aL*AMl#Q,XZb3bf8Kb#(%YkX+'$*8 -'Yh6Y%#SQ8HFfIZ3T8L%E@8Gp-%,*KKHTNHK8NHJhi0SCFH6GC"SkBb3XKQP!cI0 -jj0BkF56iLCi@jGR`3r*[R6m5VN)24(NfANTY6DH4T'rS!FhcR94eG$C*q!#+NHC -j$R&0*j@%@+1%D*jIilbTcLh4CrPkISJX3DHB"&$JcjVR(Db6cM3*#U%M4(NfcQD -11Z%NiJmiShdcLlfQmdk#3LLZQZGrF`T9TjqNRR5Gj[N$mJkCK4)F%0ai"R99LfZ -UkBY+Fi$5PJ)rRAlM)PHKCpDc8be#f-L1Sp!FCP%lYlMQlP`1,*p&hL$BBE$3c3k -BHU)q4M`UDj!!CHYXPJ`Mb&58DKIC1eJeRG3+0+TSLZ$CUmQBG@iVd&i!$l))rNV -QUP0F8NY33ERAPmJVGDC,+N"r4Y`V@dr-eJN[b36H%E'Bl(ELTmjlbCfI(q9HAk@ -qU00I3LVK34(hb[B5jh8@61k%L8AF+pY$K0(*-%'9JUlrBfT'lQdB,`1b+[I+pT( -MkY5Bb%p`S1M1V%HQVM0N%JQ1+5HkN3a6*mS#l5VJKI,Fl!l1DHTmQ@JNU&RD(Cq -QKUc6CN)$d6XLl-KHH!3qR6d6Q3Z'U28mL8LNNfK5!HDe)RDH[BbcEMUA*RI#Sj3 -aANY8e5NeZC-j+Q@-Rk6@TM0V!ReS&a&Mc*Bj3k)6E)&@"bh*-XBl1DIQhVRa'R) -0CB`r)YlSG*Z!(6J3G8HfMTaACpd#E3Q`64PMGJGhCqMNQr3RHNfNGf4A%Tpd$Nj -i,XLU9EZC'VK1a3RSdd@4hT(p009+RC%6'%-Y8EAK)q6Y1M%Rc33UG*H$9fB1&P# -TXT'*-YV&HYV)K(YeNA[Cb!4cMb&A'3GH#&p20*q6f,QAbCdDqAm!N!-K)3jdBfa -0B@03FQpUC@0dF`#3&Y%"J!*L!hF!N!-"!!)JN`#3"aB!N!1'!!!#!2q3"!-!V6C -3$,#%lk8!N!8-8kd!N!8#6elrerrl!*!'F!rhL`!!: Index: mac/tclMacResource.c ================================================================== --- mac/tclMacResource.c +++ mac/tclMacResource.c @@ -9,11 +9,11 @@ * 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. * - * SCCS: @(#) tclMacResource.c 1.35 97/11/24 15:03:58 + * RCS: @(#) $Id: tclMacResource.c,v 1.1.2.4 1999/04/14 00:34:52 surles Exp $ */ #include #include #include @@ -132,12 +132,10 @@ { Tcl_Obj *resultPtr, *objPtr; int index, result; long fileRef, rsrcId; FSSpec fileSpec; - Tcl_DString buffer; - char *nativeName; char *stringPtr; char errbuf[16]; OpenResourceFork *resourceRef; Handle resource = NULL; OSErr err; @@ -394,13 +392,13 @@ } else { FCBPBRec fileRec; Handle pathHandle; short pathLength; Str255 fileName; + Tcl_DString dstr; - if (strcmp(Tcl_GetStringFromObj(objv[2], NULL), "ROM Map") - == 0) { + if (strcmp(Tcl_GetString(objv[2]), "ROM Map") == 0) { Tcl_SetStringObj(resultPtr,"no file path for ROM Map", -1); return TCL_ERROR; } resourceRef = GetRsrcRefFromObj(objv[2], 1, "files", resultPtr); @@ -427,13 +425,16 @@ "could not get file path from token", -1); return TCL_ERROR; } HLock(pathHandle); - Tcl_SetStringObj(resultPtr,*pathHandle,pathLength); + Tcl_ExternalToUtfDString(NULL, *pathHandle, pathLength, &dstr); + + Tcl_SetStringObj(resultPtr, Tcl_DStringValue(&dstr), Tcl_DStringLength(&dstr)); HUnlock(pathHandle); DisposeHandle(pathHandle); + Tcl_DStringFree(&dstr); } return TCL_OK; case RESOURCE_LIST: if (!((objc == 3) || (objc == 4))) { Tcl_WrongNumArgs(interp, 2, objv, "resourceType ?resourceRef?"); @@ -469,10 +470,11 @@ resource = GetIndResource(rezType, i); } if (resource != NULL) { GetResInfo(resource, &id, (ResType *) &rezType, theName); if (theName[0] != 0) { + objPtr = Tcl_NewStringObj((char *) theName + 1, theName[0]); } else { objPtr = Tcl_NewIntObj(id); } @@ -490,26 +492,31 @@ if (limitSearch) { UseResFile(saveRef); } return TCL_OK; - case RESOURCE_OPEN: + case RESOURCE_OPEN: { + Tcl_DString ds, buffer; + char *str, *native; + int length; + if (!((objc == 3) || (objc == 4))) { Tcl_WrongNumArgs(interp, 2, objv, "fileName ?permissions?"); return TCL_ERROR; } - stringPtr = Tcl_GetStringFromObj(objv[2], &length); - nativeName = Tcl_TranslateFileName(interp, stringPtr, &buffer); - if (nativeName == NULL) { - return TCL_ERROR; + str = Tcl_GetStringFromObj(objv[2], &length); + if (Tcl_TranslateFileName(interp, str, &buffer) == NULL) { + return TCL_ERROR; } - err = FSpLocationFromPath(strlen(nativeName), nativeName, - &fileSpec) ; + native = Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&buffer), + Tcl_DStringLength(&buffer), &ds); + err = FSpLocationFromPath(Tcl_DStringLength(&ds), native, &fileSpec); + Tcl_DStringFree(&ds); Tcl_DStringFree(&buffer); + if (!((err == noErr) || (err == fnfErr))) { - Tcl_AppendStringsToObj(resultPtr, - "invalid path", (char *) NULL); + Tcl_AppendStringsToObj(resultPtr, "invalid path", (char *) NULL); return TCL_ERROR; } /* * Get permissions for the file. We really only understand @@ -528,11 +535,11 @@ case O_RDONLY: macPermision = fsRdPerm; break; case O_WRONLY: case O_RDWR: - macPermision = fsRdWrShPerm; + macPermision = fsRdWrPerm; break; default: panic("Tcl_ResourceObjCmd: invalid mode value"); break; } @@ -550,11 +557,11 @@ SetResLoad(true); if (fileRef == -1) { err = ResError(); if (((err == fnfErr) || (err == eofErr)) && - (macPermision == fsRdWrShPerm)) { + (macPermision == fsRdWrPerm)) { /* * No resource fork existed for this file. Since we are * opening it for writing we will create the resource fork * now. */ @@ -598,12 +605,12 @@ if (TclMacRegisterResourceFork(fileRef, resultPtr, TCL_RESOURCE_CHECK_IF_OPEN) != TCL_OK) { CloseResFile(fileRef); return TCL_ERROR; } - return TCL_OK; + } case RESOURCE_READ: if (!((objc == 4) || (objc == 5))) { Tcl_WrongNumArgs(interp, 2, objv, "resourceType resourceId ?resourceRef?"); return TCL_ERROR; @@ -627,11 +634,11 @@ resource = Tcl_MacFindResource(interp, rezType, resourceId, rsrcId, stringPtr, &releaseIt); if (resource != NULL) { size = GetResourceSizeOnDisk(resource); - Tcl_SetStringObj(resultPtr, *resource, size); + Tcl_SetByteArrayObj(resultPtr, (unsigned char *) *resource, size); /* * Don't release the resource unless WE loaded it... */ @@ -738,11 +745,11 @@ } } if (Tcl_GetOSTypeFromObj(interp, objv[i], &rezType) != TCL_OK) { return TCL_ERROR; } - stringPtr = Tcl_GetStringFromObj(objv[i+1], &length); + stringPtr = (char *) Tcl_GetByteArrayFromObj(objv[i+1], &length); if (gotInt == false) { rsrcId = UniqueID(rezType); } if (resourceId == NULL) { @@ -900,11 +907,11 @@ UseResFile(saveRef); } return result; default: - panic("Tcl_GetIndexFromObject returned unrecognized option"); + panic("Tcl_GetIndexFromObj returned unrecognized option"); return TCL_ERROR; /* Should never be reached. */ } } /* @@ -945,21 +952,21 @@ errStr = errNum; goto sourceFmtErr; } if (objc == 2) { - string = TclGetStringFromObj(objv[1], &length); + string = Tcl_GetStringFromObj(objv[1], &length); return Tcl_EvalFile(interp, string); } /* * The following code supports a few older forms of this command * for backward compatability. */ - string = TclGetStringFromObj(objv[1], &length); + string = Tcl_GetStringFromObj(objv[1], &length); if (!strcmp(string, "-rsrc") || !strcmp(string, "-rsrcname")) { - rsrcName = TclGetStringFromObj(objv[2], &length); + rsrcName = Tcl_GetStringFromObj(objv[2], &length); } else if (!strcmp(string, "-rsrcid")) { if (Tcl_GetLongFromObj(interp, objv[2], &rsrcID) != TCL_OK) { return TCL_ERROR; } } else { @@ -966,22 +973,20 @@ errStr = errBad; goto sourceFmtErr; } if (objc == 4) { - fileName = TclGetStringFromObj(objv[3], &length); + fileName = Tcl_GetStringFromObj(objv[3], &length); } return Tcl_MacEvalResource(interp, rsrcName, rsrcID, fileName); sourceFmtErr: Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), errStr, "should be \"", - Tcl_GetStringFromObj(objv[0], (int *) NULL), - " fileName\" or \"", - Tcl_GetStringFromObj(objv[0], (int *) NULL), - " -rsrc name ?fileName?\" or \"", - Tcl_GetStringFromObj(objv[0], (int *) NULL), - " -rsrcid id ?fileName?\"", (char *) NULL); + Tcl_GetString(objv[0]), " fileName\" or \"", + Tcl_GetString(objv[0]), " -rsrc name ?fileName?\" or \"", + Tcl_GetString(objv[0]), " -rsrcid id ?fileName?\"", + (char *) NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -1100,12 +1105,11 @@ SetSoundVolume(0, RESET_VOLUME); } } else { Tcl_AppendStringsToObj(resultPtr, " \"", sndArg, "\" is not a valid sound. (Try ", - Tcl_GetStringFromObj(objv[0], (int *) NULL), - " -list)", NULL); + Tcl_GetString(objv[0]), " -list)", NULL); return TCL_ERROR; } } return TCL_OK; @@ -1239,11 +1243,11 @@ NULL if application resource. */ { Handle sourceText; Str255 rezName; char msg[200]; - int result; + int result, iOpenedResFile = false; short saveRef, fileRef = -1; char idStr[64]; FSSpec fileSpec; Tcl_DString buffer; char *nativeName; @@ -1255,11 +1259,12 @@ nativeName = Tcl_TranslateFileName(interp, fileName, &buffer); if (nativeName == NULL) { return TCL_ERROR; } - err = FSpLocationFromPath(strlen(nativeName), nativeName, &fileSpec); + err = FSpLocationFromPath(strlen(nativeName), nativeName, + &fileSpec); Tcl_DStringFree(&buffer); if (err != noErr) { Tcl_AppendResult(interp, "Error finding the file: \"", fileName, "\".", NULL); return TCL_ERROR; @@ -1271,10 +1276,11 @@ fileName, "\".", NULL); return TCL_ERROR; } UseResFile(fileRef); + iOpenedResFile = true; } else { /* * The default behavior will search through all open resource files. * This may not be the behavior you desire. If you want the behavior * of this call to *only* search the application resource fork, you @@ -1311,11 +1317,12 @@ result = Tcl_Eval(interp, sourceStr); ckfree(sourceStr); if (result == TCL_RETURN) { result = TCL_OK; } else if (result == TCL_ERROR) { - sprintf(msg, "\n (rsrc \"%.150s\" line %d)", resourceName, + sprintf(msg, "\n (rsrc \"%.150s\" line %d)", + resourceName, interp->errorLine); Tcl_AddErrorInfo(interp, msg); } goto rezEvalCleanUp; @@ -1328,16 +1335,31 @@ "\" could not be loaded from ", (fileName != NULL ? fileName : "application"), ".", NULL); rezEvalCleanUp: + + /* + * TRICKY POINT: The code that you are sourcing here could load a + * shared library. This will go AHEAD of the resource we stored away + * in saveRef on the resource path. + * If you restore the saveRef in this case, you will never be able + * to get to the resources in the shared library, since you are now + * pointing too far down on the resource list. + * So, we only reset the current resource file if WE opened a resource + * explicitly, and then only if the CurResFile is still the + * one we opened... + */ + + if (iOpenedResFile && (CurResFile() == fileRef)) { + UseResFile(saveRef); + } + if (fileRef != -1) { CloseResFile(fileRef); } - UseResFile(saveRef); - return result; } /* *----------------------------------------------------------------------------- @@ -1680,11 +1702,11 @@ /* * Get the string representation. Make it up-to-date if necessary. */ - string = TclGetStringFromObj(objPtr, &length); + string = Tcl_GetStringFromObj(objPtr, &length); if (length != 4) { if (interp != NULL) { Tcl_ResetResult(interp); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), @@ -1803,11 +1825,11 @@ * * Register an open resource fork in the table of open resources * managed by the procedures in this file. If the resource file * is already registered with the table, then no new token is made. * - * The bahavior is controlled by the value of tokenPtr, and of the + * The behavior is controlled by the value of tokenPtr, and of the * flags variable. For tokenPtr, the possibilities are: * - NULL: The new token is auto-generated, but not returned. * - The string value of tokenPtr is the empty string: Then * the new token is auto-generated, and returned in tokenPtr * - tokenPtr has a value: The string value will be used for the token, @@ -1825,11 +1847,11 @@ * * Results: * Standard Tcl Result * * Side effects: - * An entry is added to the resource name table. + * An entry may be added to the resource name table. * *---------------------------------------------------------------------- */ int @@ -1851,16 +1873,18 @@ ResourceInit(); } /* * If we were asked to, check that this file has not been opened - * already. + * already with a different permission. It it has, then return an error. */ + new = 1; + if (flags & TCL_RESOURCE_CHECK_IF_OPEN) { Tcl_HashSearch search; - short oldFileRef; + short oldFileRef, filePermissionFlag; FCBPBRec newFileRec, oldFileRec; OSErr err; oldFileRec.ioCompletion = NULL; oldFileRec.ioFCBIndx = 0; @@ -1870,19 +1894,21 @@ newFileRec.ioFCBIndx = 0; newFileRec.ioNamePtr = NULL; newFileRec.ioVRefNum = 0; newFileRec.ioRefNum = fileRef; err = PBGetFCBInfo(&newFileRec, false); + filePermissionFlag = ( newFileRec.ioFCBFlags >> 12 ) & 0x1; resourceHashPtr = Tcl_FirstHashEntry(&resourceTable, &search); while (resourceHashPtr != NULL) { - oldFileRef = (short) Tcl_GetHashKey(&resourceTable, resourceHashPtr); - - + if (oldFileRef == fileRef) { + new = 0; + break; + } oldFileRec.ioVRefNum = 0; oldFileRec.ioRefNum = oldFileRef; err = PBGetFCBInfo(&oldFileRec, false); /* @@ -1889,38 +1915,56 @@ * err might not be noErr either because the file has closed * out from under us somehow, which is bad but we're not going * to fix it here, OR because it is the ROM MAP, which has a * fileRef, but can't be gotten to by PBGetFCBInfo. */ - - if ((oldFileRef == fileRef) || - ((err == noErr) + if ((err == noErr) && (newFileRec.ioFCBVRefNum == oldFileRec.ioFCBVRefNum) - && (newFileRec.ioFCBFlNm == oldFileRec.ioFCBFlNm))) { - - resourceId = (char *) Tcl_GetHashValue(resourceHashPtr); - Tcl_SetStringObj(tokenPtr, resourceId, -1); - return TCL_OK; + && (newFileRec.ioFCBFlNm == oldFileRec.ioFCBFlNm)) { + /* + * In MacOS 8.1 it seems like we get different file refs even + * though we pass the same file & permissions. This is not + * what Inside Mac says should happen, but it does, so if it + * does, then close the new res file and return the original + * one... + */ + + if (filePermissionFlag == ((oldFileRec.ioFCBFlags >> 12) & 0x1)) { + CloseResFile(fileRef); + new = 0; + break; + } else { + if (tokenPtr != NULL) { + Tcl_SetStringObj(tokenPtr, "Resource already open with different permissions.", -1); + } + return TCL_ERROR; + } } - resourceHashPtr = Tcl_NextHashEntry(&search); } - - } + - resourceHashPtr = Tcl_CreateHashEntry(&resourceTable, + /* + * If the file has already been opened with these same permissions, then it + * will be in our list and we will have set new to 0 above. + * So we will just return the token (if tokenPtr is non-null) + */ + + if (new) { + resourceHashPtr = Tcl_CreateHashEntry(&resourceTable, (char *) fileRef, &new); - if (!new) { - if (tokenPtr != NULL) { - resourceId = (char *) Tcl_GetHashValue(resourceHashPtr); - Tcl_SetStringObj(tokenPtr, resourceId, -1); - } - return TCL_OK; - } - - + } + + if (!new) { + if (tokenPtr != NULL) { + resourceId = (char *) Tcl_GetHashValue(resourceHashPtr); + Tcl_SetStringObj(tokenPtr, resourceId, -1); + } + return TCL_OK; + } + /* * If we were passed in a result pointer which is not an empty * string, attempt to use that as the key. If the key already * exists, silently fall back on resource%d... */ Index: mac/tclMacResource.r ================================================================== --- mac/tclMacResource.r +++ mac/tclMacResource.r @@ -10,11 +10,11 @@ * Copyright (c) 1994-97 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclMacResource.r 1.19 97/09/23 12:51:41 + * RCS: @(#) $Id: tclMacResource.r,v 1.1.2.2 1998/09/24 23:59:17 stanton Exp $ */ #include #include @@ -65,13 +65,11 @@ * resource fork the source command has been modified to support * sourcing from resources. In the below case "source -rsrc {Init}" * will load the TEXT resource named "Init". */ -read 'TEXT' (0, "Init", purgeable, preload) "::library:init.tcl"; -read 'TEXT' (1, "History", purgeable,preload) "::library:history.tcl"; -read 'TEXT' (2, "Word", purgeable,preload) "::library:word.tcl"; +#include "tclMacTclCode.r" /* * The following resource is used when creating the 'env' variable in * the Macintosh environment. The creation mechanisim looks for the * 'STR#' resource named "Tcl Environment Variables" rather than a Index: mac/tclMacShLib.exp ================================================================== --- mac/tclMacShLib.exp +++ mac/tclMacShLib.exp @@ -195,10 +195,11 @@ SetIsInvisible SetIsStationery SetNameLocked Share StrToAddr +TclAccess TclAllocateFreeObjects TclChdir TclCleanupByteCode TclCleanupCommand TclCompileBreakCmd @@ -248,11 +249,10 @@ TclDoGlob TclEmitForwardJump TclExecuteByteCode TclExpandCodeArray TclExpandJumpFixupArray -TclExpandParseValue TclExprFloatError TclFileAttrsCmd TclFileCopyCmd TclFileDeleteCmd TclFileMakeDirsCmd @@ -301,31 +301,28 @@ TclInvokeStringCommand TclIsProc TclLoadFile TclLooksLikeInt TclLookupVar -TclMacAccess +TclpAccess TclMacCreateEnv TclMacExitHandler TclMacFOpenHack TclMacInitExitToShell TclMacInstallExitToShellPatch TclMacOSErrorToPosixError TclMacReadlink TclMacRemoveTimer TclMacStartTimer -TclMacStat +TclpStat TclMacTimerExpired TclMatchFiles TclNeedSpace TclObjIndexForString TclObjInterpProc TclObjInvoke TclObjInvokeGlobal -TclParseBraces -TclParseNestedCmd -TclParseQuotes TclPlatformExit TclPlatformInit TclPreventAliasLoop TclPrintByteCodeObj TclPrintInstruction @@ -339,10 +336,11 @@ TclSetElementOfIndexedArray TclSetEnv TclSetIndexedScalar TclSetupEnv TclSockGetPort +TclStat TclTeardownNamespace TclTestChannelCmd TclTestChannelEventCmd TclUnsetEnv TclUpdateReturnInfo @@ -526,11 +524,10 @@ Tcl_GlobalEval Tcl_GlobalEvalObj Tcl_GlobalObjCmd Tcl_HashStats Tcl_HideCommand -Tcl_HistoryCmd Tcl_IfCmd Tcl_Import Tcl_IncrCmd Tcl_InfoObjCmd Tcl_Init Index: mac/tclMacSock.c ================================================================== --- mac/tclMacSock.c +++ mac/tclMacSock.c @@ -6,11 +6,11 @@ * 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. * - * SCCS: @(#) tclMacSock.c 1.59 97/10/09 18:24:42 + * RCS: @(#) $Id: tclMacSock.c,v 1.1.2.3 1999/04/14 00:34:53 surles Exp $ */ #include "tclInt.h" #include "tclPort.h" #include "tclMacInt.h" @@ -238,15 +238,19 @@ {"courier", 530}, {"uucp", 540}, {NULL, 0}, }; -/* - * Every open socket has an entry on the following list. - */ +typedef struct ThreadSpecificData { + /* + * Every open socket has an entry on the following list. + */ + + TcpState *socketList; +} ThreadSpecificData; -static TcpState *socketList = NULL; +static Tcl_ThreadDataKey dataKey; /* * Globals for holding information about OS support for sockets. */ @@ -282,68 +286,81 @@ InitSockets() { ParamBlockRec pb; OSErr err; long response; - - initialized = 1; - Tcl_CreateExitHandler(SocketExitHandler, (ClientData) NULL); - - if (Gestalt(gestaltMacTCPVersion, &response) == noErr) { - hasSockets = true; - } else { - hasSockets = false; - } - - if (!hasSockets) { - return; - } - - /* - * Load MacTcp driver and name server resolver. - */ - - - pb.ioParam.ioCompletion = 0L; - pb.ioParam.ioNamePtr = "\p.IPP"; - pb.ioParam.ioPermssn = fsCurPerm; - err = PBOpenSync(&pb); - if (err != noErr) { - hasSockets = 0; - return; - } - driverRefNum = pb.ioParam.ioRefNum; - - socketBufferSize = GetBufferSize(); - err = OpenResolver(NULL); - if (err != noErr) { - hasSockets = 0; - return; - } - - GetCurrentProcess(&applicationPSN); - /* - * Create UPP's for various callback routines. - */ - - resultUPP = NewResultProc(DNRCompletionRoutine); - completeUPP = NewTCPIOCompletionProc(IOCompletionRoutine); - closeUPP = NewTCPIOCompletionProc(CloseCompletionRoutine); - - /* - * Install an ExitToShell patch. We use this patch instead - * of the Tcl exit mechanism because we need to ensure that - * these routines are cleaned up even if we crash or are forced - * to quit. There are some circumstances when the Tcl exit - * handlers may not fire. - */ - - TclMacInstallExitToShellPatch(CleanUpExitProc); - - Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL); - - initialized = 1; + ThreadSpecificData *tsdPtr; + + if (! initialized) { + /* + * Do process wide initialization. + */ + + initialized = 1; + + if (Gestalt(gestaltMacTCPVersion, &response) == noErr) { + hasSockets = true; + } else { + hasSockets = false; + } + + if (!hasSockets) { + return; + } + + /* + * Load MacTcp driver and name server resolver. + */ + + + pb.ioParam.ioCompletion = 0L; + pb.ioParam.ioNamePtr = "\p.IPP"; + pb.ioParam.ioPermssn = fsCurPerm; + err = PBOpenSync(&pb); + if (err != noErr) { + hasSockets = 0; + return; + } + driverRefNum = pb.ioParam.ioRefNum; + + socketBufferSize = GetBufferSize(); + err = OpenResolver(NULL); + if (err != noErr) { + hasSockets = 0; + return; + } + + GetCurrentProcess(&applicationPSN); + /* + * Create UPP's for various callback routines. + */ + + resultUPP = NewResultProc(DNRCompletionRoutine); + completeUPP = NewTCPIOCompletionProc(IOCompletionRoutine); + closeUPP = NewTCPIOCompletionProc(CloseCompletionRoutine); + + /* + * Install an ExitToShell patch. We use this patch instead + * of the Tcl exit mechanism because we need to ensure that + * these routines are cleaned up even if we crash or are forced + * to quit. There are some circumstances when the Tcl exit + * handlers may not fire. + */ + + TclMacInstallExitToShellPatch(CleanUpExitProc); + } + + /* + * Do per-thread initialization. + */ + + tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey); + if (tsdPtr == NULL) { + tsdPtr->socketList = NULL; + Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL); + Tcl_CreateThreadExitHandler(SocketExitHandler, (ClientData) NULL); + } } /* *---------------------------------------------------------------------- * @@ -368,17 +385,16 @@ if (hasSockets) { Tcl_DeleteEventSource(SocketSetupProc, SocketCheckProc, NULL); /* CleanUpExitProc(); TclMacDeleteExitToShellPatch(CleanUpExitProc); */ } - initialized = 0; } /* *---------------------------------------------------------------------- * - * TclHasSockets -- + * 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. * @@ -391,16 +407,14 @@ * *---------------------------------------------------------------------- */ int -TclHasSockets( +TclpHasSockets( Tcl_Interp *interp) /* Interp for error messages. */ { - if (!initialized) { - InitSockets(); - } + InitSockets(); if (hasSockets) { return TCL_OK; } if (interp != NULL) { @@ -432,20 +446,21 @@ 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. */ - for (statePtr = socketList; statePtr != NULL; + for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if (statePtr->flags & TCP_RELEASE) { continue; } if (SocketReady(statePtr)) { @@ -478,10 +493,11 @@ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { TcpState *statePtr; SocketEvent *evPtr; TcpState dummyState; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } @@ -489,11 +505,11 @@ * Queue events for any ready sockets that don't already have events * queued (caused by persistent states that won't generate WinSock * events). */ - for (statePtr = socketList; statePtr != NULL; + for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { /* * Check to see if this socket is dead and needs to be cleaned * up. We use a dummy statePtr whose only valid field is the * nextPtr to allow the loop to continue even if the element @@ -1107,11 +1123,11 @@ /* *---------------------------------------------------------------------- * * TcpGetHandle -- * - * Called from Tcl_GetChannelFile to retrieve handles from inside + * Called from Tcl_GetChannelHandle to retrieve handles from inside * a file based channel. * * Results: * The appropriate handle or NULL if not present. * @@ -1468,21 +1484,22 @@ static TcpState * NewSocketInfo( StreamPtr tcpStream) { TcpState *statePtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); statePtr = (TcpState *) ckalloc((unsigned) sizeof(TcpState)); statePtr->tcpStream = tcpStream; statePtr->psn = applicationPSN; statePtr->flags = 0; statePtr->checkMask = 0; statePtr->watchMask = 0; statePtr->acceptProc = (Tcl_TcpAcceptProc *) NULL; statePtr->acceptProcData = (ClientData) NULL; - statePtr->nextPtr = socketList; - socketList = statePtr; + statePtr->nextPtr = tsdPtr->socketList; + tsdPtr->socketList = statePtr; return statePtr; } /* *---------------------------------------------------------------------- @@ -1503,15 +1520,17 @@ static void FreeSocketInfo( TcpState *statePtr) /* The state pointer to free. */ { - if (statePtr == socketList) { - socketList = statePtr->nextPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (statePtr == tsdPtr->socketList) { + tsdPtr->socketList = statePtr->nextPtr; } else { TcpState *p; - for (p = socketList; p != NULL; p = p->nextPtr) { + for (p = tsdPtr->socketList; p != NULL; p = p->nextPtr) { if (p->nextPtr == statePtr) { p->nextPtr = statePtr->nextPtr; break; } } @@ -1540,11 +1559,11 @@ ClientData sock) /* The socket to wrap up into a channel. */ { TcpState *statePtr; char channelName[20]; - if (TclHasSockets(NULL) != TCL_OK) { + if (TclpHasSockets(NULL) != TCL_OK) { return NULL; } statePtr = NewSocketInfo((StreamPtr) sock); /* TODO: do we need to set the port??? */ @@ -1767,11 +1786,11 @@ * - currently ignored */ { TcpState *statePtr; char channelName[20]; - if (TclHasSockets(interp) != TCL_OK) { + if (TclpHasSockets(interp) != TCL_OK) { return NULL; } /* * Create a new client socket and wrap it in a channel. @@ -1818,11 +1837,11 @@ ClientData acceptProcData) /* Data for the callback. */ { TcpState *statePtr; char channelName[20]; - if (TclHasSockets(interp) != TCL_OK) { + if (TclpHasSockets(interp) != TCL_OK) { return NULL; } /* * Create a new client socket and wrap it in a channel. @@ -1873,20 +1892,21 @@ * handle, such as TCL_FILE_EVENTS. */ { TcpState *statePtr; SocketEvent *eventPtr = (SocketEvent *) evPtr; int mask = 0; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; } /* * Find the specified socket on the socket list. */ - for (statePtr = socketList; statePtr != NULL; + for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if ((statePtr == eventPtr->statePtr) && (statePtr->tcpStream == eventPtr->tcpStream)) { break; } @@ -2124,11 +2144,11 @@ if (hostnameInited) { return hostname; } - if (TclHasSockets(NULL) == TCL_OK) { + if (TclpHasSockets(NULL) == TCL_OK) { err = GetLocalAddress(&ourAddress); if (err == noErr) { /* * Search for the doman name and return it if found. Otherwise, * just print the IP number to a string and return that. @@ -2264,14 +2284,15 @@ static pascal void CleanUpExitProc() { TCPiopb exitPB; TcpState *statePtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - while (socketList != NULL) { - statePtr = socketList; - socketList = statePtr->nextPtr; + while (tsdPtr->socketList != NULL) { + statePtr = tsdPtr->socketList; + tsdPtr->socketList = statePtr->nextPtr; /* * Close and Release the connection. */ @@ -2319,11 +2340,11 @@ OSErr err; int i; EventRecord dummy; DNRState dnrState; - if (TclHasSockets(NULL) != TCL_OK) { + if (TclpHasSockets(NULL) != TCL_OK) { return 0; } /* * Call StrToAddr to get the ip number for the passed in domain @@ -2534,11 +2555,11 @@ * 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 - * interp->result. + * the interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -2602,14 +2623,15 @@ static void ClearZombieSockets() { TcpState *statePtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - for (statePtr = socketList; statePtr != NULL; + for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if (statePtr->flags & TCP_RELEASE) { SocketFreeProc(statePtr); return; } } } ADDED mac/tclMacTclCode.r Index: mac/tclMacTclCode.r ================================================================== --- /dev/null +++ mac/tclMacTclCode.r @@ -0,0 +1,36 @@ +/* + * tclMacTclCode.r -- + * + * This file creates resources from the Tcl code that is + * usually stored in the TCL_LiBRARY + * + * 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. + * + * SCCS: @(#) tclMacTclCode.r 1.1 98/01/21 22:22:38 + */ + +#include +#include + +#define TCL_LIBRARY_RESOURCES 2000 + +/* + * The mechanisim below loads Tcl source into the resource fork of the + * application. The example below creates a TEXT resource named + * "Init" from the file "init.tcl". This allows applications to use + * Tcl to define the behavior of the application without having to + * require some predetermined file structure - all needed Tcl "files" + * are located within the application. To source a file for the + * resource fork the source command has been modified to support + * sourcing from resources. In the below case "source -rsrc {Init}" + * will load the TEXT resource named "Init". + */ + +read 'TEXT' (TCL_LIBRARY_RESOURCES, "Init", purgeable) "::library:init.tcl"; +read 'TEXT' (TCL_LIBRARY_RESOURCES + 1, "Auto", purgeable) "::library:auto.tcl"; +read 'TEXT' (TCL_LIBRARY_RESOURCES + 2, "Package", purgeable,preload) "::library:package.tcl"; +read 'TEXT' (TCL_LIBRARY_RESOURCES + 3, "History", purgeable) "::library:history.tcl"; +read 'TEXT' (TCL_LIBRARY_RESOURCES + 4, "Word", purgeable,preload) "::library:word.tcl"; Index: mac/tclMacTest.c ================================================================== --- mac/tclMacTest.c +++ mac/tclMacTest.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) tclMacTest.c 1.9 97/09/09 16:36:37 + * RCS: @(#) $Id: tclMacTest.c,v 1.1.2.2 1998/11/11 04:08:27 stanton Exp $ */ #define TCL_TEST #include "tclInt.h" @@ -186,15 +186,15 @@ } strcpy((char *) resourceName, rsrcName); c2pstr((char *) resourceName); - dataHandle = NewHandle(strlen(data) + 1); + dataHandle = NewHandle(strlen(data)); HLock(dataHandle); strcpy(*dataHandle, data); HUnlock(dataHandle); - + /* * Add the resource to the file and close it. */ AddResource(dataHandle, 'TEXT', rsrcID, resourceName); ADDED mac/tclMacThrd.c Index: mac/tclMacThrd.c ================================================================== --- /dev/null +++ mac/tclMacThrd.c @@ -0,0 +1,795 @@ +/* + * tclMacThrd.c -- + * + * This file implements the Mac-specific thread support. + * + * 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. + * + * SCCS: @(#) tclMacThrd.c 1.2 98/02/23 16:48:07 + */ + +#include "tclInt.h" +#include "tclPort.h" +#include "tclMacInt.h" +#include +#include + +#define TCL_MAC_THRD_DEFAULT_STACK (256*1024) + + +typedef struct TclMacThrdData { + ThreadID threadID; + VOID *data; + struct TclMacThrdData *next; +} TclMacThrdData; + +/* + * This is an array of the Thread Data Keys. It is a process-wide table. + * Its size is originally set to 32, but it can grow if needed. + */ + +static TclMacThrdData **tclMacDataKeyArray; +#define TCL_MAC_INITIAL_KEYSIZE 32 + +/* + * These two bits of data store the current maximum number of keys + * and the keyCounter (which is the number of occupied slots in the + * KeyData array. + * + */ + +static int maxNumKeys = 0; +static int keyCounter = 0; + +/* + * Prototypes for functions used only in this file + */ + +TclMacThrdData *GetThreadDataStruct(Tcl_ThreadDataKey keyVal); +TclMacThrdData *RemoveThreadDataStruct(Tcl_ThreadDataKey keyVal); + +/* + *---------------------------------------------------------------------- + * + * TclMacHaveThreads -- + * + * Do we have the Thread Manager? + * + * Results: + * 1 if the ThreadManager is present, 0 otherwise. + * + * Side effects: + * If this is the first time this is called, the return is cached. + * + *---------------------------------------------------------------------- + */ + +int +TclMacHaveThreads(void) +{ + static initialized = false; + static int tclMacHaveThreads = false; + long response = 0; + OSErr err = noErr; + + if (!initialized) { + err = Gestalt(gestaltThreadMgrAttr, &response); + if (err == noErr) { + tclMacHaveThreads = response | (1 << gestaltThreadMgrPresent); + } + } + + return tclMacHaveThreads; +} + +/* + *---------------------------------------------------------------------- + * + * 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(idPtr, proc, clientData) + Tcl_ThreadId *idPtr; /* Return, the ID of the thread */ + Tcl_ThreadCreateProc proc; /* Main() function of the thread */ + ClientData clientData; /* The one argument to Main() */ +{ + + if (!TclMacHaveThreads()) { + return TCL_ERROR; + } + +#if TARGET_CPU_68K && TARGET_RT_MAC_CFM + { + ThreadEntryProcPtr entryProc; + entryProc = NewThreadEntryProc(proc); + + NewThread(kCooperativeThread, entryProc, (void *) clientData, + TCL_MAC_THRD_DEFAULT_STACK, kCreateIfNeeded, NULL, (ThreadID *) idPtr); + } +#else + NewThread(kCooperativeThread, proc, (void *) clientData, + TCL_MAC_THRD_DEFAULT_STACK, kCreateIfNeeded, NULL, (ThreadID *) idPtr); +#endif + if ((ThreadID) *idPtr == kNoThreadID) { + return TCL_ERROR; + } else { + return TCL_OK; + } + +} + +/* + *---------------------------------------------------------------------- + * + * TclpThreadExit -- + * + * This procedure terminates the current thread. + * + * Results: + * None. + * + * Side effects: + * This procedure terminates the current thread. + * + *---------------------------------------------------------------------- + */ + +void +TclpThreadExit(status) + int status; +{ + ThreadID curThread; + + if (!TclMacHaveThreads()) { + return; + } + + GetCurrentThread(&curThread); + DisposeThread(curThread, NULL, false); +} + + +/* + *---------------------------------------------------------------------- + * + * Tcl_GetCurrentThread -- + * + * This procedure returns the ID of the currently running thread. + * + * Results: + * A thread ID. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tcl_ThreadId +Tcl_GetCurrentThread() +{ +#ifdef TCL_THREADS + ThreadID curThread; + + if (!TclMacHaveThreads()) { + return (Tcl_ThreadId) 0; + } else { + GetCurrentThread(&curThread); + return (Tcl_ThreadId) curThread; + } +#else + return (Tcl_ThreadId) 0; +#endif +} + + +/* + *---------------------------------------------------------------------- + * + * 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() +{ +#ifdef TCL_THREADS + /* There is nothing to do on the Mac. */; +#endif +} + + +/* + *---------------------------------------------------------------------- + * + * 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() +{ +#ifdef TCL_THREADS + /* There is nothing to do on the Mac */; +#endif +} + +/* + *---------------------------------------------------------------------- + * + * TclpMasterLock + * + * This procedure is used to grab a lock that serializes creation + * and finalization of serialization objects. This interface is + * only needed in finalization; it is hidden during + * creation of the objects. + * + * 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() +{ +#ifdef TCL_THREADS + /* There is nothing to do on the Mac */; +#endif +} + + +/* + *---------------------------------------------------------------------- + * + * TclpMasterUnlock + * + * This procedure is used to release a lock that serializes creation + * and finalization of synchronization objects. + * + * Results: + * None. + * + * Side effects: + * Release the master mutex. + * + *---------------------------------------------------------------------- + */ + +void +TclpMasterUnlock() +{ +#ifdef TCL_THREADS + /* There is nothing to do on the Mac */ +#endif +} + +#ifdef TCL_THREADS + +/* + *---------------------------------------------------------------------- + * + * Tcl_MutexLock -- + * + * This procedure is invoked to lock a mutex. This procedure + * handles initializing the mutex, if necessary. The caller + * can rely on the fact that Tcl_Mutex is an opaque pointer. + * This routine will change that pointer from NULL after first use. + * + * Results: + * None. + * + * Side effects: + * May block the current thread. The mutex is aquired when + * this returns. Will allocate memory for a pthread_mutex_t + * and initialize this the first time this Tcl_Mutex is used. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_MutexLock(mutexPtr) + Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ +{ +/* There is nothing to do on the Mac */ +} + + +/* + *---------------------------------------------------------------------- + * + * TclpMutexUnlock -- + * + * This procedure is invoked to unlock a mutex. The mutex must + * have been locked by Tcl_MutexLock. + * + * Results: + * None. + * + * Side effects: + * The mutex is released when this returns. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_MutexUnlock(mutexPtr) + Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ +{ +/* There is nothing to do on the Mac */ +} + + +/* + *---------------------------------------------------------------------- + * + * TclpFinalizeMutex -- + * + * This procedure is invoked to clean up one mutex. This is only + * safe to call at the end of time. + * + * This assumes the Master Lock is held. + * + * Results: + * None. + * + * Side effects: + * The mutex list is deallocated. + * + *---------------------------------------------------------------------- + */ + +void +TclpFinalizeMutex(mutexPtr) + Tcl_Mutex *mutexPtr; +{ +/* There is nothing to do on the Mac */ +} + + +/* + *---------------------------------------------------------------------- + * + * TclpThreadDataKeyInit -- + * + * This procedure initializes a thread specific data block key. + * Each thread has table of pointers to thread specific data. + * all threads agree on which table entry is used by each module. + * this is remembered in a "data key", that is just an index into + * this table. To allow self initialization, the interface + * passes a pointer to this key and the first thread to use + * the key fills in the pointer to the key. The key should be + * a process-wide static. + * + * There is no system-wide support for thread specific data on the + * Mac. So we implement this as an array of pointers. The keys are + * allocated sequentially, and each key maps to a slot in the table. + * The table element points to a linked list of the instances of + * the data for each thread. + * + * Results: + * None. + * + * Side effects: + * Will bump the key counter if this is the first time this key + * has been initialized. May grow the DataKeyArray if that is + * necessary. + * + *---------------------------------------------------------------------- + */ + +void +TclpThreadDataKeyInit(keyPtr) + Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, + * really (pthread_key_t **) */ +{ + + if (*keyPtr == NULL) { + keyCounter += 1; + *keyPtr = (Tcl_ThreadDataKey) keyCounter; + if (keyCounter > maxNumKeys) { + TclMacThrdData **newArray; + int i, oldMax = maxNumKeys; + + maxNumKeys = maxNumKeys + TCL_MAC_INITIAL_KEYSIZE; + + newArray = (TclMacThrdData **) + ckalloc(maxNumKeys * sizeof(TclMacThrdData *)); + + for (i = 0; i < oldMax; i++) { + newArray[i] = tclMacDataKeyArray[i]; + } + for (i = oldMax; i < maxNumKeys; i++) { + newArray[i] = NULL; + } + + if (tclMacDataKeyArray != NULL) { + ckfree((char *) tclMacDataKeyArray); + } + tclMacDataKeyArray = newArray; + + } + /* TclRememberDataKey(keyPtr); */ + } +} + +/* + *---------------------------------------------------------------------- + * + * TclpThreadDataKeyGet -- + * + * This procedure 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 * +TclpThreadDataKeyGet(keyPtr) + Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, + * really (pthread_key_t **) */ +{ + TclMacThrdData *dataPtr; + + dataPtr = GetThreadDataStruct(*keyPtr); + + if (dataPtr == NULL) { + return NULL; + } else { + return dataPtr->data; + } +} + + +/* + *---------------------------------------------------------------------- + * + * TclpThreadDataKeySet -- + * + * This procedure sets the pointer to a block of thread local storage. + * + * Results: + * None. + * + * Side effects: + * Sets up the thread so future calls to TclpThreadDataKeyGet with + * this key will return the data pointer. + * + *---------------------------------------------------------------------- + */ + +void +TclpThreadDataKeySet(keyPtr, data) + Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, + * really (pthread_key_t **) */ + VOID *data; /* Thread local storage */ +{ + TclMacThrdData *dataPtr; + ThreadID curThread; + + dataPtr = GetThreadDataStruct(*keyPtr); + + /* + * Is it legal to reset the thread data like this? + * And if so, who owns the memory? + */ + + if (dataPtr != NULL) { + dataPtr->data = data; + } else { + dataPtr = (TclMacThrdData *) ckalloc(sizeof(TclMacThrdData)); + GetCurrentThread(&curThread); + dataPtr->threadID = curThread; + dataPtr->data = data; + dataPtr->next = tclMacDataKeyArray[(int) *keyPtr - 1]; + tclMacDataKeyArray[(int) *keyPtr - 1] = dataPtr; + } +} + +/* + *---------------------------------------------------------------------- + * + * TclpFinalizeThreadData -- + * + * This procedure cleans up the thread-local storage. This is + * called once for each thread. + * + * Results: + * None. + * + * Side effects: + * Frees up all thread local storage. + * + *---------------------------------------------------------------------- + */ + +void +TclpFinalizeThreadData(keyPtr) + Tcl_ThreadDataKey *keyPtr; +{ + TclMacThrdData *dataPtr; + + if (*keyPtr != NULL) { + dataPtr = RemoveThreadDataStruct(*keyPtr); + + if ((dataPtr != NULL) && (dataPtr->data != NULL)) { + ckfree((char *) dataPtr->data); + ckfree((char *) dataPtr); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TclpFinalizeThreadDataKey -- + * + * This procedure is invoked to clean up one key. This is a + * process-wide storage identifier. The thread finalization code + * cleans up the thread local storage itself. + * + * On the Mac, there is really nothing to do here, since the key + * is just an array index. But we set the key to 0 just in case + * someone else is relying on that. + * + * Results: + * None. + * + * Side effects: + * The keyPtr value is set to 0. + * + *---------------------------------------------------------------------- + */ + +void +TclpFinalizeThreadDataKey(keyPtr) + Tcl_ThreadDataKey *keyPtr; +{ + ckfree((char *) tclMacDataKeyArray[(int) *keyPtr - 1]); + tclMacDataKeyArray[(int) *keyPtr - 1] = NULL; + *keyPtr = NULL; +} + + +/* + *---------------------------------------------------------------------- + * + * GetThreadDataStruct -- + * + * This procedure gets the data structure corresponding to + * keyVal for the current process. + * + * Results: + * The requested key data. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TclMacThrdData * +GetThreadDataStruct(keyVal) + Tcl_ThreadDataKey keyVal; +{ + ThreadID curThread; + TclMacThrdData *dataPtr; + + /* + * The keyPtr will only be greater than keyCounter is someone + * has passed us a key without getting the value from + * TclpInitDataKey. + */ + + if ((int) keyVal <= 0) { + return NULL; + } else if ((int) keyVal > keyCounter) { + panic("illegal data key value"); + } + + GetCurrentThread(&curThread); + + for (dataPtr = tclMacDataKeyArray[(int) keyVal - 1]; dataPtr != NULL; + dataPtr = dataPtr->next) { + if (dataPtr->threadID == curThread) { + break; + } + } + + return dataPtr; +} + + +/* + *---------------------------------------------------------------------- + * + * RemoveThreadDataStruct -- + * + * This procedure removes the data structure corresponding to + * keyVal for the current process from the list kept for keyVal. + * + * Results: + * The requested key data is removed from the list, and a pointer + * to it is returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TclMacThrdData * +RemoveThreadDataStruct(keyVal) + Tcl_ThreadDataKey keyVal; +{ + ThreadID curThread; + TclMacThrdData *dataPtr, *prevPtr; + + + if ((int) keyVal <= 0) { + return NULL; + } else if ((int) keyVal > keyCounter) { + panic("illegal data key value"); + } + + GetCurrentThread(&curThread); + + for (dataPtr = tclMacDataKeyArray[(int) keyVal - 1], prevPtr = NULL; + dataPtr != NULL; + prevPtr = dataPtr, dataPtr = dataPtr->next) { + if (dataPtr->threadID == curThread) { + break; + } + } + + if (dataPtr == NULL) { + /* No body */ + } else if ( prevPtr == NULL) { + tclMacDataKeyArray[(int) keyVal - 1] = dataPtr->next; + } else { + prevPtr->next = dataPtr->next; + } + + return dataPtr; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_ConditionWait -- + * + * This procedure is invoked to wait on a condition variable. + * On the Mac, mutexes are no-ops, and we just yield. After + * all, it is the application's job to loop till the condition + * variable is changed... + * + * + * Results: + * None. + * + * Side effects: + * Will block the current thread till someone else yields. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_ConditionWait(condPtr, mutexPtr, timePtr) + Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */ + Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ + Tcl_Time *timePtr; /* Timeout on waiting period */ +{ + if (TclMacHaveThreads()) { + YieldToAnyThread(); + } +} + +/* + *---------------------------------------------------------------------- + * + * 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(condPtr) + Tcl_Condition *condPtr; +{ + if (TclMacHaveThreads()) { + YieldToAnyThread(); + } +} + + +/* + *---------------------------------------------------------------------- + * + * 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(condPtr) + Tcl_Condition *condPtr; +{ + /* Nothing to do on the Mac */ +} + + + +#endif /* TCL_THREADS */ + ADDED mac/tclMacThrd.h Index: mac/tclMacThrd.h ================================================================== --- /dev/null +++ mac/tclMacThrd.h @@ -0,0 +1,20 @@ +/* + * tclUnixThrd.h -- + * + * This header file defines things for thread support. + * + * Copyright (c) 1998 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * SCCS: @(#) + */ + +#ifndef _TCLMACTHRD +#define _TCLMACTHRD + +#ifdef TCL_THREADS + +#endif /* TCL_THREADS */ +#endif /* _TCLMACTHRD */ Index: mac/tclMacTime.c ================================================================== --- mac/tclMacTime.c +++ mac/tclMacTime.c @@ -7,11 +7,11 @@ * 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. * - * SCCS: @(#) tclMacTime.c 1.19 97/06/27 13:07:10 + * RCS: @(#) $Id: tclMacTime.c,v 1.1.2.2 1999/03/10 06:49:25 stanton Exp $ */ #include "tclInt.h" #include "tclPort.h" #include @@ -239,13 +239,14 @@ *---------------------------------------------------------------------- */ struct tm * TclpGetDate( - const time_t *tp, /* Time struct to fill. */ + TclpTime_t time, /* Time struct to fill. */ int useGMT) /* True if date should reflect GNT time. */ { + const time_t *tp = (const time_t *)time; DateTimeRec dtr; MachineLocation loc; long int offset; static struct tm statictime; static const short monthday[12] = Index: mac/tclMacUnix.c ================================================================== --- mac/tclMacUnix.c +++ mac/tclMacUnix.c @@ -5,16 +5,16 @@ * available to the Unix implementation, but that require * extra work to do on a Macintosh. These include routines * Unix Tcl normally hands off to the Unix OS. * * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center - * Copyright (c) 1994-1996 Sun Microsystems, Inc. + * 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. * - * SCCS: @(#) tclMacUnix.c 1.56 96/12/12 19:38:08 + * RCS: @(#) $Id: tclMacUnix.c,v 1.1.2.2 1998/09/24 23:59:18 stanton Exp $ */ #include #include #include @@ -49,64 +49,10 @@ */ #define usageErr 500 #define noSourceErr 501 #define isDirErr 502 -/* - * Static functions in this file. - */ - -static int GlobArgs _ANSI_ARGS_((Tcl_Interp *interp, - int *argc, char ***argv)); - -/* - *---------------------------------------------------------------------- - * - * GlobArgs -- - * - * The following function was taken from Peter Keleher's Alpha - * Editor. *argc should only count the end arguments that should - * be globed. argv should be incremented to point to the first - * arg to be globed. - * - * Results: - * Returns 'true' if it worked & memory was allocated, else 'false'. - * - * Side effects: - * argv will be alloced, the call will need to release the memory - * - *---------------------------------------------------------------------- - */ - -static int -GlobArgs( - Tcl_Interp *interp, /* Tcl interpreter. */ - int *argc, /* Number of arguments. */ - char ***argv) /* Argument strings. */ -{ - int res, len; - char *list; - - /* - * Places the globbed args all into 'interp->result' as a list. - */ - res = Tcl_GlobCmd(NULL, interp, *argc + 1, *argv - 1); - if (res != TCL_OK) { - return false; - } - len = strlen(interp->result); - list = (char *) ckalloc(len + 1); - strcpy(list, interp->result); - Tcl_ResetResult(interp); - - res = Tcl_SplitList(interp, list, argc, argv); - ckfree((char *) list); - if (res != TCL_OK) { - return false; - } - return true; -} /* *---------------------------------------------------------------------- * * Tcl_EchoCmd -- @@ -136,28 +82,28 @@ chan = Tcl_GetChannel(interp, "stdout", &mode); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } for (i = 1; i < argc; i++) { - result = Tcl_Write(chan, argv[i], -1); + result = Tcl_WriteChars(chan, argv[i], -1); if (result < 0) { Tcl_AppendResult(interp, "echo: ", Tcl_GetChannelName(chan), ": ", Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } if (i < (argc - 1)) { - Tcl_Write(chan, " ", -1); + Tcl_WriteChars(chan, " ", -1); } } - Tcl_Write(chan, "\n", -1); + Tcl_WriteChars(chan, "\n", -1); return TCL_OK; } /* *---------------------------------------------------------------------- * - * Tcl_LsCmd -- + * Tcl_LsObjCmd -- * * This procedure is invoked to process the "ls" Tcl command. * See the user documentation for details on what it does. * * Results: @@ -167,47 +113,49 @@ * See the user documentation. * *---------------------------------------------------------------------- */ int -Tcl_LsCmd( +Tcl_LsObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument strings. */ { #define STRING_LENGTH 80 #define CR '\n' int i, j; int fieldLength, len = 0, maxLen = 0, perLine; - char **origArgv = argv; OSErr err; CInfoPBRec paramBlock; HFileInfo *hpb = (HFileInfo *)¶mBlock; DirInfo *dpb = (DirInfo *)¶mBlock; char theFile[256]; char theLine[STRING_LENGTH + 2]; int fFlag = false, pFlag = false, aFlag = false, lFlag = false, cFlag = false, hFlag = false; + char *argv; + Tcl_Obj *newObjv[2], *resultObjPtr; /* * Process command flags. End if argument doesn't start * with a dash or is a dash by itself. The remaining arguments * should be files. */ - for (i = 1; i < argc; i++) { - if (argv[i][0] != '-') { + for (i = 1; i < objc; i++) { + argv = Tcl_GetString(objv[i]); + if (argv[0] != '-') { break; } - if (!strcmp(argv[i], "-")) { + if (!strcmp(argv, "-")) { i++; break; } - for (j = 1 ; argv[i][j] ; ++j) { - switch(argv[i][j]) { + for (j = 1 ; argv[j] ; ++j) { + switch(argv[j]) { case 'a': case 'A': aFlag = true; break; case '1': @@ -235,27 +183,37 @@ return TCL_ERROR; } } } - argv += i; - argc -= i; + objv += i; + objc -= i; /* * No file specifications means we search for all files. * Glob will be doing most of the work. */ - if (!argc) { - argc = 1; - argv = origArgv; - strcpy(argv[0], "*"); + if (!objc) { + objc = 1; + newObjv[0] = Tcl_NewStringObj("*", -1); + newObjv[1] = NULL; + objv = newObjv; + } + + if (Tcl_GlobObjCmd(NULL, interp, objc + 1, objv - 1) != TCL_OK) { + Tcl_ResetResult(interp); + return TCL_ERROR; + } + + resultObjPtr = Tcl_GetObjResult(interp); + Tcl_IncrRefCount(resultObjPtr); + if (Tcl_ListObjGetElements(interp, resultObjPtr, &objc, &objv) != TCL_OK) { + Tcl_DecrRefCount(resultObjPtr); + return TCL_ERROR; } - if (!GlobArgs(interp, &argc, &argv)) { - Tcl_ResetResult(interp); - return TCL_ERROR; - } + Tcl_ResetResult(interp); /* * There are two major methods for listing files: the long * method and the normal method. */ @@ -262,10 +220,13 @@ if (lFlag) { char creator[5], type[5], time[16], date[16]; char lineTag; long size; unsigned short flags; + Tcl_Obj *objPtr; + char *string; + int length; /* * Print the header for long listing. */ if (hFlag) { @@ -276,12 +237,12 @@ Tcl_AppendResult(interp, "-------------------------------------------------------------\n", NULL); } - for (i = 0; i < argc; i++) { - strcpy(theFile, argv[i]); + for (i = 0; i < objc; i++) { + strcpy(theFile, Tcl_GetString(objv[i])); c2pstr(theFile); hpb->ioCompletion = NULL; hpb->ioVRefNum = 0; hpb->ioFDirIndex = 0; @@ -345,15 +306,14 @@ Tcl_AppendResult(interp, theLine, "\n", NULL); } - if ((interp->result != NULL) && (*(interp->result) != '\0')) { - int slen = strlen(interp->result); - if (interp->result[slen - 1] == '\n') { - interp->result[slen - 1] = '\0'; - } + objPtr = Tcl_GetObjResult(interp); + string = Tcl_GetStringFromObj(objPtr, &length); + if ((length > 0) && (string[length - 1] == '\n')) { + Tcl_SetObjLength(objPtr, length - 1); } } else { /* * Not in long format. We only print files names. If the * -C flag is set we need to print in multiple coloumns. @@ -367,12 +327,13 @@ */ if (!cFlag) { perLine = 1; fieldLength = STRING_LENGTH; } else { - for (i = 0; i < argc; i++) { - len = strlen(argv[i]); + for (i = 0; i < objc; i++) { + argv = Tcl_GetString(objv[i]); + len = strlen(argv); if (len > maxLen) { maxLen = len; } } fieldLength = maxLen + 3; @@ -380,12 +341,12 @@ } argCount = 0; linePos = 0; memset(theLine, ' ', STRING_LENGTH); - while (argCount < argc) { - strcpy(theFile, argv[argCount]); + while (argCount < objc) { + strcpy(theFile, Tcl_GetString(objv[argCount])); c2pstr(theFile); hpb->ioCompletion = NULL; hpb->ioVRefNum = 0; hpb->ioFDirIndex = 0; @@ -455,10 +416,10 @@ } else { Tcl_AppendResult(interp, theLine, NULL); } } } - - ckfree((char *) argv); - + + Tcl_DecrRefCount(resultObjPtr); + return TCL_OK; } Index: mac/tclMacUtil.c ================================================================== --- mac/tclMacUtil.c +++ mac/tclMacUtil.c @@ -8,11 +8,11 @@ * 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. * - * SCCS: @(#) tclMacUtil.c 1.53 97/07/30 16:46:16 + * RCS: @(#) $Id: tclMacUtil.c,v 1.1.2.2 1998/09/24 23:59:19 stanton Exp $ */ #include "tcl.h" #include "tclInt.h" #include "tclMacInt.h" @@ -199,11 +199,11 @@ */ int FSpLocationFromPath( int length, /* Length of path. */ - char *path, /* The path to convert. */ + CONST char *path, /* The path to convert. */ FSSpecPtr fileSpecPtr) /* On return the spec for the path. */ { Str255 fileName; OSErr err; short vRefNum; Index: tests/README ================================================================== --- tests/README +++ tests/README @@ -1,96 +1,423 @@ -Tcl Test Suite --------------- - -SCCS: @(#) README 1.6 96/04/17 10:51:11 - -This directory contains a set of validation tests for the Tcl -commands. Each of the files whose name ends in ".test" is -intended to fully exercise one or a few Tcl commands. The -commands tested by a given file are listed in the first line -of the file. - -You can run the tests in two ways: +README -- Tcl test suite design document. + +RCS: @(#) $Id: README,v 1.1.2.8 1999/04/07 01:59:27 hershey Exp $ + +Contents: +--------- + + 1. Introduction + 2. Definitions file + 3. Writing a new test + 4. Constraints + 5. Adding a New Test File + 6. Test output + 7. Selecting tests for execution within a file + 8. Selecting files to be sourced by all.tcl + 9. Incompatibilities with prior Tcl versions + +1. Introduction: +---------------- + +This directory contains a set of validation tests for the Tcl commands +and C Library procedures for Tcl. Each of the files whose name ends +in ".test" is intended to fully exercise the functions in the C source +file that corresponds to the file prefix. The C functions and/or Tcl +commands tested by a given file are listed in the first line of the +file. + +You can run the tests in three ways: + (a) type "make test" in ../unix; this will run all of the tests. - (b) start up tcltest in this directory, then "source" the test + + (b) type "tcltest ?