Compare commits

...
Author SHA1 Message Date
ferrieux 1e227ad96b Zap outdated comment. 2014-09-08 21:36:53 +00:00
ferrieux 023afbc349 Don't leak our temp sorted chunk table. 2014-09-06 19:56:32 +00:00
dkf a6adbc9a84 a little bit of code tidy-up 2014-09-06 14:31:09 +00:00
ferrieux 5e91384e89 Qsort gotcha: pointer difference is *not* a proper order unless computed in N+1 bits. Use explicit comparison instead. 2014-09-06 13:19:21 +00:00
ferrieux 376e1e4c2a merge trunk 2014-09-05 20:42:40 +00:00
ferrieux b47df5123e Distinguish hanging from crashing in exit tests. 2014-09-03 19:44:29 +00:00
ashok 996c102b1f [132fad6fde]. Fixed GetCache to use TclpSysAlloc+memset instead
of calloc. Now consistent with tclWinThrd.c which no longer
uses malloc in its TclpSysAlloc implementation.
2014-09-03 15:48:56 +00:00
ferrieux a024a52335 Refrain from calling TclFinalizeThreadData() in quick-exit case as it is useless (just memory freeing). Superficially fixes [Bug 132fad6f]; that bug is still exerciseable thanks to recent additions to the test suite that exercise full finalization. 2014-09-02 22:00:03 +00:00
ferrieux 2e4f40528b Add test cases in very first position for hang-on-exit, both in (normal) quick-exit and TCL_FINALIZE_ON_EXIT=1 modes. 2014-09-02 21:57:20 +00:00
jan.nijtmans 8964b0101f Combine TCL_SHLIB_LD_EXTRAS+TK_SHLIB_LD_EXTRAS (for Cygwin and FreeBSD) to a single SHLIB_LD_LIBS usable for both Tcl and Tk 2014-09-01 08:17:49 +00:00
jan.nijtmans 6d02d4e9dc Combine TCL_SHLIB_LD_EXTRAS+TK_SHLIB_LD_EXTRAS (for Cygwin and FreeBSD) to a single SHLIB_LD_LIBS usable for both Tcl and Tk. 2014-09-01 08:11:52 +00:00
dgp 6e00c594ea Use TclpSys* macros, not direct system calls. 2014-08-29 17:33:06 +00:00
dkf 77e18bafa5 [b9e1a3032e] Implement the documented method search order for TclOO.
This corrects the relative positions of object-defined methods and class mixins.
2014-08-28 07:53:24 +00:00
dgp bcdc8e8a6d merge release 2014-08-27 20:34:04 +00:00
dgp 7cd4eb1657 merge trunk; update changes 2014-08-25 21:43:21 +00:00
dgp a562752936 TIP 429 implementation. New command [string cat]. 2014-08-25 21:37:58 +00:00
dgp 46346effdc merge-mark 2014-08-25 15:40:01 +00:00
dgp 6c10f6324b merge release 2014-08-25 15:36:16 +00:00
dgp ae0f801eaf Do not let fossil README droppings leak into distribuion 2014-08-25 13:51:31 +00:00
dgp a9c6d78680 make dist allowed README-* fossil droppings to leak into the distribution. 2014-08-25 13:31:10 +00:00
dgp dbacb46d52 Bump to zlib 2.0.1. 2014-08-22 22:11:13 +00:00
dgp 7ab1ebdc32 Bump to TclOO 1.0.2 2014-08-22 21:52:37 +00:00
dgp 3ca10397cf merge trunk; stamp release date. 2014-08-22 17:28:46 +00:00
dgp 13e336e4cd merge 8.5; fix notifier mask bug and Tcl_Read performance regression 2014-08-22 13:48:50 +00:00
dgp 80604a93c1 merge 8.5; stamp release date 2014-08-22 13:44:23 +00:00
dgp aa8f4d27ac Correct performance regression in a series of short binary reads from a
socket.  Many thanks to Eric Boudaillier for the report and testing support.
2014-08-22 13:23:04 +00:00
dgp b08dc28c80 Same results; simpler logic. 2014-08-22 13:20:21 +00:00
dgp 92f9aca55f Test fix for likely cause of reported I/O slowdown.
In a DoRead() revision, it came to favor making every effort to fill
buffers, in preference to a more sensible goal of favoring avoiding calls
out to the driver if there's already enough data in the buffers to satisfy
the read operation.  Result is many more calls out to recv() than are
a good idea.  Ought to show up most glaringly when many Tcl_Read() calls
asking for small numbers of bytes (compared to buffer size) each, and that
matches the reported case.
2014-08-21 23:07:34 +00:00
andreask ce04ed5ad3 Fix reviewed and accepted. 2014-08-20 18:59:31 +00:00
dgp eda831ff7e Make test io-36.1.1 more portable. 2014-08-20 18:40:07 +00:00
dgp bc9dca8ca6 Docs for Tcl_CreateChannelHandler() state that the registered handler proc
will be called back with a mask value. "Mask is an integer mask indicating
which of the requested conditions actually exists for the channel; it will
contain ***a subset of the bits from the mask argument*** to
Tcl_CreateChannelHandler when the handler was created." (emhpasis added).

Tcl_NotifyChannel is not honoring this.  It passes a mask value that may
contain bits not in common with the mask argument to T_CCH().

This commit is a one-liner patch adding in the masking step to make things
behave as documented.  Thanks to apn for digging this out.  (In combination
with other questionable code, this led to a hang in test http-4.6 on Windows)

Tcl_NotifyChannel() has had this error in all of recorded Tcl history.
It's hard to imagine any code dependent on it though.  If any exists, it
can be revised to pass the mask value it truly needs to T_CCH() and end up
with code suitable both before and after this change.

If you concur, please merge to core-8-5-branch, and I'll take it from there.
2014-08-20 17:50:41 +00:00
dgp f8a968fdb8 Additions to changes. 2014-08-20 14:28:36 +00:00
jan.nijtmans 72fee4f1c7 [74e073599e5e7c5eb535e2f60f1b06feb468eaae|74e073599e]: tclsh is using old style dialogs when Tk is loaded on Windows 2014-08-20 11:23:09 +00:00
jan.nijtmans 71f6f450b2 [74e073599e5e7c5eb535e2f60f1b06feb468eaae|74e073599e]: tclsh is using old style dialogs when Tk is loaded on Windows 2014-08-20 11:13:29 +00:00
ferrieux f2225b9dc1 merge trunk 2014-08-19 20:35:16 +00:00
dgp 344b547cd4 Update changes file. 2014-08-19 18:34:09 +00:00
dgp 60125626dc merge trunk 2014-08-19 13:39:19 +00:00
dgp 36c74f5033 Improved credit 2014-08-18 13:28:58 +00:00
dkf 02b159d09e [7d52e1101b] oo::object should know that oo::class is a subclass. 2014-08-17 15:23:49 +00:00
dgp d5113635d3 Reconcile changes file with 8.6.1. 2014-08-14 16:48:08 +00:00
dgp 7cfbfdffd3 merge 8.5 2014-08-14 16:36:44 +00:00
ferrieux 49dbc80e0d Proof-of-concept of a nonmonotonic Tcl_Obj allocator, with zero perf impact and explicit ::tcl::unsupported::gc. Works with both threadAlloc and the older one. Disappointment: though it does free() the blocks, glibc is very reluctant to give back the pages to the OS :( 2014-08-14 16:32:08 +00:00
jan.nijtmans a0e133cb07 Put back SystemV timezone files, which were removed in previous commit. Don't know if that was by accident, but seems unwise in a Tcl patch release. 2014-08-13 09:06:09 +00:00
jan.nijtmans e4a9f37030 Put back SystemV timezone files, which were removed in previous commit. Don't know if that was by accident, but seems unwise in a Tcl patch release. 2014-08-13 09:04:55 +00:00
dgp 459724f70a merge 8.5, update changes 2014-08-13 02:54:31 +00:00
Kevin B Kenny 7f8321b616 merge tzdata2014f from ietf.org 2014-08-13 01:45:39 +00:00
Kevin B Kenny ac5fa7c959 tzdata2014f from ietf.org 2014-08-13 01:42:17 +00:00
dgp 8c3d28816c Update changes file 2014-08-12 21:41:29 +00:00
dgp 13828f74ee merge 8.5 2014-08-12 15:51:06 +00:00
dgp 822b0d469e merge trunk 2014-08-12 15:47:20 +00:00
dgp 8755613114 merge-mark. Do not accommodate udp bugs in Tcl 8.6.2. 2014-08-12 15:46:20 +00:00
dgp c93483448e Accommodate the "udp" package, and any other Tcl package that expects a
[read] on a channel @ EOF to attempt another pass through the channel drivers
instead of immediately returning an empty string.  Correcting this misbehavior
appears too disruptive in a patch release to a long stable branch.
2014-08-12 15:28:09 +00:00
andreask 582c164dc3 Fixed type conversion warnings which break a Win32 debug build (MSVC). 2014-08-06 18:20:56 +00:00
ferrieux 91b9c5690e Fix comment inaccuracy. 2014-08-05 22:10:58 +00:00
ferrieux d544f36344 More aggressive constant folding in [string cat]. Thanks AndreasK for kicking. 2014-08-05 18:20:48 +00:00
ferrieux 796e087b9c Better organize [string cat] by chunks of 255 args. 2014-08-05 11:29:16 +00:00
ferrieux 76e87312ed Add constant folding to [string cat]. Mixed-quote idiom is now compiled to a single push. 2014-08-05 10:34:10 +00:00
ferrieux 5863c1e1b9 More optimized non-BC [string cat] using Tcl_AppendObjToObj() - thx Donal 2014-08-05 09:55:54 +00:00
ferrieux 50f00c62f2 Hum. Really merge trunk. 2014-08-04 14:06:13 +00:00
ferrieux 2918630e90 merge trunk 2014-08-04 14:02:53 +00:00
dgp 00ee522067 merge trunk 2014-08-04 13:37:22 +00:00
dgp 87724ab09f Add tclsh.exe.manifest.in to the distribution 2014-08-04 13:36:57 +00:00
dgp 43aaaf34e5 merge 8.5 2014-08-04 13:35:47 +00:00
dgp 67fcf44a82 Add tclsh.exe.manifest.in to the distribution. 2014-08-04 13:35:06 +00:00
dkf 239374cbb8 Tidy up the docs 2014-08-03 22:43:42 +00:00
ferrieux 25860d9071 Don't use [pid] in tests, stick to constant literals. 2014-08-02 15:26:46 +00:00
ferrieux 1cecac9cad TIP 429 Implementation: [string cat] 2014-08-02 13:04:16 +00:00
dgp 23b2b428b6 merge trunk 2014-08-02 04:38:36 +00:00
dgp 9c45b517dc Another Preserve/Release on channels is needed during IO finalization. 2014-08-02 04:36:39 +00:00
dgp f70b625cf3 merge 8.5 2014-08-02 04:29:41 +00:00
dgp 592bd0b065 Another Preserve/Release on channels is needed during IO finalization. 2014-08-02 04:25:27 +00:00
dgp f4f511dbae merge 8.5 2014-08-02 00:06:21 +00:00
andreask a3cfa0d708 Addition of a cast in tclWinFile.c to match types in a comparison, and
fix of a TRACE string literal in tclExecute.c with a bogus escape. Both
would otherwise bug a Windows debug build (where warnings are errors).
2014-08-01 20:07:40 +00:00
andreask 6563197fa8 Updated package "platform" to version 1.0.13. Separated the
identifiers "macosx*-i386-x86_64" and "macosx-universal" as
incompatible with each other.
2014-08-01 19:50:11 +00:00
dgp 08c2327777 merge-mark 2014-08-01 19:29:20 +00:00
andreask 0b7630c23f Updated package "platform" to version 1.0.13. Separated the
identifiers "macosx*-i386-x86_64" and "macosx-universal" as
incompatible with each other.

Plus addition of a cast in tclIO.c to match types in a comparison
which otherwise bugs a Windows debug build (warnings are errors).
2014-08-01 18:36:50 +00:00
dgp b425d2c241 merge trunk 2014-08-01 17:18:21 +00:00
dgp bd2e4fe97f merge 8.5 2014-08-01 17:17:24 +00:00
dgp bed95cfaf7 Backport the cheaper Preserve/Release on channels. 2014-08-01 17:16:35 +00:00
dgp a745e85067 [e75fabac06] Teardown line information after failed ensemble subcommand
compile attempts.  Copy/paste from CompileCmdCompileProc().  May be
refactor opportunity here.
2014-08-01 16:01:30 +00:00
dgp 232336fbee Correction and commentary in the details of ensemble compiling. 2014-08-01 14:36:30 +00:00
jan.nijtmans c62d8b25aa Fix part of [d19aef1487] (broken --disable-load on MacOSX), broken by [4d417791c9] 2014-07-31 21:23:45 +00:00
dgp 179c36fd48 merge trunk 2014-07-31 20:00:40 +00:00
dgp 5191ece516 [a84a720966] Protect against double free in TclOO classChainCache teardown. 2014-07-31 19:58:53 +00:00
dgp f1e1a92d13 merge trunk 2014-07-31 15:49:44 +00:00
dgp 6c55284908 [3757cdf808] More clock refactoring with spooky impact on [string match]
performance.
2014-07-30 16:41:24 +00:00
dgp fd5a54c8dd Complete transformation off Tcl_Preserve() legacy onto ref counting. 2014-07-30 02:58:27 +00:00
dgp d9ab63098e Reduce the cost of Preserve/Release on channels 2014-07-30 00:22:33 +00:00
dgp 2cbe892d48 [3757cdf808] Refactoring seems to reduce (maybe somewhat kinda sorta) a
bizarre performance regression.  Still not what it was.  Damn Heisenbugs.
2014-07-29 00:22:32 +00:00
dgp cfb0ea03ec Bump to 8.6.2 for release. 2014-07-28 14:50:06 +00:00
dgp 5ec61dacf7 merge 8.5 2014-07-28 12:53:19 +00:00
dgp c6eb718dfd An alternative implementation of [chan copy] that operates in precisely
those circumstances where the incumbent implementation is known to perform
a byte-for-byte copy from input channel to output channel.

In that case, the new implementation ceases the activity of copying every
byte from buffer to buffer to buffer to buffer to effect the copy.  Instead
it arranges for the very same buffer the input channel read driver read into
to be the buffer the output channel write driver writes out from.  No data
copying (or even examining) at all.  When the proper conditions apply, this
ought to be noticeably faster.
2014-07-28 02:06:53 +00:00
dgp a1bd6bc434 merge trunk 2014-07-28 01:53:01 +00:00
dgp 51be2107ea Revise MBRead() to be used in both sync and async modes. 2014-07-28 01:42:42 +00:00
dgp cf106cdda6 Push MBWrite() differences out to callers. 2014-07-27 22:53:01 +00:00
jan.nijtmans e98326383b merge-mark 2014-07-27 22:47:48 +00:00
jan.nijtmans 1db9d005b6 correct EOLFIX macro, broken by [a803608ed5] 2014-07-27 22:44:36 +00:00
dgp 3eb6318d9b Rework MBWrite() so it can be used in both sync and async modes.
Reduce code duplication.
2014-07-27 17:20:32 +00:00
dgp 19d6bd367d Use common MBError() routine for sync and async operations. 2014-07-26 15:44:32 +00:00
dgp 7f4563705c Extend the "move buffer" implementation to cover the async case. 2014-07-26 15:02:09 +00:00
dgp b627af851c merge trunk 2014-07-24 17:19:28 +00:00
dgp ef647d7ccd [9d19af7adb] Make sure all timer events get canceled. 2014-07-24 17:17:41 +00:00
dgp 0a9367fbc9 simplify moveBytes selection logic 2014-07-24 15:34:05 +00:00
dgp 841ecebfa5 Make sure MoveBytes error reporting reproduces what CopyData does. Bugward compatibility! 2014-07-24 15:24:11 +00:00
dgp b3bdbd342b merge trunk 2014-07-24 15:17:55 +00:00
dgp bfe912517c Test format of write error messages during binary [chan copy] 2014-07-24 15:17:19 +00:00
dgp 97d74c549d Make sure MoveBytes records read error messages. 2014-07-24 15:02:09 +00:00
dgp 595290e064 merge trunk 2014-07-24 15:01:16 +00:00
dgp 631849ea86 Test read error during binary [chan copy]. 2014-07-24 15:00:07 +00:00
dgp 213c040089 Extend the buffer move optimization to the "same encodings" case. 2014-07-23 17:10:26 +00:00
dgp 0bc839ec64 Revert the EOLFIX changes of checkin [a803608ed5] (2013-10-28).
They do not work on the one machine where they must -- the release managers!
Appears that the NATIVE_TCLSH support isn't found on the 8.5 branch, so we
shouldn't expect to use it.
2014-07-23 13:10:34 +00:00
dgp 72c15c0c4e Bump to 8.5.16 for release. 2014-07-23 12:26:21 +00:00
dgp df7b610caf merge trunk 2014-07-22 20:27:59 +00:00
dgp 2ad2aba317 Workaround [info frame] troubles with -singleproc 1 testing operations. 2014-07-22 19:57:51 +00:00
dgp 5eaa219754 Avoid [thread::exit]; Using it leads to memleaks. 2014-07-22 18:12:27 +00:00
dgp 2c10c359b5 [12b0997ce7] Plug memleak in iocmd.tf-32.0 . 2014-07-22 17:04:15 +00:00
dgp bfab4c718b [12b0997ce7] Plug memleak in iocmd.tf-32.0 . 2014-07-22 16:44:38 +00:00
dgp d19b7190cb [e6477e1b0f] Plug memleak in AtForkChild() detected in iocmd-11.4. 2014-07-21 14:26:56 +00:00
dgp 97d610fbfe [75b8433707] Revised fix for memleak in oo instance list management. 2014-07-19 16:35:59 +00:00
dkf 4e4b5a7e53 [75b8433707] Plug a subtle memory leak in TclOO.
Test suite very unhappy with this.  Shoving into
a mistake branch until that's sorted.
2014-07-18 22:05:16 +00:00
dkf 6cd3ffa246 [b43f2b49f7] New compilation strategy for lappend that allows multi-value
lappend to not have quadratic performance (through better reference management).
2014-07-18 12:18:44 +00:00
jan.nijtmans d2d54ff3de Finally, use correct octal notation which works in Tcl 9 as well. 2014-07-17 18:43:55 +00:00
jan.nijtmans eaf423b505 merge fork 2014-07-17 17:52:27 +00:00
dgp f345a78f27 Revised fix for memleak in [info frame]. Still pretty ugly, but not more
so than a lot of TIP 280 machinery.
2014-07-17 15:48:59 +00:00
jan.nijtmans 5203cce0e0 Convert TesteventloopCmd and TestchmodCmd to Tcl_Obj-API form. 2014-07-17 15:15:28 +00:00
jan.nijtmans f07fe1c911 Make sure that all "testchmod" arguments start with '0', making it more obvious that the value is octal.
dgp: Isn't the better way to make it obvious the values
are octal to use the explicit octal notation?

For example, [testchmod 0o777 $path] ?

Really seems like a bad idea to me to introduce *more*
incompatibilities for the planned conversion for 
having the value 0777 stop meaning 255 and start
meaning 777 in Tcl 9.

Answer (Jan). You guessed exactly what's my follow-up plan. This was an intermediate step which keeps all test-cases running.
2014-07-17 14:08:30 +00:00
jan.nijtmans 7571df843a Fix [3cdcfa40809ffd2b9d3d71f77dc57da615243730|3cdcfa4080]: tclWinFile.c does not compile with Win VC6 2014-07-17 11:02:03 +00:00
jan.nijtmans f7c255fa17 Convert some non-ASCII characters in testcase comments - which were mangled by my editor in [79ace7b793] - to valid UTF-8: This way my editor will not mangle them again, and fossil will show in the UI which characters are supposed to be there. 2014-07-17 07:39:00 +00:00
dgp 07d1de7a4f [9969cf8ca6] Move the bailout when the ->rewind flag is set down after all
the housekeeping matters tearing down frames (trace data) is complete.
2014-07-17 04:24:23 +00:00
dgp d586b47d44 Backout checkin that broke test io-39.1. 2014-07-16 23:58:54 +00:00
dgp b58f928be5 Repair improper assertion. 2014-07-16 22:01:57 +00:00
dgp 6f05041d3f Assert an equality test, not an assignment 2014-07-16 21:48:18 +00:00
dgp 0d27a4b905 Assert an equality test, not an assignment. 2014-07-16 21:46:30 +00:00
dgp 4870917293 [6a2d339e50] Plug memleak in INST_STR_REPLACE instruction. 2014-07-16 15:59:00 +00:00
jan.nijtmans 1797998aed Modify the "gettimes" test-command to use the Tcl_Obj API.
New "testbytestring" command which can be used to replace the (to-be-deprecated) "bytestring" command from tcltest and/or the "indentity" encoding. 
Adapt many testcases to use the "testbytestring" command.
2014-07-16 10:02:02 +00:00
dgp 0fac79a0fb [726349fab8] Stop leaking compression dictionary on zlib xform channel close. 2014-07-15 15:10:32 +00:00
dgp 8825fb59d7 Suppress valgrind warnings about uninitialized values. 2014-07-11 20:40:24 +00:00
dgp 5af71fcbff [1211aceef2] Fix refcount management of TclpTempFileName() that caused leak. 2014-07-11 18:20:42 +00:00
dgp 431189b805 [9b352768e6] Plug memleak in INST_DICT_FIRST. 2014-07-11 15:44:42 +00:00
dgp 4822b65c03 Stop memleak in [info frame]. 2014-07-11 12:56:16 +00:00
jan.nijtmans b58baa4ff6 Starting with Unicode 6.3, the mongolian vowel separator (U+180e) is no longer a whitespace, but for Tcl it still is.
Update documentation accordingly, and extend test-cases for Unicode 7 compliance.
2014-07-11 10:43:15 +00:00
jan.nijtmans 0a0d095f20 Starting with Unicode 6.3, the mongolian vowel separator (U+180e) is no longer a whitespace, but for Tcl it still is.
"NEL/Next Line" (U+0085) should have been a Unicode whitespace, but never was in Tcl. This is corrected in Tcl 8.6, but for legacy reasons not in Tcl 8.5.
Update documentation accordingly, and extend test-cases for Unicode 7 compliance.
2014-07-11 10:38:55 +00:00
dgp dbed3f8089 [3479689] Plug memory leak due to incomplete bug fix. 2014-07-11 04:49:49 +00:00
dgp d6605e9057 makeFile / removeFile balance. 2014-07-10 18:17:28 +00:00
dgp 0992240c65 makeFile / removeFile balance 2014-07-10 18:11:39 +00:00
dgp 0e96637923 dup test name 2014-07-10 18:02:45 +00:00
dgp 8fd7a48012 dup test name 2014-07-10 18:00:42 +00:00
dgp b406c00842 [f652ae79ed] Close sockets used in tests, so as not to corrupt other
tests in the suite.
2014-07-10 17:21:23 +00:00
dgp 31eb3eebb7 [7368d225a6] Extend the auto-cleanup of zero ref count values passed in to
the Tcl_*SetVar*() family of routines to cover the missing case where the
flags value of TCL_APPEND_VALUE is passed in alone.
*** POTENTIAL INCOMAPTIBILITY***
2014-07-10 16:40:30 +00:00
dgp b81d871afb [7368d225a6] Extend the auto-cleanup of zero ref count values passed in
to the Tcl_*SetVar*() family of routines to cover the missing case where
the flags value of TCL_APPEND_VALUE is passed in alone.
*** POTENTIAL INCOMAPTIBILITY***
2014-07-10 15:45:32 +00:00
dgp cf1f2fb61e Repair buffer indexing error in Tcl_ReadRaw(). 2014-07-10 12:59:24 +00:00
dgp 61f8119019 Repair buffer indexing error in Tcl_ReadRaw() exposed by iogt-6.0 and valgrind. 2014-07-10 12:52:10 +00:00
jan.nijtmans a072994389 Don't use Tcl_GetCommandInfo when Tcl_FindCommand suffices. 2014-07-09 18:49:38 +00:00
dgp da31ff7eb8 First draft of using buffer moves in place of buffer copies to create an
efficient [chan copy].
2014-07-09 14:44:13 +00:00
dgp d5ffff6214 The write and flush operations of reflected transforms ([chan push]) have
been converting all lower level channel errors from Tcl_WriteRaw() into
EINVAL.  Generally this is a perplexing discard of useful information, but
worse it interferes with the EAGAIN signalling that is required to manage
the BLOCKED state of a nonblocking channel.  Thanks to aspect for demo
scripts that pointed to the bug.
2014-07-08 13:45:09 +00:00
jan.nijtmans e1b54e0e11 Update Unicode tables to Unicode 7.0 2014-07-04 12:49:40 +00:00
jan.nijtmans 53df9e36da Update Unicode tables to Unicode 7.0 2014-07-04 12:47:21 +00:00
dgp 8d68951021 Clarify http::config and http::geturl -headers roles in setting request headers. 2014-07-02 20:22:43 +00:00
dgp 4b4b642fe6 [c31ca233ca] Fix TclGetsObjBinary() so that each [gets] rediscovers whether
a nonblocking channel is blocked.
2014-07-02 16:30:41 +00:00
dgp 0cf246c174 [c31ca233ca] Fix TclGetsObjBinary() so that each [gets] rediscovers whether
a nonblocking channel is blocked.
2014-07-02 16:20:30 +00:00
dgp ee896008d0 Fix mismatch of Tcl_Preserve() / Tcl_Release(). 2014-06-26 16:01:05 +00:00
dgp 6bc046c0bc Fix mismatch of Tcl_Preserve() / Tcl_Release(). 2014-06-26 15:59:27 +00:00
dgp 58f92b6316 Simplify / refactor Tcl_ReadRaw(). No need for CopyBuffer(). 2014-06-24 16:46:12 +00:00
dgp ddeb3ab35c Simplify / refactor Tcl_ReadRaw(). No need for CopyBuffer(). 2014-06-24 16:34:05 +00:00
jan.nijtmans 0d9a8edf22 Fix execute-6.5 test failure on trunk: the "preserveCore" part of tcltest::test assumes that the cleanup is done first, so moving the cleanup means the the "preserverCore" part needs to move with it. 2014-06-23 12:49:41 +00:00
jan.nijtmans 6ab9c80ea1 Fix execute-6.5 test failure on trunk: the "preserveCore" part of tcltest::test assumes that the cleanup is done first, so moving the cleanup means the the "preserverCore" part needs to move with it. 2014-06-23 12:48:16 +00:00
jan.nijtmans aa6f0b1cab ticket [2f9df4c4fa]: tcltest - request to move -cleanup script execution until after -output compare.
tcltest -> version 2.3.8
2014-06-22 16:17:12 +00:00
jan.nijtmans c7510fa5b9 ticket [2f9df4c4fa]: tcltest - request to move -cleanup script execution until after -output compare
tcltest -> version 2.3.8
2014-06-22 16:15:43 +00:00
jan.nijtmans efcc225259 previous commit was not quite right, this one should be better 2014-06-20 20:50:48 +00:00
jan.nijtmans 24b0f264c3 ticket [2f9df4c4fa]: tcltest - request to move -cleanup script execution until after -output compare 2014-06-20 20:21:50 +00:00
aku 3cd11c535e [b47b176adf] Stop possible segfaults when variability in mutex lock
schedules cause a ForwardingResult to remain on the forwardList after
it has been processed (IORChan is the origin of the code in IORTrans).
2014-06-20 05:14:43 +00:00
aku f326f97897 [b47b176adf] Stop possible segfaults when variability in mutex lock
schedules cause a ForwardingResult to remain on the forwardList after
it has been processed (IORChan is the origin of the code in IORTrans).
2014-06-20 05:05:21 +00:00
dgp 7834f2fe96 [b47b176adf] Stop segfault when variability in mutex lock schedules cause
a ForwardingResult to remain on the forwardList after it has been
processed.
2014-06-19 16:38:33 +00:00
dkf 7bde946742 [f0f876c141] Improve consistency in error messages. 2014-06-17 14:30:06 +00:00
dgp fce6982a3e [1758a0b603] socket_*-2.13 : Workaround the broken select() in some Linux
kernels that fails to report a writable state on a socket when an error
condition (or remote close) is present.
2014-06-16 13:38:26 +00:00
dgp 52af4f6df3 [1758a0b603] socket-2.13 : Workaround the broken select() in some Linux
kernels that fails to report a writable state on a socket when an error
condition (or remote close) is present.
2014-06-16 12:44:13 +00:00
dgp 908fc261b6 merge socket test from 8.5 2014-06-16 12:19:30 +00:00
dgp eab2f47c2c merge 8.5 2014-06-16 12:09:32 +00:00
dkf ab6933ef6b [311e61d12a] Generate error code in *all* places where commands are looked up. 2014-06-16 09:24:39 +00:00
dkf c20374dfa6 [cb042d294e] Improve consistency of [dict] wrong-args error messages. 2014-06-15 16:50:32 +00:00
dkf 5f82234293 [1b0266d8bb] Make [dict replace] and [dict remove] have canonicalization semantics close to [lrange] and [lreplace]. [dict merge] is also improved, but is not as strict. 2014-06-15 16:14:18 +00:00
dkf 17751a998c Some more cleaning up 2014-06-15 16:11:56 +00:00
dkf 08d9096362 Make [dict replace] and [dict remove] guarantee result canonicality. 2014-06-15 07:52:57 +00:00
dgp 2621d5a21a Draft test for [1758a0b603]. 2014-06-13 21:15:13 +00:00
dgp 4e3fe86fc2 Additional check for an error condition on the socket. 2014-06-12 13:36:18 +00:00
dgp 86b84b6d21 Workaround the broken select() in some Linux kernels that fails to report
a writable state on a socket when an error condition (or remote close) is
present.  Would be good to add actual test suite tests for this, but until
then see demo scripts in the ticket 1758a0b603.
2014-06-11 17:24:58 +00:00
dkf 6a99b9a546 Improved the error messages.
We do not want parsing an invalid dictionary to give errors about lists!
As compensation, we get greater precision in the errorcode.
2014-06-07 14:18:40 +00:00
dkf e5104aa3dc merge trunk 2014-06-06 08:47:28 +00:00
dkf fae85d1af5 merge trunk 2014-06-06 08:46:58 +00:00
dgp bb40f1cd2c Tests socket*-2.12 test for DiscardOutput() updates. 2014-06-05 19:13:09 +00:00
dgp bb4c894bca Test socket-2.12 covers the DiscardOutput() update. 2014-06-05 19:06:08 +00:00
dgp b4cc0cbac8 When too many chars are read by ReadChars() and we trim the limits to get it right on the next pass, don't forget the TCL_UTF_MAX padding demanded by Tcl_ExternalToUtf(). (Thanks for finding that, aku!) Fix the factorPtr management. It was just totaly wrong. The factor should be a ratio of the record of bytes read to the record of chars read. With those fixes, new test io-12.6 covers the "too many chars" code. 2014-06-05 15:20:59 +00:00
dgp 16b3c54eb0 merge fork 2014-06-05 15:20:03 +00:00
dgp 3eb959fc93 When too many chars are read by ReadChars() and we trim the limits to
get it right on the next pass, don't forget the TCL_UTF_MAX padding
demanded by Tcl_ExternalToUtf().  (Thanks for finding that, aku!)
Fix the factorPtr management.  It was just totaly wrong. The factor should
be a ratio of the record of bytes read to the record of chars read.
With those fixes, new test io-12.6 covers the "too many chars" code.
2014-06-05 15:17:29 +00:00
andreask ba7b49d9c4 Fixed a tricky interaction of IO system and encodings which could
result in a panic.

The relevant function is ReadChars() (short RC in the following).

When the encoding and translation transforms deliver more characters
than were requested the iterative algorithm used by RC reduces the
value of "dstLimit" (= the number of bytes allowed to be copied into
the destination buffer) to force the next round to deliver less
characters, hopefully the number requested.

The existing code used the byte located just after the last wanted
character to determine the new limit. The resulting value could
_undershoot_ the best possible limit because Tcl_ExternalToUtf would
effectively reduce this limit further, by TCL_UTF_MAX+1, to have
enough space for a single multi-byte character in the buffer, and a
closing '\0' as well.

One effect of this were additional calls to ReadChars() to retrieve
the characters missed by a call with an undershot limit.

In the limit (sic) however this was also able to cause a full-blown
"Buffer Underflow" panic if the original request was for less than
TCL_UTF_MAX characters (*), and we are using a single-byte encoding
like iso-8859-1. Because then the undershot dstLimit would prevent the
next round from copying anything, and causing it to try and
consolidate the current buffer with the next buffer, thinking that it
had to merge a multi-byte character split across buffer boundaries.

(Ad *) For example because the previous call had undershot already and
left only such a small amount of characters behind!

The basic fix to the problem is to add TCL_UTF_MAX back to the limit,
like is done in all the (three) other places in RC setting a new
one. Note however that this naive fix may generate a new limit which
is the same as the old, or possibly larger. If that happens we act
very conservatively and reduce the limit by only one byte instead.

While I believe that this last conservative approach will never reduce
the limit to TCL_UTF_MAX or less before reaching a state where it
returnds the exact amount of requested characters I still added a
check against this situation anyway, causing a new panic if triggered.
2014-06-05 00:22:59 +00:00
andy 45fd54872f Add missing calls to Tcl_DecrRefCount() in string object man page examples. 2014-06-04 21:45:29 +00:00
dgp cb1e14e0eb Revise DiscardOutput() to account for revisions to the loop in FlushChannel() which is its only caller. We need to discard the curOutPtr buffer as well, and not count on another pass through the loop to attempt to flush it (and raise the same failure again?). 2014-06-04 16:42:21 +00:00
dgp 3189f48d19 Revise DiscardOutput() to account for revisions to the loop in FlushChannel()
which is its only caller.  We need to discard the curOutPtr buffer as well,
and not count on another pass through the loop to attempt to flush it
(and raise the same failure again?).
2014-06-04 16:36:25 +00:00
dkf 6a91e192f8 more tests, cleaning up the code a bit 2014-06-04 08:15:26 +00:00
dgp 3334cf2103 Valgrind doesn't like use of uninitialized variables. 2014-06-04 03:25:44 +00:00
dgp 518ffe037f merge fork of 8.5 branch 2014-06-03 19:57:31 +00:00
dgp 2691f4b9a9 [734138ded8] Revisions so that unreported errors don't get lost during
the close of a channel.
2014-06-03 17:47:23 +00:00
dgp 93b55b0dc4 Backport I/O core fixes made known by async socket work on trunk. 2014-06-03 17:32:33 +00:00
dkf 1e37d8beb0 merge trunk 2014-06-03 08:13:58 +00:00
dkf 10caa9b482 [1b0266d8bb] Working towards ensuring that all dict operations are sufficiently strict. 2014-06-03 07:26:11 +00:00
dgp 6c7e545b80 These edits make all tests outside of socket-14.* pass on OSX Mavericks.
Several socket-14.* tests failing there, and those that pass are very slow
about it.  Firewall or poor networking configuration may be playing a role.
2014-06-03 02:26:07 +00:00
dgp 004361c91d These edits make the tests socket-14.11.[01] stop hanging, but also introduce
a whole raft of test failures.  WIP.
2014-06-02 20:03:14 +00:00
max 744e7bfe51 Improve robustness of the socket tests against systems that support IPv6, but don't resolve localhost to ::1 (and vice versa for IPv4 and 127.0.0.1). 2014-06-02 10:57:38 +00:00
dgp 9b701fdae7 Correct the interest masks in the Tcl_CreateFileHandler() calls in PipeWatchProc(). When we are interested in both readable and writable events of a command pipeline channel, we only want the readable from the read end of the pipe, and the writable from the write end of the pipe. 2014-05-31 02:40:00 +00:00
dgp 1f197f004a Correct the interest masks in the Tcl_CreateFileHandler() calls in
PipeWatchProc().  When we are interested in both readable and writable
events of a command pipeline channel, we only want the readable from
the read end of the pipe, and the writable from the write end of the pipe.
2014-05-31 02:30:53 +00:00
oehhar 312e71eff4 win socket -async: do not loose connect notification by temporarily stop connect monitoring. Bug [336441ed59] 2014-05-30 10:36:01 +00:00
dgp 3dcb02dc07 Refinements of FlushChannel() and its callers. Notably includes removal of the flag BUFFER_READY. 2014-05-29 15:04:52 +00:00
oehhar 78bb5378e9 Try not to loose FD_CONNECT by switching monitoring off. 2014-05-29 14:56:10 +00:00
oehhar bf498960d9 merge core-8-5-branch 2014-05-29 14:53:45 +00:00
andreask 329c85106b Merged the workarounds and fixes for wrapped executables on various
platforms into the trunk. For details see the merged revision and its
ancestor.
2014-05-28 19:21:35 +00:00
dgp 334ffdfa50 Refinements of FlushChannel() and its callers. Notably includes removal
of the flag BUFFER_READY.
2014-05-28 18:58:51 +00:00
dgp 4b98569f89 Update comment to explain assumptions. 2014-05-28 18:49:02 +00:00
dgp 0fe50b37a2 Further simplifications to FlushChannel(). This makes clear the
BUFFER_READY flag serves no necessary purpose, so it is removed.
2014-05-28 18:24:56 +00:00
dgp c08a9df4d6 Expand the IsBufferFull() macro to check non-NULL bufPtr.. 2014-05-28 17:14:11 +00:00
dgp a60da763ba Increase size of test io-29.34 so that it more portably tests the case where
the OS networking machinery gets backed up and blocks.
Added several TODO comments on potential simplifications.
2014-05-28 16:54:02 +00:00
dgp 88ab76b3b8 Move code that can only matter in the first loop iteration out of the loop. 2014-05-27 13:28:41 +00:00
dgp 5f8f27387d Comment out lines of test io-53.4 that appear to do nothing of any value. 2014-05-24 19:56:37 +00:00
andreask ceae73bd28 Followup on [72c54e1659]. Removed unused variable. 2014-05-23 17:17:35 +00:00
jan.nijtmans a74fb9ea31 eliminate two unused variables. 2014-05-23 14:59:03 +00:00
andreask cc63d97f54 Workarounds and fixes for wrapped executables on various platforms
regarding the handling of wrapped dynamic libraries.

The basic flow of operation is to copy such libraries into a temp
file, hand them to the OS loader for processing, and then to delete
them immediately, to prevent them from being accessible to other
executables. On platforms where that is not possible the library is
left in place and things are arranged to delete it on regular process
exit.

An example of the latter are older revisions of HPUX which report that
the file is busy when trying to delete it. Younger revisions of HPUX
have changed to allow the deletion, but are also buggy, the OS loader
mangles its data structures so that a second library loaded in this
manner fails.

More recently it was found that Linux which is usually ok with
deleting the file and gets everything right shows the same trouble as
modern HPUX when the "docker" containerization system is involved, or
more specifically the AUFS in use there. Deleting the loaded library
file mangles data structures and breaks loading of the following
libraries. For a demonstration which does not involve Tcl at all see
the ticket

     https://github.com/dotcloud/docker/issues/1911

in the docker tracker.

This of course breaks the use of wrapped executables within docker
containers.

This commit introduces the function TclSkipUnlink() which centralizes
the handling of such exceptions to unlinking the library after unload,
and provides code handling the known cases. IOW HPUX is generally
forced to not unlink, and ditto when we detect that the copied library
file resides within an AUFS.

The latter must however be explicitly activated by setting the define
-DTCL_TEMPLOAD_NO_UNLINK during build. We still need proper configure
tests to set it on the relevant platforms (i.e. Linux).

The AUFS detection and handling can be overridden by the environment
variable TCL_TEMPLOAD_NO_UNLINK which can force the behaviour either
way (skip or not). In case the user knows best, or wishes to test if
the problem with AUFS has been fixed.
2014-05-22 17:17:12 +00:00
andy 461b9f3322 Ditto [dict append], [dict incr], and [dict lappend]. Update description of [dict create] to explicitly state that it returns the new dictionary. 2014-05-21 22:00:52 +00:00
andy 47089ed2b3 Ditto [dict unset]. 2014-05-21 21:40:09 +00:00
andy ff04f434c4 Update dict man page to state that [dict set] returns the updated dictionary value. 2014-05-21 21:32:44 +00:00
jan.nijtmans e55620ed06 Fix gcc warning (signed-unsigned compare) 2014-05-21 14:37:57 +00:00
max 052f13167e Fix c&p errors in test descriptions 2014-05-21 10:37:10 +00:00
dgp 6fb8bfc715 Rework the management of the CHANNEL_BLOCKED and CHANNEL_EOF flags, in particular not allowing them to leak between multiple layers of a stacked channel. Much common code refactored into ChanRead(). 2014-05-20 15:17:11 +00:00
dgp f19d7ab302 Rework the management of the CHANNEL_BLOCKED and CHANNEL_EOF flags, in
particular not allowing them to leak between multiple layers of a stacked
channel.  Much common code refactored into ChanRead().
2014-05-20 15:00:50 +00:00
oehhar 3eb4868d33 Fix and improve socket -async [13d3af3ad5] 2014-05-20 14:46:37 +00:00
dgp 090475cc9c Same improvements to the zlib transform operations. 2014-05-19 18:29:26 +00:00
dgp 7f2205461c Simplify ReflectInput(). Also stop intruding on channel internals with
direct clearing of CHANNEL_EOF flag.
2014-05-19 18:08:05 +00:00
jan.nijtmans b1576079b7 [47d66253c9]: "lsearch -sorted -integer" on 64bit system
***POTENTIAL INCOMPATIBILITY***
Changes results of both [lsearch -integer] and [lsort -integer].
2014-05-17 07:01:22 +00:00
dgp 125a9f8a25 Simplify the inputProc of [testchannel transform]. 2014-05-17 03:38:28 +00:00
dgp 5b5dffa386 Simplify the inputProc of [testchannel transform]. 2014-05-17 03:32:27 +00:00
dgp 48b8a3755c Revise results of tests iogt-2.[123] to account for EOF flags no
longer leaking across channel stacks.
2014-05-17 03:05:36 +00:00
dgp 94d4975fa2 Repair broken tests iogt-2.[123].
What happened is that now that EOF flags no loger leak acros channel
stack layers, an EOF in the bottom channel isn't detected in the top one
until the ChanRead call at the top level actually returns 0 bytes.  This
causes one more query/ma
2014-05-17 02:53:34 +00:00
dgp 604007076c Merge flag changes. - Wow, no trouble with [chan push] demonstrated. 2014-05-16 23:17:15 +00:00
ferrieux 3afefe3d81 Let the generated Makefile be emacs-friendly by avoiding spurious empty lines and misplaced tabs. Useful e.g. to just set CFLAGS to debug and save. 2014-05-16 21:33:41 +00:00
dgp 5db8831fb0 Improved use of EOF state to avoid worthless allocations. 2014-05-16 19:11:49 +00:00
dgp 28721acb58 Move the resets and testings of the BLOCKED flag to where they make more sense. 2014-05-16 18:45:37 +00:00
dgp 6a8b9ef2d6 merge trunk 2014-05-16 15:23:26 +00:00
dgp 4715d60689 merge 8.5 2014-05-16 15:10:37 +00:00
dgp 539adc9f7f merge 8.5 2014-05-16 15:05:08 +00:00
dgp 5e1812e37c Fix for failing tests *io-32.11* 2014-05-16 14:59:45 +00:00
dgp 158ab27221 merge 8.5 2014-05-16 14:47:59 +00:00
dgp edb5d20cbf Merge completion of dgp-read-bytes branch. 2014-05-16 14:47:15 +00:00
dgp 47912a0cab Bug fix - accept consumption of the trailing newline in crlf with no
characters produced.  Also delete false assertions.
2014-05-16 14:40:39 +00:00
dgp d32b2d8171 More tests to demo the bug more directly. 2014-05-16 12:56:01 +00:00
dgp 61f362f9a4 Branch to demo bug introduced in the parent commit. 2014-05-15 18:38:22 +00:00
dgp b4ca74a562 Portable test to demo bug otherwise seen only on Windows. 2014-05-15 16:48:43 +00:00
jan.nijtmans 8eb9237e4a Minor bug-fix in [3118489] implementation: NUL in filenames. Filenames starting with <drive>: but without a following slash should be considered volume-relative i.e. the ':' is valid here. 2014-05-15 14:59:03 +00:00
jan.nijtmans c6cd29b3f9 Fix [3118489]: NUL in filenames. (On Windows, protect against invalid use of ':' in filenames as well) 2014-05-15 14:54:45 +00:00
dgp 3bb92ad005 Push the setting and clearing of CHANNEL_BLOCKED flag to the more inner
parts of the channel read machinery.
2014-05-15 11:04:35 +00:00
dgp eccb17258f merge trunk 2014-05-14 15:09:15 +00:00
dgp f57343eb42 merge 8.5 2014-05-14 14:52:42 +00:00
jan.nijtmans e55ee4d6cc Fix 3 test-cases which started failing on Windows 2014-05-14 09:19:26 +00:00
jan.nijtmans 2e71d669fe Fix 3 test-cases which started failing on Windows 2014-05-14 09:11:42 +00:00
dgp 07f07faf4b Refactored much management of the BLOCKED and EOF flags into ChanRead() then
began repairing some of the logic about them. Tests iogt-2.* now fail because
they've been crafted as experiments recording the fine detail of reflected
channel driver calls, and fixing the management of channel flags is changing
that. zlib-8.5 also needed adjustment to reflect that an EOF set must come
with an empty string read when flags are functioning properly.
2014-05-13 18:49:20 +00:00
dgp 63543e9ad0 Rework Tcl_ReadRaw() mostly taking things out of the loop that never repeat. 2014-05-13 18:24:23 +00:00
dgp 73ccc4ba86 Salvaged what was left of value in the dgp-read-bytes-detour branch.
Refactored much management of the BLOCKED and EOF flags into ChanRead()
then began repairing some of the logic about them.
Tests iogt-2.* now fail because they've been crafted as experiments recording
the fine detail of reflected channel driver calls, and fixing the management
of channel flags is changing that.
2014-05-13 16:42:07 +00:00
jan.nijtmans 9265507b2c [958bc05fbe]: Clarify "clock format" using "%R" 2014-05-13 11:25:26 +00:00
jan.nijtmans 7974460313 [958bc05fbe]: Clarify "clock format" using "%R" 2014-05-13 11:23:40 +00:00
dgp 5fedb4d01b Restore the largefileSupport constraint on Darwin, where tests (chan)io-34.21
take an unbearable 90 seconds each to complete.
2014-05-12 21:52:39 +00:00
dgp 29055898b0 Restore the largefileSupport constraint on Darwin, where tests (chan)io-34.21
take an unbearable 90 seconds each to complete.
2014-05-12 21:50:55 +00:00
dgp 7156085860 Have the [chan push] machinery ReadRaw() directly into the argument to be
passed to the read method of the channel transformation command.  Save a copy.
2014-05-12 17:19:16 +00:00
jan.nijtmans 5d76c6e6c0 Possible fix for [47d66253c92197d30bff280b02e0a9e62f07cee2|47d66253c9]: "lsearch -sorted -integer" on 64bit system 2014-05-12 13:09:00 +00:00
dkf a4eef46453 [6d2f249a01] Handle a failure to comprehend half-way through the compilation of a chain of compileable ensembles. 2014-05-11 10:39:14 +00:00
dgp 73f53667ed Repair another "impossible" test and the segfault it reveals. 2014-05-09 17:46:45 +00:00
dgp fbb32b908c Correct namespace bugs in normally skipped tests. Constrain them as "knownBug" rather than "unknownFailure". 2014-05-09 17:35:12 +00:00
dgp 1b7b5e839c Correct namespace bugs in normally skipped tests.
Constrain them as "knownBug" rather than "unknownFailure".
2014-05-09 16:55:34 +00:00
dgp 643d4e096b Added comment explaining the "knownBug" in iogt-6.1 2014-05-09 16:39:08 +00:00
dgp 8b4cb6f5d9 Added comment explaining the "knownBug" in iogt-6.1 2014-05-09 16:38:23 +00:00
dgp 54a7fb1431 Tests (chan)io-34.21 are constrained for largefileSupport, and that's disabled by default, which means never tested, which means the ridiculous bugs in them are never found and fixed.
Fixed the bugs, changed the default. Large File Suppport (4GB) is commonplace now. Let those without it suffer a few failing tests reporting that fact to them.
2014-05-09 16:33:58 +00:00
dgp d7461d07ad Tests (chan)io-34.21 are constrained for largefileSupport, and that's
disabled by default, which means never tested, which means the ridiculous
bugs in them are never found and fixed.

Fixed the bugs, changed the default.  Large File Suppport (4GB) is
commonplace now.  Let those without it suffer a few failing tests reporting
that fact to them.
2014-05-09 16:31:06 +00:00
dgp f4401162e8 Test iocmd-32.1 is not "impossible" but after writing it properly it does segfault trying to use a deleted interp. Fixed. 2014-05-09 13:33:27 +00:00
dgp a84b51c1b4 Test iocmd-32.1 is not "impossible" but after writing it properly it
does segfault trying to use a deleted interp.  Fixed.
2014-05-09 13:19:30 +00:00
jan.nijtmans e538095963 Fix [3389978]: Support for paths longer than MAX_PATH on Windows. 2014-05-09 12:03:58 +00:00
jan.nijtmans 99a5afc6e0 Make Cygwin's "configure" work from another directory than /unix. (Not everything works this way!) 2014-05-09 10:10:20 +00:00
jan.nijtmans 61c463f55f Make Cygwin's "configure" work from another directory than /unix. (Not everything works this way!) 2014-05-09 10:08:56 +00:00
dgp 2ff193dc57 Merge the reforms of dgp-trunk-read branch into trunk. (port of dgp-read-bytes)
Large overhaul of I/O read operations
	- Protects integer overflow of buffers, reusing append machinery
	- Forces -buffersize changes to take place when commanded
	- Uses assertions to simplify code in "can't happen" situations
	- Eliminated duplication of -translation processing
		- Fixes bugs io-35.18b and io-35.20
2014-05-08 17:38:09 +00:00
dgp 7d850a310d Merge the reforms of dgp-read-bytes branch into 8.5+ releases.
Large overhaul of I/O read operations
	- Protects integer overflow of buffers, reusing append machinery
	- Forces -buffersize changes to take place when commanded
	- Uses assertions to simplify code in "can't happen" situations
	- Eliminated duplication of -translation processing
		- Fixes bugs io-35.18b and io-35.20
2014-05-08 17:30:32 +00:00
dgp 95eec569fd merge trunk 2014-05-08 16:21:45 +00:00
dgp fa53de3d90 silence compiler warning 2014-05-08 16:21:12 +00:00
dgp f1ace09e64 merge trunk 2014-05-08 16:12:35 +00:00
dgp f54edc88cf Fix the panic in iogt-2.5.
Back in 2011, Bugs 3384654 and 3393276 first noticed troubles with
ChannelBuffer sharing, but the magnitude of the problem wasn't truly
grasped.  A fix was applied that turned out to be more of a band-aid
workaround.  Now that the real fix is in place, the band-aid is actually
preventing it working properly in thie case.  Rip it off!
2014-05-08 16:03:50 +00:00
dgp 04fbce15ca Revert the iogt-2.5 fix. For now one panic is better than widespread
memory leaks.
2014-05-08 13:01:47 +00:00
jan.nijtmans e083b8e9bb More efficient/robust implementation of function TclNativeCreateNativeRep().
- No more intermediate results in a Tcl_DString, just allocate space directly. 
- Let MultiByteToWideChar() do all the difficult work, inclusive checking for invalid byte sequences.
- Handled extended win32 paths, inclusive UNC paths.
Implementation for a great deal taken over from fossil.
2014-05-08 12:46:47 +00:00
dgp 65baa666b5 merge trunk 2014-05-08 03:28:56 +00:00
dgp 22c5cd91eb Merge 8.5. 2014-05-08 03:13:01 +00:00
dgp 48ecb1a2ee Merge 8.5. 2014-05-08 02:55:47 +00:00
dgp 75e37a235a Stop leak in iocmd-21.22. 2014-05-08 02:38:52 +00:00
dkf e29e8eee24 Corrected description of where tcl_platform(user) comes from on Unix. 2014-05-07 22:22:02 +00:00
dkf 84a26717ef Corrected description of where tcl_platform(user) comes from on Unix. 2014-05-07 22:19:30 +00:00
dgp 643b20e2b2 Stop leaks of cloned Tcl_ChannelTypes. 2014-05-07 03:30:55 +00:00
dgp 68f4187dd1 Stop leak in io-53.5. 2014-05-07 02:28:56 +00:00
dgp 01ccb9ccaa Stop leak in io-33.7. 2014-05-06 23:51:32 +00:00
dgp 3fd76e6ba7 Stop memory leak in io-29.34 2014-05-06 23:23:43 +00:00
dgp 7218e5967c Stop memory leak in io-29.27. 2014-05-06 22:34:45 +00:00
dgp cc1b3e8ddc Symptom relief. Make test stop panicking.
This is not the proper final answer.  ChannelBuffer management in
FlushChannel is simply not robustly correct yet.
2014-05-06 17:33:55 +00:00
dgp c4669a8b0c Add Panic call to better identify where iogt-2.5 goes wrong. 2014-05-06 15:23:43 +00:00
dgp a0d540327f Merge 8.5. New test iogt-2.5 panics. 2014-05-06 14:43:19 +00:00
dgp 2d6278c829 merge 8.5 2014-05-06 14:10:57 +00:00
dgp ba89a15d53 Have to manage the lifetime of the self handle in testchannel transform. 2014-05-06 13:56:29 +00:00
jan.nijtmans d8b36a0216 Start working on [3389978]. Appears to work, but some clean-up needed. 2014-05-06 11:17:28 +00:00
dgp b8c001575a Segfaulting test (backport of iortrans-5.11). 2014-05-05 17:18:51 +00:00
dgp 681e50da88 Merge GotFlag() backport from 8.5. Conflicts galore! 2014-05-05 13:23:20 +00:00
jan.nijtmans b04c31eecb merge-mark 2014-05-05 09:18:42 +00:00
jan.nijtmans acdf0e593a Backport "GotFlag" macro from Tcl 8.6. Makes code more readable. No change in functionality. 2014-05-05 09:17:46 +00:00
dgp 3c51a58c1e merge trunk 2014-05-02 15:58:03 +00:00
dgp acce1f902b merge 8.5 2014-05-02 15:41:45 +00:00
jan.nijtmans 9888275261 Re-apply [3010352], bringing back the symbol exports of shared libraries as it was in 8.6.0/8.6.1. 2014-05-02 15:35:14 +00:00
dgp 01f9f84db5 Bring back self restacking support. Channel tests all passing now. 2014-05-02 15:29:41 +00:00
dgp 9bed70dea4 Fixup restacking tests to expect the right results. 2014-05-02 15:19:57 +00:00
dgp 3ab2f65ec6 Backport channel self restacking support. (Test iogt-2.4). 2014-05-02 15:06:57 +00:00
dgp 322ea4d71d Add some comments about possible other self-restacking troubles. 2014-05-02 14:45:03 +00:00
dgp fd83709b45 Fully restore topChan resetting to accommodate self-restacking channels. 2014-05-02 13:02:48 +00:00
dgp c09e2ded08 Re-enable buffer recycling. 2014-05-02 12:39:14 +00:00
dgp 8e5e88f4db Stop the segfault in iogt-2.4. First by changing the UpdateInterest()
call that triggers it.  "downChanPtr" may no longer be the right argument
at that point.  Second, after ending the segfault, the test became an 
infinite loop (nested unstacking?!  whoa.), so revised the test to one
that terminates (and passes).  Left behind a comment that the recursive
unstacking case may require more examination.
2014-05-01 16:33:39 +00:00
dgp d3c1978e07 merge trunk 2014-05-01 15:13:46 +00:00
dgp fb36ca1b18 merge trunk 2014-05-01 15:00:40 +00:00
dgp 27ce96cd71 merge 8.5 2014-05-01 14:52:13 +00:00
dgp abd9269a04 We must Preserve channels if we're going to use TclChanCaughtErrorBypass() to get error information after channel routines are called (and have possibly called for the channel to go away). 2014-05-01 14:36:34 +00:00
dgp aacc275d30 We must Preserve channels if we're going to use TclChanCaughtErrorBypass()
to get error information after channel routines are called (and have possibly
called for the channel to go away).
2014-05-01 14:18:35 +00:00
dkf 0b7940e00e make doubly sure that things which should be unshared stay unshared 2014-05-01 09:11:09 +00:00
jan.nijtmans 183a28c109 merge-mark 2014-05-01 07:44:34 +00:00
jan.nijtmans c4f8c1063c Fix more corner-cases like [0e92c404f19ede5b2eb06e6db27647d3138cc56|0e92c404f1]: The only place where a type of &tclByteArrayType can be trusted is when determining its length, because the character length of a (UTF-8) string is always equal to the byte length of the byte array. 2014-05-01 07:38:27 +00:00
dgp 438b6b5009 Merge in the fixes for improper ChannelBuffer sharing via recycling. 2014-05-01 01:26:04 +00:00
dgp a95f198d2e missing constraint 2014-05-01 01:15:42 +00:00
jan.nijtmans 87d82b22e7 Better (safer) fix for [0e92c404f1] 2014-04-30 21:59:00 +00:00
dkf e0c1d41f5e [82e7f67325] Fix an evil refcount problem in compiled [string replace]. 2014-04-30 21:24:39 +00:00
dgp 1a41595e06 Stop the segfaults in [close] during [gets] tests.
Not sure this is the right behavior, but it's better than crashing.
2014-04-30 19:54:51 +00:00
dgp 2d4cef6d56 Panic message to pinpoint the cause of iocmd-21.23 segfault. 2014-04-30 19:33:21 +00:00
dgp f8ff5f9f13 Another segfault demo test, this one with [close] during [gets]. 2014-04-30 19:12:37 +00:00
dgp 210aa9605a Make sure no shared ChannelBuffers get recycled. 2014-04-29 17:40:15 +00:00
dgp 19292d74bf merge trunk 2014-04-29 17:04:33 +00:00
dgp ab5b2feda0 Fix bug exposed when buffer recycling is disabled. 2014-04-29 16:47:48 +00:00
dgp 35a41cd0d6 Fix bug exposed when buffer recycling is disabled. 2014-04-29 16:36:39 +00:00
dgp 9873314d0d Revise the logic for setting TCL_ENCODING_END in the outputEncodingFlags
so it does not rely on buffer recycling.
2014-04-29 15:54:03 +00:00
ferrieux f3f494358f Clarify fcopy manpage regarding its bidirectional uses. [1350564] 2014-04-28 20:28:10 +00:00
dgp 0c9e9be9e5 Disable buffer recycling to expose bugs for fixing. 2014-04-25 20:12:48 +00:00
dgp e024894c53 Disable buffer recycling, which creates mysteries. 2014-04-25 19:51:36 +00:00
dgp e3220aa631 Test iortrans-4.8.2 demos an infinite loop. Possible trouble with
pushback buffers.
2014-04-25 17:34:11 +00:00
dgp 47d1451282 merge trunk 2014-04-24 18:21:49 +00:00
dgp 5f636c9b81 merge 8.5 2014-04-24 18:14:36 +00:00
dgp 45659eebd2 Make sure the ReflectedChannel struct is freed in the handler thread,
where it was allocated.  This constraint allows the struct to safely
hold Tcl_Obj values, which has been convenient for storing callback commands.
2014-04-24 15:27:58 +00:00
dgp 3ec273770b [3493120] Plug memory leak in thread exit. 2014-04-24 04:34:01 +00:00
dgp c69e73e183 [3493120] Plug memory leak in thread exit. 2014-04-23 18:25:27 +00:00
sebres fa12c3782d *nix segfault cleared: we should reset a thread key after freeing of alloc cache (in tclUnixThrd.c) 2014-04-23 09:18:20 +00:00
dgp af15fe284a Merge the [testchannel transform] fixes. 2014-04-22 15:09:06 +00:00
dgp d7f092d1cf Add refcounting and preservation to [testchannel transform] to stop segfault
in test iogt-2.4.
2014-04-22 14:57:44 +00:00
sebres fea67060de Memory leak after thread exit, fixed (alloc cache released by exit), belong to ticket [3493120]
Moved over to branch bug-3493120.  This is not ready
for the core-8-5-branch.  Segfaults all over the place
in a thread-enabled build on a CentOS system.
2014-04-22 13:25:41 +00:00
dgp ea20dfbaae merge trunk 2014-04-21 20:02:39 +00:00
dgp da22d54b77 merge 8.5 2014-04-21 20:01:49 +00:00
dgp e4bf3a0afd Merge refcounting machinery for ChannelBuffer. 2014-04-21 19:04:08 +00:00
dgp 473f2fb8dd Added a refcounting mechanism to ChannelBuffers. Other edits to
stop segfaults in tests iocmd-21.2[12].
2014-04-21 18:55:41 +00:00
dgp 29d26aa2c1 Another test exposing another segfault. 2014-04-17 19:58:41 +00:00
dgp fecf0d5e64 merge 8.5 2014-04-17 19:17:33 +00:00
dgp b70fbe851c merge trunk 2014-04-17 19:11:47 +00:00
dgp 747725c1fc Merge reflected channel improvements. 2014-04-17 18:10:02 +00:00
dgp f60122dc91 Reflected channels. Keep a set of method names cached so we don't create
new each operation, and we can benefit from any lookup info cached in intreps.
2014-04-17 17:55:59 +00:00
dgp dfb3ea8358 Simplify reflected channels.
Instead of having two modes of Close operations and the need to choose
between them with a special value of the methods field, when the initialize
pass fails for some reason, simply do not create the channel so there's
nothing that needs closing.  Then the methods field no longer holds anything
used, so eliminate it.  All the methods checking is done by [chan create].
2014-04-17 16:05:06 +00:00
jan.nijtmans da5348ec0f Remove all win95-specific test-cases, since Windows 95 is not supported any more. 2014-04-17 14:01:14 +00:00
dgp 322bd5dd1f merge 8.5 2014-04-16 20:11:05 +00:00
dgp 9f8bc994a9 merge trunk 2014-04-16 17:35:08 +00:00
dgp a7101c49af [d19a30db57] More testing. 2014-04-16 15:40:09 +00:00
dgp ea3c325aa5 Repair new test so all parts will be effective. 2014-04-16 15:37:26 +00:00
sebres 9915e77374 Test for [d19a30db57] extended 2014-04-16 15:30:37 +00:00
dgp 9db9d4ff84 [d19a30db57] Fixed segfault in [clock] internals. Includes test. 2014-04-16 15:30:23 +00:00
dgp 335591836a Test for [d19a30db57]. 2014-04-16 15:17:14 +00:00
jan.nijtmans e9e54156fa Fix compiler warnings in win32/cygwin build 2014-04-16 14:12:19 +00:00
jan.nijtmans f91d3dd584 merge fork: Segmentation fault using some functions of tcl::clock, fixed, belong to ticket [d19a30db57] 2014-04-16 14:07:10 +00:00
jan.nijtmans 88d357a99c Fix compiler warnings in win32/cygwin build. 2014-04-16 14:04:02 +00:00
sebres c97d829e0c Segmentation fault using some functions of tcl::clock, fixed, belong to ticket [d19a30db57] 2014-04-16 13:18:56 +00:00
jan.nijtmans be0324597a Remove unused variable, don't use deprecated function, some formatting. 2014-04-16 11:20:54 +00:00
jan.nijtmans fcca5df8d6 Upgrade from Winsock 1.1 to Winsock 2.2, which is always available on Win2000+. See: [http://msdn.microsoft.com/en-us/library/windows/desktop/ms742213%28v=vs.85%29.aspx] for details.
Move winsock initialization to TclpInitPlatform(void), so we can be sure everywhere that we have an initialized winsock2. 
Stub entries for TclWinGetServByName/TclWinGetSockOpt/TclWinSetSockOpt are no longer necessary (will be removed in 9.0, but are kept in 8.x)
2014-04-16 09:44:12 +00:00
jan.nijtmans 7284ed46fb Upgrade from Winsock 1.1 to Winsock 2.2, which is always available on Win2000+. See: [http://msdn.microsoft.com/en-us/library/windows/desktop/ms742213%28v=vs.85%29.aspx] for details.
Move winsock initialization to TclpInitPlatform(void), so we can be sure everywhere that we have an initialized winsock2. 
Stub entries for TclWinGetServByName/TclWinGetSockOpt/TclWinSetSockOpt are no longer necessary (will be removed in 9.0, but are kept in 8.x)
2014-04-16 09:28:54 +00:00
dgp 5b2fb22633 Purge the (now unused) argc and argv fields. 2014-04-15 18:36:01 +00:00
dgp 16c608178f Purge (now unused) argc and argv fields. 2014-04-15 17:45:26 +00:00
dgp 924739ac23 [88aef05cda] Stop reentrancy segfault in reflected channels by managing
callbacks as (copies of) lists, not shared Tcl_Obj arrays. Still could use
cleanup and improvements.
2014-04-15 17:25:37 +00:00
dgp fdcd434e12 [88aef05cda] Stop reentrancy segfault in reflected channels by managing
callbacks as (copies of) lists, not shared Tcl_Obj arrays.  Still could
use cleanup and improvements.
2014-04-15 16:09:28 +00:00
jan.nijtmans 5d9aef7a4e Test-cases which pick up the completion of bug-fix [e663138a06d98e48b5fbb42cc015cf1698f486cd|e663138a06]. Thanks, Don! 2014-04-15 10:41:44 +00:00
dgp b497ad4e53 [e663138a06] Fix the new INST_NUM_TYPE instruction so that the boundary
cases of [string is] on integral values are computed right.  Code is now
correct, though still suffers from a large amount of ugly.
2014-04-14 18:45:04 +00:00
jan.nijtmans a95a8e4a9c Fix [3118489]: NUL in filenames, now fixed for both Windows and UNIX.
For consistancy, any NUL character in a filename prevents the native filesystem to generate a native file representation for it. Other filesystems than the native one may still accept it, but it's not recommended.
2014-04-11 09:55:15 +00:00
jan.nijtmans d10806530d Fix [3118489] for Windows only: NUL in filenames. This allows various characters to be used in win32 filenames which are normally invalid, as described here: [http://cygwin.com/cygwin-ug-net/using-specialnames.html#pathnames-specialchars]. The Cygwin shell can handle those same filenames as well. In other shells (cmd.exe/mSys) or on the Windows desktop the filenames will look strange, but that's all. 2014-04-11 08:23:44 +00:00
jan.nijtmans c867dfd034 [792641f95b]: Normalized win32 paths should never contain backslash. 2014-04-10 13:59:13 +00:00
jan.nijtmans 601ecb35c8 [792641f95b]: Normalized win32 paths should never contain backslash. 2014-04-10 13:32:14 +00:00
jan.nijtmans 87fc10a8da Fix bug [e663138a06]: Test failures in "string is" 2014-04-10 07:57:18 +00:00
max 32d3c7b2a1 * Give clearer names to some of the state flags and sync them with Windows where it makes sense.
*  Rework WaitForConnect once more to always report ENOTCONN on I/O operations on failed async sockets.
  *  Fix synchronous connections to a server that only listens on IPv6 (or whatever comes later in the list returned by getaddrinfo(), socket-15.*)
  *  Fix spurious writable event on async sockets (socket-14.15).
2014-04-08 18:00:35 +00:00
oehhar 42143bf4e9 Beautify check for async connect reentry 2014-04-08 15:15:31 +00:00
jan.nijtmans a7350e3489 Provide full Tcl patchlevel to tcl.pc and move private libs to "Libs.private".
Record the fact that Tcl 8.6 requires Zlib 1.2.3 as a minimum. 
Supply both the shared library and the stub library to "Libs": Only one of them will actually be linked in, depending on whether -DUSE_TCL_STUBS is defined or not.
2014-04-08 15:02:27 +00:00
jan.nijtmans 8a33c02a15 Provide full Tcl patchlevel to tcl.pc and move private libs to "Libs.private". 2014-04-08 14:52:04 +00:00
oehhar 1abf8e4ad8 Changed error report logic, that an async connect error is only reported by 'fconfigure -error' and not by a possible last command terminating the async connect. The terminating command always returns "socket is not connected" on connect error. In addition, some flags were renamed: TCP_ASYNC_SOCKET to TCP_NONBLOCKING and also the new state flags. 2014-04-08 14:40:20 +00:00
max e92b34ab12 Rename error to connectError in struct TcpState. 2014-04-07 15:18:09 +00:00
max 59e40535f5 Rename CreateClientSocket to TcpConnect 2014-04-07 15:11:32 +00:00
oehhar 3d4fa09102 Renamed function CreateClientSocket to TcpConnect and variable error to connectError 2014-04-07 15:08:31 +00:00
jan.nijtmans 5e96fb5ee1 Merge-mark: Those two test-cases will arrive in trunk as soon as branch [http://core.tcl.tk/tcl/timeline?r=bug-13d3af3ad5|bug-13d3af3ad5] is merged. 2014-04-07 14:32:59 +00:00
oehhar d0e001a334 Return async connect error by first following read or write operation. 2014-04-07 12:34:18 +00:00
oehhar 8bf9869083 Moved tests socket-8.2 and socket-8.3 to socket-14.3 and socket-14.4 and made them robust against connect failures 2014-04-04 16:44:33 +00:00
oehhar 269a88ebaf Avoid multiple returns of connect errors 2014-04-04 16:27:39 +00:00
max 9757dd7eba Move tests 8.2 and 8.3 out of the IPv4/IPv6 loop to 14.13 and 14.14. 2014-04-04 15:56:48 +00:00
max 9365e418f3 Fix/improve tests. 2014-04-04 15:45:34 +00:00
max ebb15ded42 Add tests for bugs [336441ed59] and [581937ab1e] from core-8-5-branch. 2014-04-04 11:53:33 +00:00
oehhar 2f51a2e128 Fix for Bug [97069ea11a]: Set return message in close if a flush error is reported (which may be an error from a background flush) 2014-04-04 11:14:17 +00:00
max a5f9898e34 * Rework WaitForConnect() to fix synchronous completion of asynchronous connections.
*  Let TcpInputProc() and TcpOutputProc() fail before calling any I/O syscalls when an asynchronous connection has failed.
  *  Adjust the tests accordingly.
2014-04-04 10:02:47 +00:00
oehhar e2c7cfecc1 Fix for Bug [97069ea11a]: Set return message in close if a flush error is reported (which may be an error from a background flush) 2014-04-04 08:55:16 +00:00
max c736ad3e88 Make the naming of TcpState variables consistent 2014-04-04 08:51:58 +00:00
max 3d1b611f4c Revert the tests for bug#97069ea11a from socket.test, because it is hard to test with the socket command in a platform-independent way. As the bug is in tclIOChan.c and should be tested there with a dummy channel driver that can reliably reproduce the situation that suppresses the error message. 2014-04-04 08:29:51 +00:00
oehhar 6cfae752ff Fix bug [581937ab1e]: fire readable event on async socket connect failure 2014-04-02 13:33:29 +00:00
oehhar 253440c377 Fix bug [581937ab1e]: fire readable event on async socket connect failure 2014-04-02 12:43:29 +00:00
oehhar 61e5f733e5 Fix bug [336441ed59]: Win socket stall on quick termination of async socket connect 2014-04-02 10:02:18 +00:00
oehhar 77a33cf2ff Test to demonstrate bug [336441ed59]. Depends on timing and will not always fire but is better than nothing. Reliable for me. 2014-04-02 09:54:27 +00:00
oehhar 3756d27b06 Set all variables written by the notifier thread as volatile. 2014-04-02 08:35:02 +00:00
oehhar 551a220b1f Marked all communication variables which are set by notifier thread with "volatile". 2014-04-02 08:22:12 +00:00
max a529e32955 Centralize and clarify the user of 169.254.0.0 as a non-reachable address. 2014-04-01 14:00:04 +00:00
oehhar 2e6d32b5a8 Imported fix for bug [97069ea11a] from branch bug-97069ea11a: empty error message on stalled background flush after async socket connect fail 2014-04-01 13:06:22 +00:00
max 9bc964b5bb Add test cases for Bug [97069ea11a]. 2014-04-01 12:17:36 +00:00
oehhar daa585d846 Removed thread debugging printf messages 2014-04-01 12:16:39 +00:00
oehhar bc5c5261e5 Fix test failure socket-2.9: "1 {not owner}" instead of "1 {couldn't open socket address already in use}" by only setting returned error message if not jet set. 2014-04-01 11:31:49 +00:00
oehhar a2e8fa6c52 Set return message in close if a flush error is reported (which may be an error from a background flush). Ticket [97069ea11a] 2014-04-01 09:52:34 +00:00
jan.nijtmans 4fa18eaa12 Add missing @TCL_LIB_FLAG@ to tcl.pc.in (derived from ticket [5bcb5026ad]) 2014-03-31 18:44:55 +00:00
jan.nijtmans f9c41b4bcc Cherry-pick [c54059aaad] from trunk: Added support for reporting TEA-like info via pkg-config.
Add missing @TCL_LIB_FLAG@ (derived from ticket [5bcb5026ad])
2014-03-31 15:23:30 +00:00
dgp 8655555eb4 Merge minimal fix for iocmd-23.11.
Note that top channel regeneration is removed, so that Preserve/Release
call pairs are sure to operate on the same pointers.  Other bug fixes
may need to change that.
2014-03-28 20:29:03 +00:00
dgp 2a5a3323cb Minimal patch to fix iocmd-23.11. Might not be the best fix, but is *a* fix. 2014-03-27 21:35:57 +00:00
dgp 2d315899eb Test iocmd-23.11 demos another segfault. 2014-03-27 19:15:19 +00:00
dgp 6ac66b5476 Test iocmd-23.11 demos another segfault. 2014-03-27 19:14:01 +00:00
dgp 2b096d89a3 Test iogt-2.4 is another segfault demo for [721ec69271]. 2014-03-27 16:47:33 +00:00
dgp 4252a9c191 Test iogt-2.4 is another segfault demo for [721ec69271]. 2014-03-27 16:44:04 +00:00
dgp 52fe1455a7 New test iortrans-4.8.1 exposes segfault bug [721ec69271]. 2014-03-27 16:27:09 +00:00
jan.nijtmans 4c46afc6f5 Implement RFE [b42b208ba4]: file attributes -readonly (and -archive, -hidden, -system) on Cygwin. 2014-03-26 14:38:07 +00:00
jan.nijtmans 1673f7d67a Only write back file attributes if any of them really changed. 2014-03-26 14:34:56 +00:00
jan.nijtmans c6eeda71be Implementation of [b42b208ba4]: file attributes -readonly on Cygwin. For completeness, implemented -archive, -hidden and -system as well. 2014-03-26 10:37:57 +00:00
ferrieux 15df01c93d Add test io-53.12 to verify proper unbuffered sync-fcopy [Bug #3096275] 2014-03-24 21:42:56 +00:00
oehhar 1408478f56 Fire also readable event on final async connect failure. Armor WaitForSocketEvent by access signal against notifier thread access. 2014-03-24 11:03:04 +00:00
dgp 021c7456ff Merge the checkins of the dgp-read-bytes branch onto the trunk, up to
and including checkin a1e82fb63e .  Do not merge checkin bae1c688f2
which starts to take the dgp-read-bytes branch into directions apparently
unfriendly to stacked channels, which tests for [chan push] on the trunk
help us to detect.
2014-03-23 20:59:28 +00:00
oehhar 6eb3a60712 Be sure tsd pointer to the info structure is invalidated before memory free 2014-03-23 11:42:35 +00:00
oehhar 8837ed8935 Be shure tsd pointer to the info structure is invalidated before memory free 2014-03-23 11:31:59 +00:00
oehhar e5b53212a8 Bug [336441ed59]: Buffer infoPtr between socket creation and insertion into info structure in thread local memory. Backported fix from commit [65b320b464] from branch "bug-[13d3af3ad5]". 2014-03-22 16:14:26 +00:00
dgp 97ef11cb6e Added comments raising questions about possible updates to channel
drivers on Windows.
2014-03-21 17:11:32 +00:00
dgp 71680aec07 missing declaration 2014-03-21 14:45:00 +00:00
dgp 4d2bb24e84 Correct namespace bugs in normally skipped tests.
Constrain them as "knownBug" rather than "unknownFailure".
2014-03-21 14:07:40 +00:00
dgp 56214ea49a Added comment explaining the "knownBug" 2014-03-21 13:40:58 +00:00
dgp 88cddf0b80 Convert "impossible" test to a "knownBug" test. Exposes a segfault! 2014-03-21 13:20:06 +00:00
dgp 183b5fd257 Restore default suppression of large file test. 2014-03-21 12:58:29 +00:00
dgp ff8fef8c8d Fixup ChanRead() header. Note (dstSize > 0) precondition. 2014-03-21 12:57:58 +00:00
dgp 2a7cf86d30 io-34.21 - fix bugs in normally skipped test.
io-35.18b - knownBug is not buggy on this branch.
2014-03-21 12:56:46 +00:00
dgp 0530d01b63 Documentation header for ChanRead() 2014-03-21 02:36:47 +00:00
dgp e9bb48106a Both callers of ChanRead() have simlar epilogs. Shift that into ChanRead
and refactor.
2014-03-20 23:21:48 +00:00
dgp c6fabad70e Don't allow buffer recycling to prevent or delay buffersize shrinkage. 2014-03-20 20:18:20 +00:00
dgp 88abf586de Stop routine clearing of CHANNEL_EOF. Only clear when there's a reason
(seek, eofchar change, ungets).  Otherwise, once you hit EOF you stay there.
2014-03-20 19:25:11 +00:00
dgp 16dcfe4b5f Use assertions about the pushback buffers to simplify their handling.
Mark several things left TODO.  Some tidying.
2014-03-20 16:31:11 +00:00
dgp bce5a2ae75 merge 8.5 2014-03-20 14:45:05 +00:00
jan.nijtmans cb2a1e4c13 Fix [2f7cbd01c3]: tcl8.6.1 fails to build on FreeBSD 10.0 2014-03-20 10:10:04 +00:00
jan.nijtmans a62fd8466e Fix [2f7cbd01c3]: tcl8.6.1 fails to build on FreeBSD 10.0 2014-03-20 10:06:25 +00:00
jan.nijtmans c7a7120587 Proposed fix for [2f7cbd01c3]. 2014-03-20 09:22:29 +00:00
dgp 02d7d5af4c Let TranslateInputEOL handle the "\r$eofChar" sequence in CRLF mode. 2014-03-19 21:43:31 +00:00
dgp 3e8c032e35 Complete rewrite of DoRead(). 2014-03-19 20:32:37 +00:00
dgp b9409ecdff Remove long dead "BAD_BLOCKING" support code so it no longer confuses
people reading/editing this code.
2014-03-17 17:56:47 +00:00
oehhar 912913c340 WaitForConnection like tclUnixSock.c, new option [fconfigure -connecting] 2014-03-14 17:01:33 +00:00
oehhar ac3233bf36 file tclWinSock.c reorganized to minimize diff to tclUnixSock.c. No functional change 2014-03-14 16:59:25 +00:00
oehhar 934c12d4a4 Remove writable shortcut and errorneous workaround to get [connect -async] fail error to [fconfigure -error] 2014-03-14 14:36:14 +00:00
max d1f0a7b5f7 * More test improvements for async sockets.
*  Advance async connections whenever the channel is touched (e.g. by [chan configure]).
  *  Add a noblock argument to WaitForConnect(), so that advancing async connections from [chan configure] doesn't block even on a blocking socket.
2014-03-14 14:26:22 +00:00
oehhar ee1a8aed63 Remove writable shortcut and errorneous workaround to get [connect -async] fail error to [fconfigure -error] 2014-03-14 10:59:48 +00:00
oehhar 2a00313c29 Async connect terminates: fire fileevent by setting readyEvent, propage commit fail message to [fconfigure -error] 2014-03-14 09:12:13 +00:00
max b896860fbf * Hide transient errors of the internal iterations of [socket -async] from the script level.
*  More tests for corner cases.
2014-03-11 17:34:54 +00:00
dgp 6c5d496711 Compress code for better single screen viewing. 2014-03-11 16:51:38 +00:00
oehhar 66cf21eaaf No [fconfigure -error] error in connect process; gets after failed async connect returns connect error 2014-03-11 13:35:37 +00:00
dgp 47b0512591 Trial rewrite of AUTO input translation. 2014-03-11 03:38:55 +00:00
dgp 080aa64c3d .... and then the bug fix. 2014-03-10 19:30:22 +00:00
dgp f8cfd0ecd0 Test for the bug I just committed. 2014-03-10 19:29:54 +00:00
dgp ee4aa52d42 Rewrite CRLF translation to use more system calls. 2014-03-10 19:00:19 +00:00
max ca31b05c9d WaitForConnect may only call back to CreateClientSocket when the socket is writable or something. When it does so for a pending socket, it is falsely assumed to have succeeded and a subsequent read/write operation will fail. 2014-03-10 18:11:08 +00:00
dgp baf55bba6a Bring CRLF translation in parallel with others. 2014-03-10 17:58:32 +00:00
oehhar 75cae59053 Additional security for wrong pointer 2014-03-10 16:59:09 +00:00
oehhar 10a9e13e5d Fire write fileevent if async connect fails finally (test socket-14.2) 2014-03-10 15:38:21 +00:00
oehhar 3bb727a3c7 Also continue async connect without event loop if gets/puts is called (test socket-14.8.*) 2014-03-10 15:22:56 +00:00
oehhar e02a90c10d Workaround if FD_CONNECT notification comes before socket list registration in TcpThreadActionProc 2014-03-10 14:36:38 +00:00
max 5de4bf8981 * tclUnixSock.c: Fix WaitForConnect() for client sockets that have to try more than one address.
*  socket.test: Extend and improve tests for [socket -async]
  *  socket.test: Add latency measuring and calculation for Windows.
2014-03-10 12:08:44 +00:00
dgp 12a4d297b9 TranslateInputEOL doesn't need to return anything. No caller cares.
Other optimizations and simplifications.
2014-03-10 03:09:03 +00:00
jan.nijtmans bef17eed6a Merge core-8-5-branch (New tests covering INPUT_NEED_NL flag handling. One exposes a bug.) 2014-03-09 21:58:12 +00:00
jan.nijtmans 6bcc85f28e Mark io-35.18b test as knownBug 2014-03-09 21:55:51 +00:00
dgp 61e8875498 TranslateInputEOL() callers no longer need assert dstLen <= srcLen. 2014-03-07 20:15:12 +00:00
dgp 5350ed1efe Simplify the input eof char scan. Update some comments. 2014-03-07 19:43:16 +00:00
oehhar d08f5c564c Still incomplete info structure in event proc: try to protect with locks (unsuccesful). Probably locks in accept socket creation missing. 2014-03-07 07:40:30 +00:00
oehhar f5cb50339f More debug to chase different fd in struct than in callback 2014-03-06 18:21:40 +00:00
dgp f3343892a7 Variable "rawStart" serves no purpose. 2014-03-06 15:51:06 +00:00
oehhar 886199711d Terminate async connect synchronously by any blocking operation 2014-03-06 10:37:13 +00:00
dgp 57182d5ef3 Remove old dead code; silence compiler warnings; tidy up. 2014-03-05 19:41:51 +00:00
dgp 5fe3c1fbee Adapt CopyAndTranslateBuffer() to changes in TranslateInputEOL().
Notably no longer using the INPUT_NEED_NL flag.
2014-03-05 17:16:35 +00:00
oehhar bfa93a894c "gets" blocked after async cannect: SOCKET_ASYNC_CONNECT was not cleared 2014-03-05 15:15:43 +00:00
max 6ddf4c01d5 Refactor the error handling logic around connect() 2014-03-05 14:40:27 +00:00
dgp e5f7fb59c4 Merge repair to correct failing tests. 2014-03-05 14:23:38 +00:00
max fa81506a01 avoid warnings about uninitialized infoPtr in DEBUG 2014-03-05 13:12:13 +00:00
max 74ed570183 Print out the value of infoPtr in DEBUG, so that coexisting sockets can be distinguished in the output. 2014-03-05 13:09:22 +00:00
oehhar 3183209237 Next async connect try works. Reset error and move notifier before connect. 2014-03-05 10:20:09 +00:00
max 5bef69e253 * Use watchEvents only for read/write/close events of [chan event], don't mix with internal use of accept and connect events.
*  WIP: Refactor the tail of CreateClientSocket() to get notifications for completed async connects right.
2014-03-04 18:54:48 +00:00
oehhar 3f6201e538 Reverted move of WSAAsyncSelect before connect -> FD_Connect message does also fire if it exists on call. 2014-03-04 07:54:18 +00:00
oehhar 596cd02dba WIP: async open event now passes to SocketEventProc() and connects but does not finalyze that (I guess). 2014-03-03 15:57:56 +00:00
dgp ecec9dacef Fixups make the test suite almost pass (except *io-39.17) 2014-03-01 03:01:41 +00:00
dgp ece5f1377f Bring over the ReadChars rewrite for integration into the other I/O work. 2014-02-28 19:01:42 +00:00
dgp c98d055207 another coverage test. 2014-02-28 18:36:00 +00:00
dgp 45f1f60132 tidy up. 2014-02-28 18:28:16 +00:00
dgp ff27c27a27 More ReadChars rewriting. Test suite now passes.
Note that this reform simplifies ReadChars a fair bit (at least in my eyes).
Also it does away with the use of an INPUT_NEED_NL flag, using the same
strategy for partial \r\n sequences as is used for incomplete multibyte chars.
2014-02-28 18:25:20 +00:00
max 3e6fc11b81 Make printf debugging switchable, because it affects 'make test' 2014-02-28 11:05:35 +00:00
max e622e61b3a Broken intermediate state.
Calling back to CreateClientSocket() from the event loop works, but
the final failed or succeeded state of an asyncronous socket does not
get notified to the channel correctly.
2014-02-28 10:47:53 +00:00
dgp 2f73d6810c Work in progress attempting a ReadChars rewrite. 2014-02-27 20:21:10 +00:00
dgp 378008089c remove comment 2014-02-27 20:11:47 +00:00
dgp 8f2742b2f5 merge 8.5 2014-02-26 20:28:36 +00:00
dgp 4a58d3c00a New tests covering INPUT_NEED_NL flag handling. One exposes a bug. 2014-02-26 17:47:46 +00:00
jan.nijtmans 4840e7dbb4 Simplify macro handling in tclOO*Decls.h, just as already done in "novem" [0c37ab8944], itcl*Decls.h and tdbc*Decls.h.
This doesn't change the way symbols are exported. This simplifications were already present in the Tcl 8.6.2 headers, but those were buggy when tclOO was linked in statically without using stubs.
2014-02-26 13:16:18 +00:00
max e31901dcd5 Merge trunk 2014-02-26 12:44:12 +00:00
dgp 2207a65968 More coverage tests and bug fixes. 2014-02-26 11:26:00 +00:00
dkf 282de06cab [8d5f5b8034] Flush internal representations in [string tolower] of unshared obj 2014-02-25 15:49:52 +00:00
oehhar 8f14151916 Do not reopen a win serial channel for serial detection. There are issues with some Bluetooth virtual com. Fix bug [2413550], patch by Rolf Schroedter 2014-02-25 08:02:17 +00:00
dgp e8e909f1cd Reduce ReadBytes to simplest expression. 2014-02-24 21:25:08 +00:00
dgp 6733e57835 simplification trims 2014-02-24 21:01:07 +00:00
dgp 6978c989d7 merge 8.5 2014-02-24 20:53:57 +00:00
dgp d888a526f4 Merge the stricter binary mode experiment. 2014-02-24 19:11:37 +00:00
oehhar ada7d66e9f Do not reopen a win serial channel for serial detection. There are issues with some Bluetooth virtual com. Fix bug [2413550], patch by Rolf Schroedter 2014-02-24 17:25:08 +00:00
dkf 1a8dc819d6 [3597178]: Improve documentation of what's going on with encodings 2014-02-23 13:07:36 +00:00
dgp b3bfa3ee1d Simplify ReadBytes based on new constraints. 2014-02-21 15:12:16 +00:00
dgp b6212a88b3 fix type error 2014-02-21 15:02:35 +00:00
dgp 01eab1e2cd Switch consistently on the narrower def of binary mode. 2014-02-20 21:23:33 +00:00
dgp 90725c211b Can we send some binary reads down the char-reading path? 2014-02-20 20:31:55 +00:00
dgp 90d3294572 Refactoring repair to fix failing test. 2014-02-20 03:51:16 +00:00
dgp 6e09fe5ab9 [1230597] Update test comment. 2014-02-19 14:12:37 +00:00
dgp fa1ab4f740 [1230597] Update test comment. 2014-02-19 14:10:55 +00:00
dgp 3ac01c586f Next coverage test to expose another refactoring error. 2014-02-19 03:45:17 +00:00
dgp c65342141a Shortcut ReadBytes() when it's a no-op. 2014-02-19 03:36:15 +00:00
dgp 0e8e132aca Callers of TranslateInputEOL are expected to manage the INPUT_NEED_NL flag. 2014-02-18 23:20:06 +00:00
dgp d4cb991846 Another coverage test that reveals refactoring error. 2014-02-18 21:27:35 +00:00
dgp e51a0bd096 coverage test for -translation cr 2014-02-18 18:35:19 +00:00
dgp 521821debf Refactor correction exposed by coverage test. 2014-02-18 18:26:22 +00:00
dgp 06a0036a49 Coverage test for -translation auto handling of INPUT_SAW_CR flag.
Demonstrates refactor failure.
2014-02-18 17:54:06 +00:00
dkf c91f173c8b [9bf7e67b37]: minor documentation blooper 2014-02-16 08:18:29 +00:00
dgp ec145024fd merge 8.5 2014-02-12 18:46:03 +00:00
jan.nijtmans 47f1107ebc typo 2014-02-12 12:15:15 +00:00
jan.nijtmans 78bbf020ea typo 2014-02-12 12:13:32 +00:00
dgp 342aec6684 Refactor so that CopyAndTranslateBuffer() calls on TranslateInputEOL()
instead of duplicating so much of its function.  Note the testing gaps.
2014-02-11 19:53:41 +00:00
jan.nijtmans f0882154a8 Fix execute permission bit (should not be set) for *Decls.h files 2014-02-11 10:58:30 +00:00
oehhar 89583a6623 Changed position of flag evaluation as proposed by Phil Hoffman 2014-02-11 08:53:33 +00:00
jan.nijtmans 0258413bde Eliminate all usage of WIN32 and __WIN32__ macros: Some compilers (e.g. Clang/LLVM) don't define it, and _WIN32 is much more portable anyway.
See: [http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system#WindowsCygwinnonPOSIXandMinGW]
2014-02-10 11:59:22 +00:00
dgp e175773277 This patch is not pointless. Tests encoding-25.* demonstrate its utility. 2014-02-07 19:40:25 +00:00
dgp b6ae0212a1 [a4494e28ed] Use flag bit instead of NULL pointer to suppress
teardown list of imported commands when the original command
              gets re-created. This prevents the panic otherwise possible when
              the invalid state represented by the NULL pointer is encountered
              during a command delete trace.
2014-02-06 22:48:34 +00:00
dgp 5ff110b484 Change the flag value to avoid merge conflict with trunk. 2014-02-06 22:41:14 +00:00
dgp 438b687249 [a4494e28ed] Use flag bit instead of NULL pointer to suppress teardown list of
imported commands when the original command gets re-created.  This prevents the
panic otherwise possible when the invalid state represented by the NULL pointer
is encountered during a command delete trace.
2014-02-06 22:38:17 +00:00
jan.nijtmans 8c3bcfe950 check for existance of __BORLANDC__ before using its value 2014-02-06 21:45:29 +00:00
jan.nijtmans cacb796441 Check for existance of __BORLANDC__ before using its value 2014-02-06 21:44:43 +00:00
dgp cad363e97d Revised ReadChars to restore an attempt to make sure we do not short read
because of a false notion of limited storage space.
The test suite does not appear to demonstrate any case where this matters.
Could be an incomplete test suite, or an example of pointless code.
2014-02-06 19:04:36 +00:00
dgp f54081e9e5 merge 8.5 2014-02-06 16:33:24 +00:00
jan.nijtmans 40094302e0 Satisfy required position of __stdcall from VC++ 2014-02-04 21:52:46 +00:00
jan.nijtmans c7569e1c35 Satisfy required position of __stdcall from VC++ 2014-02-04 21:51:32 +00:00
jan.nijtmans ae659fdb12 Add missing __stdcall (which crashes on win32), and clean-up indenting 2014-02-04 21:33:13 +00:00
jan.nijtmans fc5e6debde remove duplicate declaration 2014-02-04 21:29:44 +00:00
jan.nijtmans 876dd3ac96 Add missing __stdcall (which crashes on win32), and clean-up indenting 2014-02-04 21:21:53 +00:00
dgp 8c665116c9 Simplify the core output operations of channels. Reduce duplicative and dead code. 2014-02-04 16:24:14 +00:00
dgp 1eb2dfe0fc Simplify the core output operations of channels. Reduce duplicative and
dead code.
2014-02-04 15:17:12 +00:00
dgp f53e4a7a0e Be sure to finalize the identity encoding. 2014-02-04 14:30:55 +00:00
dkf 5be047220d make the printing of source much less inclined to be fazed by non-ASCII chars 2014-02-04 09:02:23 +00:00
dkf 510244810f [971cb4f1db]: Make debugging traces less inclined to serious visual corruption 2014-02-04 08:15:52 +00:00
dgp 9f92115d2d merge 8.5 2014-02-03 22:58:36 +00:00
jan.nijtmans ad8e3dcb0a Fix [651e828a52]: Wrong Windows version reported for Windows 8.1 2014-02-03 15:19:26 +00:00
jan.nijtmans f77ffeb9b2 Fix [651e828a52]: Wrong Windows version reported for Windows 8.1 2014-02-03 14:43:52 +00:00
dkf c574af192d add compilation of [string is] 2014-02-02 16:01:21 +00:00
dkf fd4bc0f106 compilation of [string is] 2014-02-02 14:43:48 +00:00
dkf cca7f018e0 improve the disassembly 2014-02-02 14:42:12 +00:00
dgp e12cc95f12 Simplify macro typecasting. 2014-01-31 22:07:10 +00:00
dgp beb8c62dff The "channel" Tcl_ObjType is caching only. It never needs an UpdateString routine.
It's also static to the tclIO.c file.
2014-01-31 20:42:21 +00:00
dgp 684c2c9051 Do not call updateStringProc directly. We have TclGetString() for that. 2014-01-31 20:02:58 +00:00
jan.nijtmans 767efbf478 Fix [4b3b7a3082]: tcl8.5.15/generic/tclExecute.c:7713: array index before sanity check ? 2014-01-31 09:19:11 +00:00
jan.nijtmans b4b95b976a Fix [4b3b7a3082]: tcl8.5.15/generic/tclExecute.c:7713: array index before sanity check ? 2014-01-31 09:13:13 +00:00
dgp 2c59046c95 Refactor to eliminate the DoWriteChars() layer. 2014-01-30 20:10:21 +00:00
dgp f11f5780e0 Eliminate DoWrite(). It duplicates WriteBytes(). 2014-01-30 19:30:34 +00:00
dgp c00d7aa9b9 Trial: Implement DoWrite() as WriteBytes(). 2014-01-30 19:13:28 +00:00
dgp 050c8a639f Simplification and cleanup enabled by last commit. 2014-01-30 18:45:11 +00:00
dgp 248247d828 Refactor WriteChars() and WriteBytes() into simple wrappers of a common
routine Write().
2014-01-30 18:31:39 +00:00
oehhar 42f972d403 merge 8.5 2014-01-30 15:02:40 +00:00
dgp a92cc7b340 Eliminate the use of a staging buffer in WriteChars(). 2014-01-30 14:51:44 +00:00
jan.nijtmans b6ac569a5d Fix [22c10c8e79]: core-8-5: msvc6 build: "Side by Side" error 2014-01-30 14:50:22 +00:00
jan.nijtmans 2c00f457ae Fix [22c10c8e79]: core-8-5: msvc6 build: "Side by Side" error 2014-01-30 14:44:56 +00:00
dgp 4a8456e406 Eliminate the use of a staging buffer in WriteChars(). 2014-01-30 14:31:17 +00:00
oehhar 63d77c0046 win/tclWinChan.c Tcl_InitNotifier: Bug [2413550] Avoid reopening of serial channels which causes issues with Bluetooth virtual com. Patch by Rolf Schroedter. 2014-01-30 11:02:51 +00:00
andreask cc6eaf6308 Squashed C99 syntax breaking the native AIX cc. 2014-01-29 23:18:58 +00:00
dkf 6597355ad8 Compile [string is] with character classes in a non-awful way. Needs more work to make resulting bytecode disassemble nicely. 2014-01-29 13:59:32 +00:00
dgp c53002fe3b The outputStage field is now unused, so never allocate it. 2014-01-28 20:23:26 +00:00
dgp 2c2a7d737a tidy things up 2014-01-28 20:19:39 +00:00
dgp d250eba26d Working code with no staging buffer use. 2014-01-28 18:51:59 +00:00
dgp 2585021472 WIP 2014-01-28 11:04:57 +00:00
dgp 518e457db3 merge 8.5 2014-01-27 17:58:10 +00:00
dgp 7afa150e2f merge 8.5 2014-01-27 17:35:53 +00:00
dgp 490384e3e7 Revise the Tcl_Append* machinery to tolerate NULL bytes to append.
Then have ReadChars() use that machinery to resize buffer receiving input,
rather than invent its own version.  Simplify ReadChars() callers.
2014-01-27 17:35:27 +00:00
jan.nijtmans 4e83fe1049 sync tcl.m4 with Tk version 2014-01-25 21:41:48 +00:00
jan.nijtmans 5d9939831c sync tcl.m4 with Tk version 2014-01-25 21:41:12 +00:00
dkf f4549b8fc4 merge principal development branch 2014-01-25 09:02:30 +00:00
dgp d7803bcb41 merge 8.5 2014-01-24 22:33:30 +00:00
dgp c25181bd7d In WriteChars(), eliminate the copy step through a staging buffer when it
is not required for channel translation.
2014-01-24 21:52:59 +00:00
dgp 2ceb7a6077 In WriteChars(), eliminate the copy step through a staging buffer when
it is not required for channel translation.
2014-01-24 21:45:39 +00:00
dgp e3bde55a0f Eliminate the copy to a staging buffer when that serves no functional purpose. 2014-01-24 17:38:59 +00:00
dkf 834d5da992 improved tidy-up from branch 2014-01-22 19:33:03 +00:00
jan.nijtmans 2be298f89d remove unused variable 2014-01-22 13:48:16 +00:00
dkf c9ae8d64d3 minor tidying up 2014-01-22 09:14:57 +00:00
dkf 477af49f88 add compilation for [nextto] and [yieldto]; fix [a90d9331bc] 2014-01-22 09:11:07 +00:00
dkf 7716fd3e46 [a90d9331bc]: must not crash when yieldto called in vanishing namespace 2014-01-22 09:07:45 +00:00
dgp e99699b008 There is no need for ReadBytes() or its caller(s) to track how many bytes
are actually stored in objPtr.  The ByteArray Tcl_ObjType already has the
machinery to take care of this.
2014-01-21 22:08:16 +00:00
dgp 72fa9a96c8 Backport of bytearray append machinery to support bug fixes in ReadBytes. 2014-01-21 21:32:53 +00:00
dgp 8fc4750efc merge mark 2014-01-21 18:17:14 +00:00
dgp 78b4196767 Silence compiler warnings. 2014-01-21 18:16:37 +00:00
dgp 1e9a5591d9 [2992970] Restore safety of Tcl_AppendObjToObj(x, x) for bytearrays. 2014-01-21 17:25:41 +00:00
dkf 128e4211ae implementation of [yieldto] in bytecode 2014-01-21 15:07:59 +00:00
dkf 88b2f7f06e added compilation for [nextto] 2014-01-19 18:39:24 +00:00
dgp a994cc42f5 [2992970] Restore the safety of Tcl_AppendObjToObj(x, x) for bytearrays.
Also moves overflow checking to TclAppendBytesToByteArray() and adds
the ability to call TABTBA() with bytes==NULL, for appending unspecified
bytes.  That is, the string grows, but the new bytes are of undetermined
value.  Like Tcl_NewByteArrayObj(NULL, length) this option is useful
for manipulating buffers.  The TABTBA growth algorithm is also enhanced
a bit, copying over a fuller implementation from GrowStringBuffer()
in tclStringObj.c
2014-01-15 19:04:52 +00:00
dkf 12945e9a16 extend [string is] to booleans 2014-01-13 08:06:43 +00:00
dkf 2803a8a055 a different approach 2014-01-10 15:58:41 +00:00
dkf 29ae06c2d3 use compact form 2014-01-09 10:49:04 +00:00
jan.nijtmans 48459b2357 Make DEFAULT_TRIM_SET a MODULE_SCOPE string constant, so its value can be shared in tclCmdMZ.o and TclCompCmdsSZ.o
and it no longer pollutes the tclStringTrim.h header file.
2014-01-08 11:04:44 +00:00
dkf 8f95efa4cf merge main working branch 2014-01-07 14:25:22 +00:00
dkf c8e62b1cfa Add compilations for the following commands:
* concat
 * linsert
 * namespace origin
 * next
 * string replace
 * string tolower
 * string totitle
 * string toupper
 * string trim
 * string trimleft
 * string trimright
2014-01-07 14:19:04 +00:00
dkf cbc312324e make function static once more; not needed outside of source file 2014-01-07 14:13:37 +00:00
dkf 03ecb591a6 reduce the overhead of NR-enabled TclOO [next] 2014-01-07 13:59:30 +00:00
dkf 6bb7b1e15d factor out a common stanza 2014-01-05 17:31:38 +00:00
dkf a2e12b4377 merge main working branch 2014-01-05 17:00:15 +00:00
dkf 6d9846f8c9 merge trunk 2014-01-05 16:57:05 +00:00
mig 666deab1ea fix arraySet compiler to set -errorcode instead of -errorCode in return options 2014-01-05 15:01:52 +00:00
mig bb9e19e6eb skip the switch(result) on returning TCL_OK from a proc 2014-01-05 14:10:42 +00:00
mig ea8a9ba071 reducing TEBCdata: pc and cleanup now passed in the NREcallback 2014-01-05 12:01:04 +00:00
dkf 430c9bc178 redevelop code to have more in common with the interpreted [string is] and to remove non-working types 2014-01-02 15:30:53 +00:00
jan.nijtmans e7e7bafe96 merge-mark 2014-01-02 10:11:42 +00:00
dkf 9c349ce2e2 more fixes to instruction tracing; ensure all places that need DECACHE_STACK_INFO have it 2014-01-02 10:01:35 +00:00
dkf e7f9c9c822 merge main working branch 2014-01-02 09:38:03 +00:00
dkf 83fcae9bbe implement TclOO's [next] in bytecode 2014-01-02 09:17:07 +00:00
dkf d5961a83e0 merge main working branch; made opcode work by getting callback ordering right 2014-01-02 09:15:18 +00:00
dkf 9c6b83d5b1 merge trunk 2014-01-02 08:51:04 +00:00
dkf 8a115927af ... and more silly errors 2014-01-02 08:50:08 +00:00
dkf 68cab10668 merge trunk 2014-01-02 08:35:48 +00:00
dkf c28c2d5b9a oops... 2014-01-02 08:35:01 +00:00
dkf 78f85049ff merge main working branch 2014-01-02 08:32:36 +00:00
dkf a30f092ea3 merge trunk 2014-01-02 03:27:16 +00:00
dkf 4f13f826e4 more fixes to instruction tracing; ensure all places that need DECACHE_STACK_INFO have it. jan.nijtmans: Branch moved aside an hidden, so future bisects are not affected by this branch mistakes. 2014-01-02 03:10:43 +00:00
dkf 1c54736c0d factor out a common peephole stanza 2014-01-01 16:19:14 +00:00
dkf f9dd75e79c another jump peephole, this time with string comparisons 2013-12-31 23:34:57 +00:00
dkf d423ce0c06 more cleaning up of error-case instruction tracing 2013-12-31 17:28:16 +00:00
dkf 76b954ec41 merge trunk 2013-12-31 16:28:15 +00:00
dkf c45f1130d1 more peephole optimizations in TEBC, and better instruction execution traces 2013-12-31 16:26:55 +00:00
mig 0891bbbcbb clarify the resume sequence in TEBCresume; make checkInterp a local variable, remove it from the saved struct 2013-12-31 12:14:50 +00:00
dkf 05feb2c73f merge trunk 2013-12-31 10:49:07 +00:00
dkf 0e49a49b8f remove ill-advised change to assembler
What made sense for the compiler does not for the assembler, as that can (and does) build code blocks entirely out of order.
2013-12-31 10:47:19 +00:00
dgp 57dc79f34e merge trunk 2013-12-30 16:36:12 +00:00
dkf 413a0c2501 put the other definition of a trim set in the header file too 2013-12-30 11:56:54 +00:00
dkf 76007824cc Factor out the definition of the default string trim set; define it once only. 2013-12-30 11:40:44 +00:00
dkf db5995b2b8 merge main working branch 2013-12-30 10:24:20 +00:00
dkf 9083b5bf61 merge main working branch 2013-12-30 08:50:28 +00:00
dkf 4ad593f2bf implement [namespace origin] in bytecode 2013-12-30 08:37:49 +00:00
dkf cdacc33cbb allow generation by assembler 2013-12-30 08:16:21 +00:00
dkf f7157671ce corrected comment 2013-12-30 08:12:52 +00:00
dkf b004b21242 Improved general case of [string replace] implementation. 2013-12-29 18:49:20 +00:00
max 2a15c7082e merge trunk 2013-11-18 13:37:16 +00:00
max 9901b732cc To prepare for completion of the [socket -async] implementation on Windows [13d3af3ad5]:
*  Move the server code from CreateSocket to Tcl_OpenTcpServer.
  *  Rename CreateSocket to CreateClientSocket.
  *  Unify the naming convention of socket channels with Unix (sock + hex representation of the state/info structure).
2013-11-18 12:35:58 +00:00
dgp ffb2a3d9b4 merge trunk 2013-10-23 15:34:01 +00:00
dkf 0eb33efc7a merge main dev branch 2013-01-03 14:08:49 +00:00
dkf 53baa9e5c4 merge main dev branch 2013-01-03 14:07:24 +00:00
dkf af735a0ba9 merge main dev branch 2012-12-19 11:43:40 +00:00
dkf a7b60b26f1 merge main dev branch 2012-12-19 11:42:46 +00:00
dkf d6bd07fecc merge dkf-compile-misc-info 2012-11-20 12:14:18 +00:00
dkf f497ce9a95 merge dkf-compile-misc-info 2012-11-20 12:13:43 +00:00
dkf 414163addc merge main dev branch 2012-11-05 21:56:13 +00:00
dkf 71fd534215 merge main dev branch 2012-11-05 21:55:40 +00:00
dkf b8bcc352ea merge main dev branch 2012-11-05 15:33:44 +00:00
dkf f04eef80d7 merge main dev branch 2012-11-05 15:28:01 +00:00
dkf 2de2d8678f reorder to preserve main BC development branch sequence better 2012-11-02 20:39:10 +00:00
dkf d5e04d6200 merge dkf-compile-misc-info 2012-11-02 20:25:57 +00:00
dkf 6d14b815b2 Work on compilation of [string is].
Hit some problem edge cases with differences in strictness of edge cases that
will force a rethink ([string is boolean] is significantly more strict than
Tcl_GetBooleanFromObj).
2012-11-02 16:50:06 +00:00
dkf ed18777278 Working towards a BCCed [next].
This version <i>almost</i> works, except for a problem with restoring the
context namespace upon return (which produces very strange results!)
2012-11-01 20:40:55 +00:00
384 changed files with 15190 additions and 10463 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
README: Tcl
This is the Tcl 8.6.1 source distribution.
This is the Tcl 8.6.2 source distribution.
http://sourceforge.net/projects/tcl/files/Tcl/
You can get any source release of Tcl from the URL above.
+150 -2
View File
@@ -8274,7 +8274,7 @@ Dropped support for OS X versions less than 10.4 (Tiger) (fellows)
2013-08-01 (bug fix)[1905562] RE recursion limit increased to support
reported usage of large expressions (porter)
2013-08-02 (bug fix)[9d6162] superclass slot empty crash (vdgoot,fellows)2013-08-02 (bug fix)[9d6162] superclass slot empty crash (vdgoot,fellows)
2013-08-02 (bug fix)[9d6162] superclass slot empty crash (vdgoot,fellows)
2013-08-03 (enhancement)[3611643] [auto_mkindex] support TclOO (fellows)
@@ -8303,4 +8303,152 @@ reported usage of large expressions (porter)
Many optmizations, improvements, and tightened stack management in bytecode.
--- Released 8.6.1, Septemer 20, 2013 --- http://core.tcl.tk/tcl/ for details
--- Released 8.6.1, September 20, 2013 --- http://core.tcl.tk/tcl/ for details
2013-09-27 (enhancement) improved ::env synchronization (fellows)
2013-10-20 (bug fix)[2835313] segfault from
[apply {{} {while 1 {a {*}[return -level 0 -code continue]}}}] (fellows)
2013-10-22 (bug fix)[3556215] [scan %E%G%X] support (fellows)
2013-10-25 (bug fix)[3eb2ec1] upper case scheme names in url. (nijtmans)
=> http 2.8.8
2013-10-29 (bug fix)[414d103] HP-UX: restore [exec] in threaded Tcl (nijtmans)
2013-11-04 (bug fix) C++ friendly stubs struct declarations (nijtmans)
2013-11-05 (bug fix)[426679e] OpenBSD man page rendering (nijtmans)
2013-11-12 (bug fix)[5425f2c] [fconfigure -error] breaks [socket -async]
2013-11-20 (bug fix) Improved environment variable management (nijtmans)
=> tcltest 2.3.7
2013-11-21 (platforms) Support for Windows 8.1 (nijtmans)
2013-12-06 (RFE) improved [foreach] bytecode (fellows)
2013-12-10 (RFE) improved [lmap] bytecode (sofer)
2013-12-11 (RFE) improved [catch] bytecode (sofer)
2013-12-18 (bug fix)[0b874c3] SEGV [coroutine X coroutine Y info frame] (porter)
2013-12-20 (RFE) reduced numeric conversion in bytecode (sofer)
2014-01-07 (RFE) compilers for [concat], [linsert], [namespace origin],
[next], [string replace], [string tolower], [string totitle], [string toupper],
[string trim], [string trimleft], [string trimright] (fellows)
2014-01-22 (RFE) compilers for [nextto], [yieldto] (fellows)
2014-02-02 (RFE) compiler for [string is] (fellows)
2014-02-06 (bug fix)[a4494e2] panic in test namespace-13.2 (porter)
2014-03-20 (bug fix)[2f7cbd0] FreeBSD 10.0 build failure (nijtmans)
2014-03-26 (RFE)[b42b208] Cygwin: [file attr -readonly -archive -hidden -system]
(nijtmans)
2014-03-27 (bug fix) segfault iocmd-23.11 (porter)
2014-04-02 (bug fix)[581937a] Win: readable event on async connect failure
2014-04-04 (bug fix)[581937a,97069ea] async socket connect fail (oehlmann)
2014-04-10 (bug fix)[792641f] Win: no \ in normalized path (nijtmans)
2014-04-11 (bug fix)[3118489] protect NUL in filenames (nijtmans)
2014-04-15 (bug fix)[88aef05] segfault iocmd-21.20 (porter)
2014-04-16 (update) Win: use Winsock 2.2 (nijtmans)
2014-04-16 (bug fix)[d19a30d] segfault clock-67.[23] (sebres)
2014-04-21 (bug fix) segfault iocmd-21.2[12] (porter)
2014-04-22 (bug fix) segfault iogt-2.4 (porter)
2014-04-23 (bug fix)[3493120] memleak in thread exit
2014-05-08 refactoring of core I/O functions (porter)
2014-05-09 (bug fix)[3389978] Win: extended paths support (nijtmans)
2014-05-09 (bug fix) segfault iocmd-32.1 (porter)
2014-05-11 (bug fix)[6d2f249] nested ensemble compile failure (fellows)
2014-05-17 (RFE)[47d6625] wideint support in [lsearch -integer] [lsort -integer] (nijtmans)
*** POTENTIAL INCOMPATIBILITY ***
2014-05-20 (bug fix) Stop eof and blocked state leaking thru stacks (porter)
*** POTENTIAL INCOMPATIBILITY ***
2014-05-20 (bug fix)[13d3af3] Win: socket -async tried only first IP address
2014-05-28 (platforms) work around systems that fail when a shared library
is deleted after it is [load]ed (kupries)
2014-05-31 (bug fix) chan events on pipes must be on proper ends (porter)
2014-06-04 (bug fix) socket-2.12 (porter)
2014-06-05 (bug fix) io-12.6 (kupries,porter)
2014-06-15 (RFE)[1b0266d] [dict replace|remove] return canonical dict (fellows)
*** POTENTIAL INCOMPATIBILITY ***
2014-06-16 (bug fix) socket-2.13 workaround broken select() (porter)
2014-06-20 (bug fix)[b47b176] iortrans.tf-11.0 (porter)
2014-06-22 (RFE)[2f9df4c] -cleanup scripts before -out compare (nijtmans)
2014-07-04 (update) Update Unicode data to 7.0 (nijtmans)
*** POTENTIAL INCOMPATIBILITY ***
2014-07-08 (bug) [chan push] converts blocked writes to error (aspect,porter)
2014-07-10 (bug fix)[7368d2] memleak Tcl_SetVar2(..,TCL_APPEND_VALUE) (porter)
*** POTENTIAL INCOMPATIBILITY ***
2014-07-11 (bug) leaks in SetFsPathFromAny, [info frame] (porter)
2014-07-15 (bug) compress dict leak in zlib xform channel close (porter)
2014-07-17 (bug fix)[9969cf8] leak trace data in coroutine deletion (porter)
2014-07-18 (RFE)[b43f2b4] fix [lappend] multi performance collapse (fellows)
2014-07-19 (bug fix)[75b8433] memleak managing oo instance lists (porter)
2014-07-21 (bug fix)[e6477e1] memleak in AtForkChild() (porter)
2014-07-22 (bug fix)[12b0997] memleak in iocmd.tf-32.0 (porter)
2014-07-28 (RFE) Optimized binary [chan copy] by moving buffers (porter)
2014-07-30 (enhancement) use refcounts, not Tcl_Preserve to manage lifetime
of Tcl_Channel (porter)
*** POTENTIAL INCOMPATIBILITY ***
2014-07-31 (bug fix)[a84a720] double free in oo chain deletion (porter)
2014-08-01 (bug fix)[e75faba] SEGV [apply {{} {namespace upvar a b [x]}}] (porter)
2014-08-01 (update) "macosx*-i386-x86_64" "macosx-universal" no longer compatible (kupries)
=> platform 1.0.13
2014-08-12 tzdata updated to Olson's tzdata2014f (kenny)
2014-08-17 (bug fix)[7d52e11] [info class subclasses oo::object] should
include ::oo::class (fellows)
2014-08-25 (TIP 429) New command [string cat] (leitgeb,ferrieux)
--- Released 8.6.2, August 27, 2014 --- http://core.tcl.tk/tcl/ for details
Regular → Executable
View File
Regular → Executable
View File
Executable → Regular
View File
Executable → Regular
View File
+4 -1
View File
@@ -293,6 +293,7 @@ of \fBTcl_Format\fR with functionality equivalent to:
Tcl_Obj *newPtr = \fBTcl_Format\fR(interp, format, objc, objv);
if (newPtr == NULL) return TCL_ERROR;
\fBTcl_AppendObjToObj\fR(objPtr, newPtr);
\fBTcl_DecrRefCount\fR(newPtr);
return TCL_OK;
.CE
.PP
@@ -337,7 +338,9 @@ Compile-time protection may be provided by some compilers.
of \fBTcl_ObjPrintf\fR with functionality equivalent to
.PP
.CS
\fBTcl_AppendObjToObj\fR(objPtr, \fBTcl_ObjPrintf\fR(format, ...));
Tcl_Obj *newPtr = \fBTcl_ObjPrintf\fR(format, ...);
\fBTcl_AppendObjToObj\fR(objPtr, newPtr);
\fBTcl_DecrRefCount\fR(newPtr);
.CE
.PP
but with greater convenience and efficiency when the appending
+3 -2
View File
@@ -637,8 +637,9 @@ On output, produces a locale-dependent time of day representation on a
12-hour clock. On input, accepts whatever \fB%r\fR produces.
.TP
\fB%R\fR
On output, produces a locale-dependent time of day representation on a
24-hour clock. On input, accepts whatever \fB%R\fR produces.
On output, the time in 24-hour notation (%H:%M). For a version
including the seconds, see \fB%T\fR below. On input, accepts whatever
\fB%R\fR produces.
.TP
\fB%s\fR
On output, simply formats the \fItimeVal\fR argument as a decimal
+15 -11
View File
@@ -25,11 +25,12 @@ below for a description), depending on \fIoption\fR. The legal
This appends the given string (or strings) to the value that the given
key maps to in the dictionary value contained in the given variable,
writing the resulting dictionary value back to that variable.
Non-existent keys are treated as if they map to an empty string.
Non-existent keys are treated as if they map to an empty string. The
updated dictionary value is returned.
.TP
\fBdict create \fR?\fIkey value ...\fR?
.
Create a new dictionary that contains each of the key/value mappings
Return a new dictionary that contains each of the key/value mappings
listed as arguments (keys and values alternating, with each key being
followed by its associated value.)
.TP
@@ -53,10 +54,10 @@ The key rule only matches those key/value pairs whose keys match any
of the given patterns (in the style of \fBstring match\fR.)
.VE 8.6
.TP
\fBdict filter \fIdictionaryValue \fBscript {\fIkeyVar valueVar\fB} \fIscript\fR
\fBdict filter \fIdictionaryValue \fBscript {\fIkeyVariable valueVariable\fB} \fIscript\fR
.
The script rule tests for matching by assigning the key to the
\fIkeyVar\fR and the value to the \fIvalueVar\fR, and then evaluating
\fIkeyVariable\fR and the value to the \fIvalueVariable\fR, and then evaluating
the given script which should return a boolean value (with the
key/value pair only being included in the result of the \fBdict
filter\fR when a true value is returned.) Note that the first
@@ -74,7 +75,7 @@ of the given patterns (in the style of \fBstring match\fR.)
.VE 8.6
.RE
.TP
\fBdict for {\fIkeyVar valueVar\fB} \fIdictionaryValue body\fR
\fBdict for {\fIkeyVariable valueVariable\fB} \fIdictionaryValue body\fR
.
This command takes three arguments, the first a two-element list of
variable names (for the key and value respectively of each mapping in
@@ -121,7 +122,8 @@ not specified) to the value that the given key maps to in the
dictionary value contained in the given variable, writing the
resulting dictionary value back to that variable. Non-existent keys
are treated as if they map to 0. It is an error to increment a value
for an existing key if that value is not an integer.
for an existing key if that value is not an integer. The updated
dictionary value is returned.
.TP
\fBdict info \fIdictionaryValue\fR
.
@@ -145,9 +147,10 @@ to in the dictionary value contained in the given variable, writing
the resulting dictionary value back to that variable. Non-existent
keys are treated as if they map to an empty list, and it is legal for
there to be no items to append to the list. It is an error for the
value that the key maps to to not be representable as a list.
value that the key maps to to not be representable as a list. The
updated dictionary value is returned.
.TP
\fBdict map \fR{\fIkeyVar valueVar\fR} \fIdictionaryValue body\fR
\fBdict map \fR{\fIkeyVariable valueVariable\fR} \fIdictionaryValue body\fR
.
This command applies a transformation to each element of a dictionary,
returning a new dictionary. It takes three arguments: the first is a
@@ -157,7 +160,7 @@ and the third a script to be evaluated for each mapping with the key and value
variables set appropriately (in the manner of \fBlmap\fR). In an iteration
where the evaluated script completes normally (\fBTCL_OK\fR, as opposed to an
\fBerror\fR, etc.) the result of the script is put into an accumulator
dictionary using the key that is the current contents of the \fIkeyVar\fR
dictionary using the key that is the current contents of the \fIkeyVariable\fR
variable at that point. The result of the \fBdict map\fR command is the
accumulator dictionary after all keys have been iterated over.
.RS
@@ -202,7 +205,7 @@ This operation takes the name of a variable containing a dictionary
value and places an updated dictionary value in that variable
containing a mapping from the given key to the given value. When
multiple keys are present, this operation creates or updates a chain
of nested dictionaries.
of nested dictionaries. The updated dictionary value is returned.
.TP
\fBdict size \fIdictionaryValue\fR
.
@@ -216,7 +219,8 @@ dictionary value in that variable that does not contain a mapping for
the given key. Where multiple keys are present, this describes a path
through nested dictionaries to the mapping to remove. At least one key
must be specified, but the last key on the key-path need not exist.
All other components on the path must exist.
All other components on the path must exist. The updated dictionary
value is returned.
.TP
\fBdict update \fIdictionaryVariable key varName \fR?\fIkey varName ...\fR? \fIbody\fR
.
+27 -7
View File
@@ -14,10 +14,21 @@ encoding \- Manipulate encodings
.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.
Strings in Tcl are logically a sequence of 16-bit Unicode characters.
These strings are represented in memory as a sequence of bytes that
may be in one of several encodings: modified UTF\-8 (which uses 1 to 3
bytes per character), 16-bit
.QW Unicode
(which uses 2 bytes per character, with an endianness that is
dependent on the host architecture), and binary (which uses a single
byte per character but only handles a restricted range of characters).
Tcl does not guarantee to always use the same encoding for the same
string.
.PP
Different operating system interfaces or applications may generate
strings in other encodings such as Shift\-JIS. The \fBencoding\fR
command helps to bridge the gap between Unicode and these other
formats.
.SH DESCRIPTION
.PP
Performs one of several encoding related operations, depending on
@@ -37,8 +48,9 @@ system encoding is used.
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.
character (indeed, the resulting string is a binary string as far as
Tcl is concerned, at least initially). If \fIencoding\fR is not
specified, the current system encoding is used.
.TP
\fBencoding dirs\fR ?\fIdirectoryList\fR?
.
@@ -56,6 +68,11 @@ searchable directory, that element is ignored.
.
Returns a list containing the names of all of the encodings that are
currently available.
The encodings
.QW utf-8
and
.QW iso8859-1
are guaranteed to be present in the list.
.TP
\fBencoding system\fR ?\fIencoding\fR?
.
@@ -73,7 +90,7 @@ However, because the \fBsource\fR command always reads files using the
current system encoding, Tcl will only source such files correctly
when the encoding used to write the file is the same. This tends not
to be true in an internationalized setting. For example, if such a
file was sourced in North America (where the ISO8859-1 is normally
file was sourced in North America (where the ISO8859\-1 is normally
used), each byte in the file would be treated as a separate character
that maps to the 00 page in Unicode. The resulting Tcl strings will
not contain the expected Japanese characters. Instead, they will
@@ -93,3 +110,6 @@ which is the Hiragana letter HA.
Tcl_GetEncoding(3)
.SH KEYWORDS
encoding, unicode
.\" Local Variables:
.\" mode: nroff
.\" End:
+24 -3
View File
@@ -46,8 +46,11 @@ non-blocking mode; the \fBfcopy\fR command takes care of that automatically.
However, it is necessary to enter the event loop by using
the \fBvwait\fR command or by using Tk.
.PP
You are not allowed to do other I/O operations with
\fIinchan\fR or \fIoutchan\fR during a background \fBfcopy\fR.
You are not allowed to do other input operations with \fIinchan\fR, or
output operations with \fIoutchan\fR, during a background
\fBfcopy\fR. The converse is entirely legitimate, as exhibited by the
bidirectional fcopy example below.
.PP
If either \fIinchan\fR or \fIoutchan\fR get closed
while the copy is in progress, the current copy is stopped
and the command callback is \fInot\fR made.
@@ -57,7 +60,7 @@ then all data already queued for \fIoutchan\fR is written out.
Note that \fIinchan\fR can become readable during a background copy.
You should turn off any \fBfileevent\fR handlers during a background
copy so those handlers do not interfere with the copy.
Any I/O attempted by a \fBfileevent\fR handler will get a
Any wrong-sided I/O attempted (by a \fBfileevent\fR handler or otherwise) will get a
.QW "channel busy"
error.
.PP
@@ -149,6 +152,24 @@ set total 0
-command [list CopyMore $in $out $chunk]
vwait done
.CE
.PP
The fourth example starts an asynchronous, bidirectional fcopy between
two sockets. Those could also be pipes from two [open "|hal 9000" r+]
(though their conversation would remain secret to the script, since
all four fileevent slots are busy).
.PP
.CS
set flows 2
proc Done {dir args} {
global flows done
puts "$dir is over."
incr flows -1
if {$flows<=0} {set done 1}
}
\fBfcopy\fR $sok1 $sok2 -command [list Done UP]
\fBfcopy\fR $sok2 $sok1 -command [list Done DOWN]
vwait done
.CE
.SH "SEE ALSO"
eof(n), fblocked(n), fconfigure(n), file(n)
.SH KEYWORDS
+2 -1
View File
@@ -210,7 +210,8 @@ proc httpHandlerCallback {socket token} {
.TP
\fB\-headers\fR \fIkeyvaluelist\fR
.
This option is used to add extra headers to the HTTP request. The
This option is used to add headers not already specified
by \fB::http::config\fR to the HTTP request. The
\fIkeyvaluelist\fR argument must be a list with an even number of
elements that alternate between keys and values. The keys become
header field names. Newlines are stripped from the values so the
Executable → Regular
View File
+42 -6
View File
@@ -19,6 +19,21 @@ string \- Manipulate strings
Performs one of several string operations, depending on \fIoption\fR.
The legal \fIoption\fRs (which may be abbreviated) are:
.TP
\fBstring cat\fR ?\fIstring1\fR? ?\fIstring2...\fR?
.VS 8.6.2
Concatenate the given \fIstring\fRs just like placing them directly
next to each other and return the resulting compound string. If no
\fIstring\fRs are present, the result is an empty string.
.RS
.PP
This primitive is occasionally handier than juxtaposition of strings
when mixed quoting is wanted, or when the aim is to return the result
of a concatenation without resorting to \fBreturn\fR \fB\-level 0\fR,
and is more efficient than building a list of arguments and using
\fBjoin\fR with an empty join string.
.RE
.VE
.TP
\fBstring compare\fR ?\fB\-nocase\fR? ?\fB\-length\fI length\fR? \fIstring1 string2\fR
.
Perform a character-by-character comparison of strings \fIstring1\fR
@@ -131,8 +146,9 @@ Any Unicode printing character, including space.
.IP \fBpunct\fR 12
Any Unicode punctuation character.
.IP \fBspace\fR 12
Any Unicode whitespace character, zero width space (U+200b),
word joiner (U+2060) and zero width no-break space (U+feff) (=BOM).
Any Unicode whitespace character, mongolian vowel separator
(U+180e), zero width space (U+200b), word joiner (U+2060) or
zero width no-break space (U+feff) (=BOM).
.IP \fBtrue\fR 12
Any of the forms allowed to \fBTcl_GetBoolean\fR where the value is
true.
@@ -343,10 +359,13 @@ misleading.
\fBstring bytelength \fIstring\fR
.
Returns a decimal string giving the number of bytes used to represent
\fIstring\fR in memory. Because UTF\-8 uses one to three bytes to
represent Unicode characters, the byte length will not be the same as
the character length in general. The cases where a script cares about
the byte length are rare.
\fIstring\fR in memory when encoded as Tcl's internal modified UTF\-8;
Tcl may use other encodings for \fIstring\fR as well, and does not
guarantee to only use a single encoding for a particular \fIstring\fR.
Because UTF\-8 uses a variable number of bytes to represent Unicode
characters, the byte length will not be the same as the character
length in general. The cases where a script cares about the byte
length are rare.
.RS
.PP
In almost all cases, you should use the
@@ -354,10 +373,27 @@ In almost all cases, you should use the
Tcl byte array value). Refer to the \fBTcl_NumUtfChars\fR manual
entry for more details on the UTF\-8 representation.
.PP
Formally, the \fBstring bytelength\fR operation returns the content of
the \fIlength\fR field of the \fBTcl_Obj\fR structure, after calling
\fBTcl_GetString\fR to ensure that the \fIbytes\fR field is populated.
This is highly unlikely to be useful to Tcl scripts, as Tcl's internal
encoding is not strict UTF\-8, but rather a modified CESU\-8 with a
denormalized NUL (identical to that used in a number of places by
Java's serialization mechanism) to enable basic processing with
non-Unicode-aware C functions. As this representation should only
ever be used by Tcl's implementation, the number of bytes used to
store the representation is of very low value (except to C extension
code, which has direct access for the purpose of memory management,
etc.)
.PP
\fICompatibility note:\fR it is likely that this subcommand will be
withdrawn in a future version of Tcl. It is better to use the
\fBencoding convertto\fR command to convert a string to a known
encoding and then apply \fBstring length\fR to that.
.PP
.CS
\fBstring length\fR [encoding convertto utf-8 $theString]
.CE
.RE
.TP
\fBstring wordend \fIstring charIndex\fR
+3 -3
View File
@@ -10,7 +10,7 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
argc, argv, argv0, auto_path, env, errorCode, errorInfo, tcl_interactive, tcl_library, tcl_nonwordchars, tcl_patchLevel, tcl_pkgPath, tcl_platform, tcl_precision, tcl_rcFileName, tcl_traceCompile, tcl_traceEval, tcl_wordchars, tcl_version \- Variables used by Tcl
argc, argv, argv0, auto_path, env, errorCode, errorInfo, tcl_interactive, tcl_library, tcl_nonwordchars, tcl_patchLevel, tcl_pkgPath, tcl_platform, tcl_precision, tcl_rcFileName, tcl_traceCompile, tcl_traceExec, tcl_wordchars, tcl_version \- Variables used by Tcl
.BE
.SH DESCRIPTION
.PP
@@ -347,8 +347,8 @@ was compiled with threads enabled.
.
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.
This value comes from the getuid() and getpwuid() system calls on Unix,
and the value from the GetUserName() system call on Windows.
.TP
\fBwordSize\fR
.
+340 -297
View File
@@ -137,97 +137,107 @@ static const crange alphaRangeTable[] = {
{0x41, 0x5a}, {0x61, 0x7a}, {0xc0, 0xd6}, {0xd8, 0xf6},
{0xf8, 0x2c1}, {0x2c6, 0x2d1}, {0x2e0, 0x2e4}, {0x370, 0x374},
{0x37a, 0x37d}, {0x388, 0x38a}, {0x38e, 0x3a1}, {0x3a3, 0x3f5},
{0x3f7, 0x481}, {0x48a, 0x527}, {0x531, 0x556}, {0x561, 0x587},
{0x3f7, 0x481}, {0x48a, 0x52f}, {0x531, 0x556}, {0x561, 0x587},
{0x5d0, 0x5ea}, {0x5f0, 0x5f2}, {0x620, 0x64a}, {0x671, 0x6d3},
{0x6fa, 0x6fc}, {0x712, 0x72f}, {0x74d, 0x7a5}, {0x7ca, 0x7ea},
{0x800, 0x815}, {0x840, 0x858}, {0x8a2, 0x8ac}, {0x904, 0x939},
{0x958, 0x961}, {0x971, 0x977}, {0x979, 0x97f}, {0x985, 0x98c},
{0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9df, 0x9e1},
{0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa59, 0xa5c},
{0xa72, 0xa74}, {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8},
{0xaaa, 0xab0}, {0xab5, 0xab9}, {0xb05, 0xb0c}, {0xb13, 0xb28},
{0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb5f, 0xb61}, {0xb85, 0xb8a},
{0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9},
{0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc33},
{0xc35, 0xc39}, {0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8},
{0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xd05, 0xd0c}, {0xd0e, 0xd10},
{0xd12, 0xd3a}, {0xd7a, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1},
{0xdb3, 0xdbb}, {0xdc0, 0xdc6}, {0xe01, 0xe30}, {0xe40, 0xe46},
{0xe94, 0xe97}, {0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb0},
{0xec0, 0xec4}, {0xedc, 0xedf}, {0xf40, 0xf47}, {0xf49, 0xf6c},
{0xf88, 0xf8c}, {0x1000, 0x102a}, {0x1050, 0x1055}, {0x105a, 0x105d},
{0x106e, 0x1070}, {0x1075, 0x1081}, {0x10a0, 0x10c5}, {0x10d0, 0x10fa},
{0x10fc, 0x1248}, {0x124a, 0x124d}, {0x1250, 0x1256}, {0x125a, 0x125d},
{0x1260, 0x1288}, {0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5},
{0x12b8, 0x12be}, {0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310},
{0x1312, 0x1315}, {0x1318, 0x135a}, {0x1380, 0x138f}, {0x13a0, 0x13f4},
{0x1401, 0x166c}, {0x166f, 0x167f}, {0x1681, 0x169a}, {0x16a0, 0x16ea},
{0x1700, 0x170c}, {0x170e, 0x1711}, {0x1720, 0x1731}, {0x1740, 0x1751},
{0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17b3}, {0x1820, 0x1877},
{0x1880, 0x18a8}, {0x18b0, 0x18f5}, {0x1900, 0x191c}, {0x1950, 0x196d},
{0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19c1, 0x19c7}, {0x1a00, 0x1a16},
{0x1a20, 0x1a54}, {0x1b05, 0x1b33}, {0x1b45, 0x1b4b}, {0x1b83, 0x1ba0},
{0x1bba, 0x1be5}, {0x1c00, 0x1c23}, {0x1c4d, 0x1c4f}, {0x1c5a, 0x1c7d},
{0x1ce9, 0x1cec}, {0x1cee, 0x1cf1}, {0x1d00, 0x1dbf}, {0x1e00, 0x1f15},
{0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57},
{0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fbc}, {0x1fc2, 0x1fc4},
{0x1fc6, 0x1fcc}, {0x1fd0, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fe0, 0x1fec},
{0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffc}, {0x2090, 0x209c}, {0x210a, 0x2113},
{0x2119, 0x211d}, {0x212a, 0x212d}, {0x212f, 0x2139}, {0x213c, 0x213f},
{0x2145, 0x2149}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2ce4},
{0x2ceb, 0x2cee}, {0x2d00, 0x2d25}, {0x2d30, 0x2d67}, {0x2d80, 0x2d96},
{0x2da0, 0x2da6}, {0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe},
{0x2dc0, 0x2dc6}, {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde},
{0x3031, 0x3035}, {0x3041, 0x3096}, {0x309d, 0x309f}, {0x30a1, 0x30fa},
{0x30fc, 0x30ff}, {0x3105, 0x312d}, {0x3131, 0x318e}, {0x31a0, 0x31ba},
{0x31f0, 0x31ff}, {0x3400, 0x4db5}, {0x4e00, 0x9fcc}, {0xa000, 0xa48c},
{0xa4d0, 0xa4fd}, {0xa500, 0xa60c}, {0xa610, 0xa61f}, {0xa640, 0xa66e},
{0xa67f, 0xa697}, {0xa6a0, 0xa6e5}, {0xa717, 0xa71f}, {0xa722, 0xa788},
{0xa78b, 0xa78e}, {0xa790, 0xa793}, {0xa7a0, 0xa7aa}, {0xa7f8, 0xa801},
{0xa803, 0xa805}, {0xa807, 0xa80a}, {0xa80c, 0xa822}, {0xa840, 0xa873},
{0xa882, 0xa8b3}, {0xa8f2, 0xa8f7}, {0xa90a, 0xa925}, {0xa930, 0xa946},
{0xa960, 0xa97c}, {0xa984, 0xa9b2}, {0xaa00, 0xaa28}, {0xaa40, 0xaa42},
{0xaa44, 0xaa4b}, {0xaa60, 0xaa76}, {0xaa80, 0xaaaf}, {0xaab9, 0xaabd},
{0xaadb, 0xaadd}, {0xaae0, 0xaaea}, {0xaaf2, 0xaaf4}, {0xab01, 0xab06},
{0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e},
{0xabc0, 0xabe2}, {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb},
{0xf900, 0xfa6d}, {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17},
{0xfb1f, 0xfb28}, {0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbb1},
{0xfbd3, 0xfd3d}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb},
{0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff21, 0xff3a}, {0xff41, 0xff5a},
{0xff66, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7},
{0xffda, 0xffdc}
{0x800, 0x815}, {0x840, 0x858}, {0x8a0, 0x8b2}, {0x904, 0x939},
{0x958, 0x961}, {0x971, 0x980}, {0x985, 0x98c}, {0x993, 0x9a8},
{0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9df, 0x9e1}, {0xa05, 0xa0a},
{0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa59, 0xa5c}, {0xa72, 0xa74},
{0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0},
{0xab5, 0xab9}, {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30},
{0xb35, 0xb39}, {0xb5f, 0xb61}, {0xb85, 0xb8a}, {0xb8e, 0xb90},
{0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9}, {0xc05, 0xc0c},
{0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39}, {0xc85, 0xc8c},
{0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9},
{0xd05, 0xd0c}, {0xd0e, 0xd10}, {0xd12, 0xd3a}, {0xd7a, 0xd7f},
{0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6},
{0xe01, 0xe30}, {0xe40, 0xe46}, {0xe94, 0xe97}, {0xe99, 0xe9f},
{0xea1, 0xea3}, {0xead, 0xeb0}, {0xec0, 0xec4}, {0xedc, 0xedf},
{0xf40, 0xf47}, {0xf49, 0xf6c}, {0xf88, 0xf8c}, {0x1000, 0x102a},
{0x1050, 0x1055}, {0x105a, 0x105d}, {0x106e, 0x1070}, {0x1075, 0x1081},
{0x10a0, 0x10c5}, {0x10d0, 0x10fa}, {0x10fc, 0x1248}, {0x124a, 0x124d},
{0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288}, {0x128a, 0x128d},
{0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c2, 0x12c5},
{0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135a},
{0x1380, 0x138f}, {0x13a0, 0x13f4}, {0x1401, 0x166c}, {0x166f, 0x167f},
{0x1681, 0x169a}, {0x16a0, 0x16ea}, {0x16f1, 0x16f8}, {0x1700, 0x170c},
{0x170e, 0x1711}, {0x1720, 0x1731}, {0x1740, 0x1751}, {0x1760, 0x176c},
{0x176e, 0x1770}, {0x1780, 0x17b3}, {0x1820, 0x1877}, {0x1880, 0x18a8},
{0x18b0, 0x18f5}, {0x1900, 0x191e}, {0x1950, 0x196d}, {0x1970, 0x1974},
{0x1980, 0x19ab}, {0x19c1, 0x19c7}, {0x1a00, 0x1a16}, {0x1a20, 0x1a54},
{0x1b05, 0x1b33}, {0x1b45, 0x1b4b}, {0x1b83, 0x1ba0}, {0x1bba, 0x1be5},
{0x1c00, 0x1c23}, {0x1c4d, 0x1c4f}, {0x1c5a, 0x1c7d}, {0x1ce9, 0x1cec},
{0x1cee, 0x1cf1}, {0x1d00, 0x1dbf}, {0x1e00, 0x1f15}, {0x1f18, 0x1f1d},
{0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d},
{0x1f80, 0x1fb4}, {0x1fb6, 0x1fbc}, {0x1fc2, 0x1fc4}, {0x1fc6, 0x1fcc},
{0x1fd0, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fe0, 0x1fec}, {0x1ff2, 0x1ff4},
{0x1ff6, 0x1ffc}, {0x2090, 0x209c}, {0x210a, 0x2113}, {0x2119, 0x211d},
{0x212a, 0x212d}, {0x212f, 0x2139}, {0x213c, 0x213f}, {0x2145, 0x2149},
{0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2ce4}, {0x2ceb, 0x2cee},
{0x2d00, 0x2d25}, {0x2d30, 0x2d67}, {0x2d80, 0x2d96}, {0x2da0, 0x2da6},
{0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6},
{0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x3031, 0x3035},
{0x3041, 0x3096}, {0x309d, 0x309f}, {0x30a1, 0x30fa}, {0x30fc, 0x30ff},
{0x3105, 0x312d}, {0x3131, 0x318e}, {0x31a0, 0x31ba}, {0x31f0, 0x31ff},
{0x3400, 0x4db5}, {0x4e00, 0x9fcc}, {0xa000, 0xa48c}, {0xa4d0, 0xa4fd},
{0xa500, 0xa60c}, {0xa610, 0xa61f}, {0xa640, 0xa66e}, {0xa67f, 0xa69d},
{0xa6a0, 0xa6e5}, {0xa717, 0xa71f}, {0xa722, 0xa788}, {0xa78b, 0xa78e},
{0xa790, 0xa7ad}, {0xa7f7, 0xa801}, {0xa803, 0xa805}, {0xa807, 0xa80a},
{0xa80c, 0xa822}, {0xa840, 0xa873}, {0xa882, 0xa8b3}, {0xa8f2, 0xa8f7},
{0xa90a, 0xa925}, {0xa930, 0xa946}, {0xa960, 0xa97c}, {0xa984, 0xa9b2},
{0xa9e0, 0xa9e4}, {0xa9e6, 0xa9ef}, {0xa9fa, 0xa9fe}, {0xaa00, 0xaa28},
{0xaa40, 0xaa42}, {0xaa44, 0xaa4b}, {0xaa60, 0xaa76}, {0xaa7e, 0xaaaf},
{0xaab9, 0xaabd}, {0xaadb, 0xaadd}, {0xaae0, 0xaaea}, {0xaaf2, 0xaaf4},
{0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26},
{0xab28, 0xab2e}, {0xab30, 0xab5a}, {0xab5c, 0xab5f}, {0xabc0, 0xabe2},
{0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xf900, 0xfa6d},
{0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1f, 0xfb28},
{0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbb1}, {0xfbd3, 0xfd3d},
{0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb}, {0xfe70, 0xfe74},
{0xfe76, 0xfefc}, {0xff21, 0xff3a}, {0xff41, 0xff5a}, {0xff66, 0xffbe},
{0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc}
#if TCL_UTF_MAX > 4
,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d},
{0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10280, 0x1029c}, {0x102a0, 0x102d0},
{0x10300, 0x1031e}, {0x10330, 0x10340}, {0x10342, 0x10349}, {0x10380, 0x1039d},
{0x103a0, 0x103c3}, {0x103c8, 0x103cf}, {0x10400, 0x1049d}, {0x10800, 0x10805},
{0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10900, 0x10915}, {0x10920, 0x10939},
{0x10300, 0x1031f}, {0x10330, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375},
{0x10380, 0x1039d}, {0x103a0, 0x103c3}, {0x103c8, 0x103cf}, {0x10400, 0x1049d},
{0x10500, 0x10527}, {0x10530, 0x10563}, {0x10600, 0x10736}, {0x10740, 0x10755},
{0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855},
{0x10860, 0x10876}, {0x10880, 0x1089e}, {0x10900, 0x10915}, {0x10920, 0x10939},
{0x10980, 0x109b7}, {0x10a10, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33},
{0x10a60, 0x10a7c}, {0x10b00, 0x10b35}, {0x10b40, 0x10b55}, {0x10b60, 0x10b72},
{0x10a60, 0x10a7c}, {0x10a80, 0x10a9c}, {0x10ac0, 0x10ac7}, {0x10ac9, 0x10ae4},
{0x10b00, 0x10b35}, {0x10b40, 0x10b55}, {0x10b60, 0x10b72}, {0x10b80, 0x10b91},
{0x10c00, 0x10c48}, {0x11003, 0x11037}, {0x11083, 0x110af}, {0x110d0, 0x110e8},
{0x11103, 0x11126}, {0x11183, 0x111b2}, {0x111c1, 0x111c4}, {0x11680, 0x116aa},
{0x12000, 0x1236e}, {0x13000, 0x1342e}, {0x16800, 0x16a38}, {0x16f00, 0x16f44},
{0x16f93, 0x16f9f}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
{0x11103, 0x11126}, {0x11150, 0x11172}, {0x11183, 0x111b2}, {0x111c1, 0x111c4},
{0x11200, 0x11211}, {0x11213, 0x1122b}, {0x112b0, 0x112de}, {0x11305, 0x1130c},
{0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339}, {0x1135d, 0x11361},
{0x11480, 0x114af}, {0x11580, 0x115ae}, {0x11600, 0x1162f}, {0x11680, 0x116aa},
{0x118a0, 0x118df}, {0x11ac0, 0x11af8}, {0x12000, 0x12398}, {0x13000, 0x1342e},
{0x16800, 0x16a38}, {0x16a40, 0x16a5e}, {0x16ad0, 0x16aed}, {0x16b00, 0x16b2f},
{0x16b40, 0x16b43}, {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f}, {0x16f00, 0x16f44},
{0x16f93, 0x16f9f}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88},
{0x1bc90, 0x1bc99}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
{0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a},
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e},
{0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0},
{0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734},
{0x1d736, 0x1d74e}, {0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8},
{0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7cb}, {0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f},
{0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a},
{0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89},
{0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb},
{0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d}, {0x2f800, 0x2fa1d}
{0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7cb}, {0x1e800, 0x1e8c4}, {0x1ee00, 0x1ee03},
{0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f},
{0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c},
{0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9},
{0x1eeab, 0x1eebb}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d},
{0x2f800, 0x2fa1d}
#endif
};
#define NUM_ALPHA_RANGE (sizeof(alphaRangeTable)/sizeof(crange))
static const chr alphaCharTable[] = {
0xaa, 0xb5, 0xba, 0x2ec, 0x2ee, 0x376, 0x377, 0x386, 0x38c,
0x559, 0x66e, 0x66f, 0x6d5, 0x6e5, 0x6e6, 0x6ee, 0x6ef, 0x6ff,
0x710, 0x7b1, 0x7f4, 0x7f5, 0x7fa, 0x81a, 0x824, 0x828, 0x8a0,
0xaa, 0xb5, 0xba, 0x2ec, 0x2ee, 0x376, 0x377, 0x37f, 0x386,
0x38c, 0x559, 0x66e, 0x66f, 0x6d5, 0x6e5, 0x6e6, 0x6ee, 0x6ef,
0x6ff, 0x710, 0x7b1, 0x7f4, 0x7f5, 0x7fa, 0x81a, 0x824, 0x828,
0x93d, 0x950, 0x98f, 0x990, 0x9b2, 0x9bd, 0x9ce, 0x9dc, 0x9dd,
0x9f0, 0x9f1, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36, 0xa38,
0xa39, 0xa5e, 0xab2, 0xab3, 0xabd, 0xad0, 0xae0, 0xae1, 0xb0f,
@@ -241,14 +251,16 @@ static const chr alphaCharTable[] = {
0x1bae, 0x1baf, 0x1cf5, 0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071,
0x207f, 0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183,
0x2184, 0x2cf2, 0x2cf3, 0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006,
0x303b, 0x303c, 0xa62a, 0xa62b, 0xa8fb, 0xa9cf, 0xaa7a, 0xaab1, 0xaab5,
0xaab6, 0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44
0x303b, 0x303c, 0xa62a, 0xa62b, 0xa7b0, 0xa7b1, 0xa8fb, 0xa9cf, 0xaa7a,
0xaab1, 0xaab5, 0xaab6, 0xaac0, 0xaac2, 0xab64, 0xab65, 0xfb1d, 0xfb3e,
0xfb40, 0xfb41, 0xfb43, 0xfb44
#if TCL_UTF_MAX > 4
,0x1003c, 0x1003d, 0x10808, 0x10837, 0x10838, 0x1083c, 0x109be, 0x109bf, 0x10a00,
0x16f50, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb,
0x1d546, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47,
0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d,
0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e
0x11176, 0x111da, 0x1130f, 0x11310, 0x11332, 0x11333, 0x1133d, 0x114c4, 0x114c5,
0x114c7, 0x11644, 0x118ff, 0x16f50, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2,
0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39,
0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57,
0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e
#endif
};
@@ -259,11 +271,12 @@ static const chr alphaCharTable[] = {
*/
static const crange controlRangeTable[] = {
{0x0, 0x1f}, {0x7f, 0x9f}, {0x600, 0x604}, {0x200b, 0x200f},
{0x0, 0x1f}, {0x7f, 0x9f}, {0x600, 0x605}, {0x200b, 0x200f},
{0x202a, 0x202e}, {0x2060, 0x2064}, {0x2066, 0x206f}, {0xe000, 0xf8ff},
{0xfff9, 0xfffb}
#if TCL_UTF_MAX > 4
,{0x1d173, 0x1d17a}, {0xe0020, 0xe007f}, {0xf0000, 0xffffd}, {0x100000, 0x10fffd}
,{0x1bca0, 0x1bca3}, {0x1d173, 0x1d17a}, {0xe0020, 0xe007f}, {0xf0000, 0xffffd},
{0x100000, 0x10fffd}
#endif
};
@@ -286,15 +299,18 @@ static const crange digitRangeTable[] = {
{0x30, 0x39}, {0x660, 0x669}, {0x6f0, 0x6f9}, {0x7c0, 0x7c9},
{0x966, 0x96f}, {0x9e6, 0x9ef}, {0xa66, 0xa6f}, {0xae6, 0xaef},
{0xb66, 0xb6f}, {0xbe6, 0xbef}, {0xc66, 0xc6f}, {0xce6, 0xcef},
{0xd66, 0xd6f}, {0xe50, 0xe59}, {0xed0, 0xed9}, {0xf20, 0xf29},
{0x1040, 0x1049}, {0x1090, 0x1099}, {0x17e0, 0x17e9}, {0x1810, 0x1819},
{0x1946, 0x194f}, {0x19d0, 0x19d9}, {0x1a80, 0x1a89}, {0x1a90, 0x1a99},
{0x1b50, 0x1b59}, {0x1bb0, 0x1bb9}, {0x1c40, 0x1c49}, {0x1c50, 0x1c59},
{0xa620, 0xa629}, {0xa8d0, 0xa8d9}, {0xa900, 0xa909}, {0xa9d0, 0xa9d9},
{0xaa50, 0xaa59}, {0xabf0, 0xabf9}, {0xff10, 0xff19}
{0xd66, 0xd6f}, {0xde6, 0xdef}, {0xe50, 0xe59}, {0xed0, 0xed9},
{0xf20, 0xf29}, {0x1040, 0x1049}, {0x1090, 0x1099}, {0x17e0, 0x17e9},
{0x1810, 0x1819}, {0x1946, 0x194f}, {0x19d0, 0x19d9}, {0x1a80, 0x1a89},
{0x1a90, 0x1a99}, {0x1b50, 0x1b59}, {0x1bb0, 0x1bb9}, {0x1c40, 0x1c49},
{0x1c50, 0x1c59}, {0xa620, 0xa629}, {0xa8d0, 0xa8d9}, {0xa900, 0xa909},
{0xa9d0, 0xa9d9}, {0xa9f0, 0xa9f9}, {0xaa50, 0xaa59}, {0xabf0, 0xabf9},
{0xff10, 0xff19}
#if TCL_UTF_MAX > 4
,{0x104a0, 0x104a9}, {0x11066, 0x1106f}, {0x110f0, 0x110f9}, {0x11136, 0x1113f},
{0x111d0, 0x111d9}, {0x116c0, 0x116c9}, {0x1d7ce, 0x1d7ff}
{0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x114d0, 0x114d9}, {0x11650, 0x11659},
{0x116c0, 0x116c9}, {0x118e0, 0x118e9}, {0x16a60, 0x16a69}, {0x16b50, 0x16b59},
{0x1d7ce, 0x1d7ff}
#endif
};
@@ -317,15 +333,17 @@ static const crange punctRangeTable[] = {
{0x1b5a, 0x1b60}, {0x1bfc, 0x1bff}, {0x1c3b, 0x1c3f}, {0x1cc0, 0x1cc7},
{0x2010, 0x2027}, {0x2030, 0x2043}, {0x2045, 0x2051}, {0x2053, 0x205e},
{0x2308, 0x230b}, {0x2768, 0x2775}, {0x27e6, 0x27ef}, {0x2983, 0x2998},
{0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e3b},
{0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e42},
{0x3001, 0x3003}, {0x3008, 0x3011}, {0x3014, 0x301f}, {0xa60d, 0xa60f},
{0xa6f2, 0xa6f7}, {0xa874, 0xa877}, {0xa8f8, 0xa8fa}, {0xa9c1, 0xa9cd},
{0xaa5c, 0xaa5f}, {0xfe10, 0xfe19}, {0xfe30, 0xfe52}, {0xfe54, 0xfe61},
{0xff01, 0xff03}, {0xff05, 0xff0a}, {0xff0c, 0xff0f}, {0xff3b, 0xff3d},
{0xff5f, 0xff65}
#if TCL_UTF_MAX > 4
,{0x10100, 0x10102}, {0x10a50, 0x10a58}, {0x10b39, 0x10b3f}, {0x11047, 0x1104d},
{0x110be, 0x110c1}, {0x11140, 0x11143}, {0x111c5, 0x111c8}, {0x12470, 0x12473}
,{0x10100, 0x10102}, {0x10a50, 0x10a58}, {0x10af0, 0x10af6}, {0x10b39, 0x10b3f},
{0x10b99, 0x10b9c}, {0x11047, 0x1104d}, {0x110be, 0x110c1}, {0x11140, 0x11143},
{0x111c5, 0x111c8}, {0x11238, 0x1123d}, {0x115c1, 0x115c9}, {0x11641, 0x11643},
{0x12470, 0x12474}, {0x16b37, 0x16b3b}
#endif
};
@@ -345,7 +363,8 @@ static const chr punctCharTable[] = {
0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f, 0xfe63, 0xfe68, 0xfe6a, 0xfe6b,
0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f, 0xff5b, 0xff5d
#if TCL_UTF_MAX > 4
,0x1039f, 0x103d0, 0x10857, 0x1091f, 0x1093f, 0x10a7f, 0x110bb, 0x110bc
,0x1039f, 0x103d0, 0x1056f, 0x10857, 0x1091f, 0x1093f, 0x10a7f, 0x110bb, 0x110bc,
0x11174, 0x11175, 0x111cd, 0x114c6, 0x16a6e, 0x16a6f, 0x16af5, 0x16b44, 0x1bc9f
#endif
};
@@ -383,15 +402,16 @@ static const crange lowerRangeTable[] = {
{0x1f90, 0x1f97}, {0x1fa0, 0x1fa7}, {0x1fb0, 0x1fb4}, {0x1fc2, 0x1fc4},
{0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7}, {0x1ff2, 0x1ff4}, {0x2146, 0x2149},
{0x2c30, 0x2c5e}, {0x2c76, 0x2c7b}, {0x2d00, 0x2d25}, {0xa72f, 0xa731},
{0xa771, 0xa778}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xff41, 0xff5a}
{0xa771, 0xa778}, {0xa793, 0xa795}, {0xab30, 0xab5a}, {0xfb00, 0xfb06},
{0xfb13, 0xfb17}, {0xff41, 0xff5a}
#if TCL_UTF_MAX > 4
,{0x10428, 0x1044f}, {0x1d41a, 0x1d433}, {0x1d44e, 0x1d454}, {0x1d456, 0x1d467},
{0x1d482, 0x1d49b}, {0x1d4b6, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf},
{0x1d4ea, 0x1d503}, {0x1d51e, 0x1d537}, {0x1d552, 0x1d56b}, {0x1d586, 0x1d59f},
{0x1d5ba, 0x1d5d3}, {0x1d5ee, 0x1d607}, {0x1d622, 0x1d63b}, {0x1d656, 0x1d66f},
{0x1d68a, 0x1d6a5}, {0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6e1}, {0x1d6fc, 0x1d714},
{0x1d716, 0x1d71b}, {0x1d736, 0x1d74e}, {0x1d750, 0x1d755}, {0x1d770, 0x1d788},
{0x1d78a, 0x1d78f}, {0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9}
,{0x10428, 0x1044f}, {0x118c0, 0x118df}, {0x1d41a, 0x1d433}, {0x1d44e, 0x1d454},
{0x1d456, 0x1d467}, {0x1d482, 0x1d49b}, {0x1d4b6, 0x1d4b9}, {0x1d4bd, 0x1d4c3},
{0x1d4c5, 0x1d4cf}, {0x1d4ea, 0x1d503}, {0x1d51e, 0x1d537}, {0x1d552, 0x1d56b},
{0x1d586, 0x1d59f}, {0x1d5ba, 0x1d5d3}, {0x1d5ee, 0x1d607}, {0x1d622, 0x1d63b},
{0x1d656, 0x1d66f}, {0x1d68a, 0x1d6a5}, {0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6e1},
{0x1d6fc, 0x1d714}, {0x1d716, 0x1d71b}, {0x1d736, 0x1d74e}, {0x1d750, 0x1d755},
{0x1d770, 0x1d788}, {0x1d78a, 0x1d78f}, {0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9}
#endif
};
@@ -427,39 +447,41 @@ static const chr lowerCharTable[] = {
0x4f1, 0x4f3, 0x4f5, 0x4f7, 0x4f9, 0x4fb, 0x4fd, 0x4ff, 0x501,
0x503, 0x505, 0x507, 0x509, 0x50b, 0x50d, 0x50f, 0x511, 0x513,
0x515, 0x517, 0x519, 0x51b, 0x51d, 0x51f, 0x521, 0x523, 0x525,
0x527, 0x1e01, 0x1e03, 0x1e05, 0x1e07, 0x1e09, 0x1e0b, 0x1e0d, 0x1e0f,
0x1e11, 0x1e13, 0x1e15, 0x1e17, 0x1e19, 0x1e1b, 0x1e1d, 0x1e1f, 0x1e21,
0x1e23, 0x1e25, 0x1e27, 0x1e29, 0x1e2b, 0x1e2d, 0x1e2f, 0x1e31, 0x1e33,
0x1e35, 0x1e37, 0x1e39, 0x1e3b, 0x1e3d, 0x1e3f, 0x1e41, 0x1e43, 0x1e45,
0x1e47, 0x1e49, 0x1e4b, 0x1e4d, 0x1e4f, 0x1e51, 0x1e53, 0x1e55, 0x1e57,
0x1e59, 0x1e5b, 0x1e5d, 0x1e5f, 0x1e61, 0x1e63, 0x1e65, 0x1e67, 0x1e69,
0x1e6b, 0x1e6d, 0x1e6f, 0x1e71, 0x1e73, 0x1e75, 0x1e77, 0x1e79, 0x1e7b,
0x1e7d, 0x1e7f, 0x1e81, 0x1e83, 0x1e85, 0x1e87, 0x1e89, 0x1e8b, 0x1e8d,
0x1e8f, 0x1e91, 0x1e93, 0x1e9f, 0x1ea1, 0x1ea3, 0x1ea5, 0x1ea7, 0x1ea9,
0x1eab, 0x1ead, 0x1eaf, 0x1eb1, 0x1eb3, 0x1eb5, 0x1eb7, 0x1eb9, 0x1ebb,
0x1ebd, 0x1ebf, 0x1ec1, 0x1ec3, 0x1ec5, 0x1ec7, 0x1ec9, 0x1ecb, 0x1ecd,
0x1ecf, 0x1ed1, 0x1ed3, 0x1ed5, 0x1ed7, 0x1ed9, 0x1edb, 0x1edd, 0x1edf,
0x1ee1, 0x1ee3, 0x1ee5, 0x1ee7, 0x1ee9, 0x1eeb, 0x1eed, 0x1eef, 0x1ef1,
0x1ef3, 0x1ef5, 0x1ef7, 0x1ef9, 0x1efb, 0x1efd, 0x1fb6, 0x1fb7, 0x1fbe,
0x1fc6, 0x1fc7, 0x1fd6, 0x1fd7, 0x1ff6, 0x1ff7, 0x210a, 0x210e, 0x210f,
0x2113, 0x212f, 0x2134, 0x2139, 0x213c, 0x213d, 0x214e, 0x2184, 0x2c61,
0x2c65, 0x2c66, 0x2c68, 0x2c6a, 0x2c6c, 0x2c71, 0x2c73, 0x2c74, 0x2c81,
0x2c83, 0x2c85, 0x2c87, 0x2c89, 0x2c8b, 0x2c8d, 0x2c8f, 0x2c91, 0x2c93,
0x2c95, 0x2c97, 0x2c99, 0x2c9b, 0x2c9d, 0x2c9f, 0x2ca1, 0x2ca3, 0x2ca5,
0x2ca7, 0x2ca9, 0x2cab, 0x2cad, 0x2caf, 0x2cb1, 0x2cb3, 0x2cb5, 0x2cb7,
0x2cb9, 0x2cbb, 0x2cbd, 0x2cbf, 0x2cc1, 0x2cc3, 0x2cc5, 0x2cc7, 0x2cc9,
0x2ccb, 0x2ccd, 0x2ccf, 0x2cd1, 0x2cd3, 0x2cd5, 0x2cd7, 0x2cd9, 0x2cdb,
0x2cdd, 0x2cdf, 0x2ce1, 0x2ce3, 0x2ce4, 0x2cec, 0x2cee, 0x2cf3, 0x2d27,
0x2d2d, 0xa641, 0xa643, 0xa645, 0xa647, 0xa649, 0xa64b, 0xa64d, 0xa64f,
0xa651, 0xa653, 0xa655, 0xa657, 0xa659, 0xa65b, 0xa65d, 0xa65f, 0xa661,
0xa663, 0xa665, 0xa667, 0xa669, 0xa66b, 0xa66d, 0xa681, 0xa683, 0xa685,
0xa687, 0xa689, 0xa68b, 0xa68d, 0xa68f, 0xa691, 0xa693, 0xa695, 0xa697,
0xa723, 0xa725, 0xa727, 0xa729, 0xa72b, 0xa72d, 0xa733, 0xa735, 0xa737,
0xa739, 0xa73b, 0xa73d, 0xa73f, 0xa741, 0xa743, 0xa745, 0xa747, 0xa749,
0xa74b, 0xa74d, 0xa74f, 0xa751, 0xa753, 0xa755, 0xa757, 0xa759, 0xa75b,
0xa75d, 0xa75f, 0xa761, 0xa763, 0xa765, 0xa767, 0xa769, 0xa76b, 0xa76d,
0xa76f, 0xa77a, 0xa77c, 0xa77f, 0xa781, 0xa783, 0xa785, 0xa787, 0xa78c,
0xa78e, 0xa791, 0xa793, 0xa7a1, 0xa7a3, 0xa7a5, 0xa7a7, 0xa7a9, 0xa7fa
0x527, 0x529, 0x52b, 0x52d, 0x52f, 0x1e01, 0x1e03, 0x1e05, 0x1e07,
0x1e09, 0x1e0b, 0x1e0d, 0x1e0f, 0x1e11, 0x1e13, 0x1e15, 0x1e17, 0x1e19,
0x1e1b, 0x1e1d, 0x1e1f, 0x1e21, 0x1e23, 0x1e25, 0x1e27, 0x1e29, 0x1e2b,
0x1e2d, 0x1e2f, 0x1e31, 0x1e33, 0x1e35, 0x1e37, 0x1e39, 0x1e3b, 0x1e3d,
0x1e3f, 0x1e41, 0x1e43, 0x1e45, 0x1e47, 0x1e49, 0x1e4b, 0x1e4d, 0x1e4f,
0x1e51, 0x1e53, 0x1e55, 0x1e57, 0x1e59, 0x1e5b, 0x1e5d, 0x1e5f, 0x1e61,
0x1e63, 0x1e65, 0x1e67, 0x1e69, 0x1e6b, 0x1e6d, 0x1e6f, 0x1e71, 0x1e73,
0x1e75, 0x1e77, 0x1e79, 0x1e7b, 0x1e7d, 0x1e7f, 0x1e81, 0x1e83, 0x1e85,
0x1e87, 0x1e89, 0x1e8b, 0x1e8d, 0x1e8f, 0x1e91, 0x1e93, 0x1e9f, 0x1ea1,
0x1ea3, 0x1ea5, 0x1ea7, 0x1ea9, 0x1eab, 0x1ead, 0x1eaf, 0x1eb1, 0x1eb3,
0x1eb5, 0x1eb7, 0x1eb9, 0x1ebb, 0x1ebd, 0x1ebf, 0x1ec1, 0x1ec3, 0x1ec5,
0x1ec7, 0x1ec9, 0x1ecb, 0x1ecd, 0x1ecf, 0x1ed1, 0x1ed3, 0x1ed5, 0x1ed7,
0x1ed9, 0x1edb, 0x1edd, 0x1edf, 0x1ee1, 0x1ee3, 0x1ee5, 0x1ee7, 0x1ee9,
0x1eeb, 0x1eed, 0x1eef, 0x1ef1, 0x1ef3, 0x1ef5, 0x1ef7, 0x1ef9, 0x1efb,
0x1efd, 0x1fb6, 0x1fb7, 0x1fbe, 0x1fc6, 0x1fc7, 0x1fd6, 0x1fd7, 0x1ff6,
0x1ff7, 0x210a, 0x210e, 0x210f, 0x2113, 0x212f, 0x2134, 0x2139, 0x213c,
0x213d, 0x214e, 0x2184, 0x2c61, 0x2c65, 0x2c66, 0x2c68, 0x2c6a, 0x2c6c,
0x2c71, 0x2c73, 0x2c74, 0x2c81, 0x2c83, 0x2c85, 0x2c87, 0x2c89, 0x2c8b,
0x2c8d, 0x2c8f, 0x2c91, 0x2c93, 0x2c95, 0x2c97, 0x2c99, 0x2c9b, 0x2c9d,
0x2c9f, 0x2ca1, 0x2ca3, 0x2ca5, 0x2ca7, 0x2ca9, 0x2cab, 0x2cad, 0x2caf,
0x2cb1, 0x2cb3, 0x2cb5, 0x2cb7, 0x2cb9, 0x2cbb, 0x2cbd, 0x2cbf, 0x2cc1,
0x2cc3, 0x2cc5, 0x2cc7, 0x2cc9, 0x2ccb, 0x2ccd, 0x2ccf, 0x2cd1, 0x2cd3,
0x2cd5, 0x2cd7, 0x2cd9, 0x2cdb, 0x2cdd, 0x2cdf, 0x2ce1, 0x2ce3, 0x2ce4,
0x2cec, 0x2cee, 0x2cf3, 0x2d27, 0x2d2d, 0xa641, 0xa643, 0xa645, 0xa647,
0xa649, 0xa64b, 0xa64d, 0xa64f, 0xa651, 0xa653, 0xa655, 0xa657, 0xa659,
0xa65b, 0xa65d, 0xa65f, 0xa661, 0xa663, 0xa665, 0xa667, 0xa669, 0xa66b,
0xa66d, 0xa681, 0xa683, 0xa685, 0xa687, 0xa689, 0xa68b, 0xa68d, 0xa68f,
0xa691, 0xa693, 0xa695, 0xa697, 0xa699, 0xa69b, 0xa723, 0xa725, 0xa727,
0xa729, 0xa72b, 0xa72d, 0xa733, 0xa735, 0xa737, 0xa739, 0xa73b, 0xa73d,
0xa73f, 0xa741, 0xa743, 0xa745, 0xa747, 0xa749, 0xa74b, 0xa74d, 0xa74f,
0xa751, 0xa753, 0xa755, 0xa757, 0xa759, 0xa75b, 0xa75d, 0xa75f, 0xa761,
0xa763, 0xa765, 0xa767, 0xa769, 0xa76b, 0xa76d, 0xa76f, 0xa77a, 0xa77c,
0xa77f, 0xa781, 0xa783, 0xa785, 0xa787, 0xa78c, 0xa78e, 0xa791, 0xa797,
0xa799, 0xa79b, 0xa79d, 0xa79f, 0xa7a1, 0xa7a3, 0xa7a5, 0xa7a7, 0xa7a9,
0xa7fa, 0xab64, 0xab65
#if TCL_UTF_MAX > 4
,0x1d4bb, 0x1d7cb
#endif
@@ -481,14 +503,15 @@ static const crange upperRangeTable[] = {
{0x1fd8, 0x1fdb}, {0x1fe8, 0x1fec}, {0x1ff8, 0x1ffb}, {0x210b, 0x210d},
{0x2110, 0x2112}, {0x2119, 0x211d}, {0x212a, 0x212d}, {0x2130, 0x2133},
{0x2c00, 0x2c2e}, {0x2c62, 0x2c64}, {0x2c6d, 0x2c70}, {0x2c7e, 0x2c80},
{0xff21, 0xff3a}
{0xa7aa, 0xa7ad}, {0xff21, 0xff3a}
#if TCL_UTF_MAX > 4
,{0x10400, 0x10427}, {0x1d400, 0x1d419}, {0x1d434, 0x1d44d}, {0x1d468, 0x1d481},
{0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a},
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544},
{0x1d54a, 0x1d550}, {0x1d56c, 0x1d585}, {0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed},
{0x1d608, 0x1d621}, {0x1d63c, 0x1d655}, {0x1d670, 0x1d689}, {0x1d6a8, 0x1d6c0},
{0x1d6e2, 0x1d6fa}, {0x1d71c, 0x1d734}, {0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8}
,{0x10400, 0x10427}, {0x118a0, 0x118bf}, {0x1d400, 0x1d419}, {0x1d434, 0x1d44d},
{0x1d468, 0x1d481}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9},
{0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d53b, 0x1d53e},
{0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d56c, 0x1d585}, {0x1d5a0, 0x1d5b9},
{0x1d5d4, 0x1d5ed}, {0x1d608, 0x1d621}, {0x1d63c, 0x1d655}, {0x1d670, 0x1d689},
{0x1d6a8, 0x1d6c0}, {0x1d6e2, 0x1d6fa}, {0x1d71c, 0x1d734}, {0x1d756, 0x1d76e},
{0x1d790, 0x1d7a8}
#endif
};
@@ -511,52 +534,54 @@ static const chr upperCharTable[] = {
0x20c, 0x20e, 0x210, 0x212, 0x214, 0x216, 0x218, 0x21a, 0x21c,
0x21e, 0x220, 0x222, 0x224, 0x226, 0x228, 0x22a, 0x22c, 0x22e,
0x230, 0x232, 0x23a, 0x23b, 0x23d, 0x23e, 0x241, 0x248, 0x24a,
0x24c, 0x24e, 0x370, 0x372, 0x376, 0x386, 0x38c, 0x38e, 0x38f,
0x3cf, 0x3d8, 0x3da, 0x3dc, 0x3de, 0x3e0, 0x3e2, 0x3e4, 0x3e6,
0x3e8, 0x3ea, 0x3ec, 0x3ee, 0x3f4, 0x3f7, 0x3f9, 0x3fa, 0x460,
0x462, 0x464, 0x466, 0x468, 0x46a, 0x46c, 0x46e, 0x470, 0x472,
0x474, 0x476, 0x478, 0x47a, 0x47c, 0x47e, 0x480, 0x48a, 0x48c,
0x48e, 0x490, 0x492, 0x494, 0x496, 0x498, 0x49a, 0x49c, 0x49e,
0x4a0, 0x4a2, 0x4a4, 0x4a6, 0x4a8, 0x4aa, 0x4ac, 0x4ae, 0x4b0,
0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba, 0x4bc, 0x4be, 0x4c0, 0x4c1,
0x4c3, 0x4c5, 0x4c7, 0x4c9, 0x4cb, 0x4cd, 0x4d0, 0x4d2, 0x4d4,
0x4d6, 0x4d8, 0x4da, 0x4dc, 0x4de, 0x4e0, 0x4e2, 0x4e4, 0x4e6,
0x4e8, 0x4ea, 0x4ec, 0x4ee, 0x4f0, 0x4f2, 0x4f4, 0x4f6, 0x4f8,
0x4fa, 0x4fc, 0x4fe, 0x500, 0x502, 0x504, 0x506, 0x508, 0x50a,
0x50c, 0x50e, 0x510, 0x512, 0x514, 0x516, 0x518, 0x51a, 0x51c,
0x51e, 0x520, 0x522, 0x524, 0x526, 0x10c7, 0x10cd, 0x1e00, 0x1e02,
0x1e04, 0x1e06, 0x1e08, 0x1e0a, 0x1e0c, 0x1e0e, 0x1e10, 0x1e12, 0x1e14,
0x1e16, 0x1e18, 0x1e1a, 0x1e1c, 0x1e1e, 0x1e20, 0x1e22, 0x1e24, 0x1e26,
0x1e28, 0x1e2a, 0x1e2c, 0x1e2e, 0x1e30, 0x1e32, 0x1e34, 0x1e36, 0x1e38,
0x1e3a, 0x1e3c, 0x1e3e, 0x1e40, 0x1e42, 0x1e44, 0x1e46, 0x1e48, 0x1e4a,
0x1e4c, 0x1e4e, 0x1e50, 0x1e52, 0x1e54, 0x1e56, 0x1e58, 0x1e5a, 0x1e5c,
0x1e5e, 0x1e60, 0x1e62, 0x1e64, 0x1e66, 0x1e68, 0x1e6a, 0x1e6c, 0x1e6e,
0x1e70, 0x1e72, 0x1e74, 0x1e76, 0x1e78, 0x1e7a, 0x1e7c, 0x1e7e, 0x1e80,
0x1e82, 0x1e84, 0x1e86, 0x1e88, 0x1e8a, 0x1e8c, 0x1e8e, 0x1e90, 0x1e92,
0x1e94, 0x1e9e, 0x1ea0, 0x1ea2, 0x1ea4, 0x1ea6, 0x1ea8, 0x1eaa, 0x1eac,
0x1eae, 0x1eb0, 0x1eb2, 0x1eb4, 0x1eb6, 0x1eb8, 0x1eba, 0x1ebc, 0x1ebe,
0x1ec0, 0x1ec2, 0x1ec4, 0x1ec6, 0x1ec8, 0x1eca, 0x1ecc, 0x1ece, 0x1ed0,
0x1ed2, 0x1ed4, 0x1ed6, 0x1ed8, 0x1eda, 0x1edc, 0x1ede, 0x1ee0, 0x1ee2,
0x1ee4, 0x1ee6, 0x1ee8, 0x1eea, 0x1eec, 0x1eee, 0x1ef0, 0x1ef2, 0x1ef4,
0x1ef6, 0x1ef8, 0x1efa, 0x1efc, 0x1efe, 0x1f59, 0x1f5b, 0x1f5d, 0x1f5f,
0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x213e, 0x213f, 0x2145,
0x2183, 0x2c60, 0x2c67, 0x2c69, 0x2c6b, 0x2c72, 0x2c75, 0x2c82, 0x2c84,
0x2c86, 0x2c88, 0x2c8a, 0x2c8c, 0x2c8e, 0x2c90, 0x2c92, 0x2c94, 0x2c96,
0x2c98, 0x2c9a, 0x2c9c, 0x2c9e, 0x2ca0, 0x2ca2, 0x2ca4, 0x2ca6, 0x2ca8,
0x2caa, 0x2cac, 0x2cae, 0x2cb0, 0x2cb2, 0x2cb4, 0x2cb6, 0x2cb8, 0x2cba,
0x2cbc, 0x2cbe, 0x2cc0, 0x2cc2, 0x2cc4, 0x2cc6, 0x2cc8, 0x2cca, 0x2ccc,
0x2cce, 0x2cd0, 0x2cd2, 0x2cd4, 0x2cd6, 0x2cd8, 0x2cda, 0x2cdc, 0x2cde,
0x2ce0, 0x2ce2, 0x2ceb, 0x2ced, 0x2cf2, 0xa640, 0xa642, 0xa644, 0xa646,
0xa648, 0xa64a, 0xa64c, 0xa64e, 0xa650, 0xa652, 0xa654, 0xa656, 0xa658,
0xa65a, 0xa65c, 0xa65e, 0xa660, 0xa662, 0xa664, 0xa666, 0xa668, 0xa66a,
0xa66c, 0xa680, 0xa682, 0xa684, 0xa686, 0xa688, 0xa68a, 0xa68c, 0xa68e,
0xa690, 0xa692, 0xa694, 0xa696, 0xa722, 0xa724, 0xa726, 0xa728, 0xa72a,
0xa72c, 0xa72e, 0xa732, 0xa734, 0xa736, 0xa738, 0xa73a, 0xa73c, 0xa73e,
0xa740, 0xa742, 0xa744, 0xa746, 0xa748, 0xa74a, 0xa74c, 0xa74e, 0xa750,
0xa752, 0xa754, 0xa756, 0xa758, 0xa75a, 0xa75c, 0xa75e, 0xa760, 0xa762,
0xa764, 0xa766, 0xa768, 0xa76a, 0xa76c, 0xa76e, 0xa779, 0xa77b, 0xa77d,
0xa77e, 0xa780, 0xa782, 0xa784, 0xa786, 0xa78b, 0xa78d, 0xa790, 0xa792,
0xa7a0, 0xa7a2, 0xa7a4, 0xa7a6, 0xa7a8, 0xa7aa
0x24c, 0x24e, 0x370, 0x372, 0x376, 0x37f, 0x386, 0x38c, 0x38e,
0x38f, 0x3cf, 0x3d8, 0x3da, 0x3dc, 0x3de, 0x3e0, 0x3e2, 0x3e4,
0x3e6, 0x3e8, 0x3ea, 0x3ec, 0x3ee, 0x3f4, 0x3f7, 0x3f9, 0x3fa,
0x460, 0x462, 0x464, 0x466, 0x468, 0x46a, 0x46c, 0x46e, 0x470,
0x472, 0x474, 0x476, 0x478, 0x47a, 0x47c, 0x47e, 0x480, 0x48a,
0x48c, 0x48e, 0x490, 0x492, 0x494, 0x496, 0x498, 0x49a, 0x49c,
0x49e, 0x4a0, 0x4a2, 0x4a4, 0x4a6, 0x4a8, 0x4aa, 0x4ac, 0x4ae,
0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba, 0x4bc, 0x4be, 0x4c0,
0x4c1, 0x4c3, 0x4c5, 0x4c7, 0x4c9, 0x4cb, 0x4cd, 0x4d0, 0x4d2,
0x4d4, 0x4d6, 0x4d8, 0x4da, 0x4dc, 0x4de, 0x4e0, 0x4e2, 0x4e4,
0x4e6, 0x4e8, 0x4ea, 0x4ec, 0x4ee, 0x4f0, 0x4f2, 0x4f4, 0x4f6,
0x4f8, 0x4fa, 0x4fc, 0x4fe, 0x500, 0x502, 0x504, 0x506, 0x508,
0x50a, 0x50c, 0x50e, 0x510, 0x512, 0x514, 0x516, 0x518, 0x51a,
0x51c, 0x51e, 0x520, 0x522, 0x524, 0x526, 0x528, 0x52a, 0x52c,
0x52e, 0x10c7, 0x10cd, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0a,
0x1e0c, 0x1e0e, 0x1e10, 0x1e12, 0x1e14, 0x1e16, 0x1e18, 0x1e1a, 0x1e1c,
0x1e1e, 0x1e20, 0x1e22, 0x1e24, 0x1e26, 0x1e28, 0x1e2a, 0x1e2c, 0x1e2e,
0x1e30, 0x1e32, 0x1e34, 0x1e36, 0x1e38, 0x1e3a, 0x1e3c, 0x1e3e, 0x1e40,
0x1e42, 0x1e44, 0x1e46, 0x1e48, 0x1e4a, 0x1e4c, 0x1e4e, 0x1e50, 0x1e52,
0x1e54, 0x1e56, 0x1e58, 0x1e5a, 0x1e5c, 0x1e5e, 0x1e60, 0x1e62, 0x1e64,
0x1e66, 0x1e68, 0x1e6a, 0x1e6c, 0x1e6e, 0x1e70, 0x1e72, 0x1e74, 0x1e76,
0x1e78, 0x1e7a, 0x1e7c, 0x1e7e, 0x1e80, 0x1e82, 0x1e84, 0x1e86, 0x1e88,
0x1e8a, 0x1e8c, 0x1e8e, 0x1e90, 0x1e92, 0x1e94, 0x1e9e, 0x1ea0, 0x1ea2,
0x1ea4, 0x1ea6, 0x1ea8, 0x1eaa, 0x1eac, 0x1eae, 0x1eb0, 0x1eb2, 0x1eb4,
0x1eb6, 0x1eb8, 0x1eba, 0x1ebc, 0x1ebe, 0x1ec0, 0x1ec2, 0x1ec4, 0x1ec6,
0x1ec8, 0x1eca, 0x1ecc, 0x1ece, 0x1ed0, 0x1ed2, 0x1ed4, 0x1ed6, 0x1ed8,
0x1eda, 0x1edc, 0x1ede, 0x1ee0, 0x1ee2, 0x1ee4, 0x1ee6, 0x1ee8, 0x1eea,
0x1eec, 0x1eee, 0x1ef0, 0x1ef2, 0x1ef4, 0x1ef6, 0x1ef8, 0x1efa, 0x1efc,
0x1efe, 0x1f59, 0x1f5b, 0x1f5d, 0x1f5f, 0x2102, 0x2107, 0x2115, 0x2124,
0x2126, 0x2128, 0x213e, 0x213f, 0x2145, 0x2183, 0x2c60, 0x2c67, 0x2c69,
0x2c6b, 0x2c72, 0x2c75, 0x2c82, 0x2c84, 0x2c86, 0x2c88, 0x2c8a, 0x2c8c,
0x2c8e, 0x2c90, 0x2c92, 0x2c94, 0x2c96, 0x2c98, 0x2c9a, 0x2c9c, 0x2c9e,
0x2ca0, 0x2ca2, 0x2ca4, 0x2ca6, 0x2ca8, 0x2caa, 0x2cac, 0x2cae, 0x2cb0,
0x2cb2, 0x2cb4, 0x2cb6, 0x2cb8, 0x2cba, 0x2cbc, 0x2cbe, 0x2cc0, 0x2cc2,
0x2cc4, 0x2cc6, 0x2cc8, 0x2cca, 0x2ccc, 0x2cce, 0x2cd0, 0x2cd2, 0x2cd4,
0x2cd6, 0x2cd8, 0x2cda, 0x2cdc, 0x2cde, 0x2ce0, 0x2ce2, 0x2ceb, 0x2ced,
0x2cf2, 0xa640, 0xa642, 0xa644, 0xa646, 0xa648, 0xa64a, 0xa64c, 0xa64e,
0xa650, 0xa652, 0xa654, 0xa656, 0xa658, 0xa65a, 0xa65c, 0xa65e, 0xa660,
0xa662, 0xa664, 0xa666, 0xa668, 0xa66a, 0xa66c, 0xa680, 0xa682, 0xa684,
0xa686, 0xa688, 0xa68a, 0xa68c, 0xa68e, 0xa690, 0xa692, 0xa694, 0xa696,
0xa698, 0xa69a, 0xa722, 0xa724, 0xa726, 0xa728, 0xa72a, 0xa72c, 0xa72e,
0xa732, 0xa734, 0xa736, 0xa738, 0xa73a, 0xa73c, 0xa73e, 0xa740, 0xa742,
0xa744, 0xa746, 0xa748, 0xa74a, 0xa74c, 0xa74e, 0xa750, 0xa752, 0xa754,
0xa756, 0xa758, 0xa75a, 0xa75c, 0xa75e, 0xa760, 0xa762, 0xa764, 0xa766,
0xa768, 0xa76a, 0xa76c, 0xa76e, 0xa779, 0xa77b, 0xa77d, 0xa77e, 0xa780,
0xa782, 0xa784, 0xa786, 0xa78b, 0xa78d, 0xa790, 0xa792, 0xa796, 0xa798,
0xa79a, 0xa79c, 0xa79e, 0xa7a0, 0xa7a2, 0xa7a4, 0xa7a6, 0xa7a8, 0xa7b0,
0xa7b1
#if TCL_UTF_MAX > 4
,0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d504, 0x1d505, 0x1d538,
0x1d539, 0x1d546, 0x1d7ca
@@ -570,34 +595,34 @@ static const chr upperCharTable[] = {
*/
static const crange graphRangeTable[] = {
{0x21, 0x7e}, {0xa1, 0xac}, {0xae, 0x377}, {0x37a, 0x37e},
{0x384, 0x38a}, {0x38e, 0x3a1}, {0x3a3, 0x527}, {0x531, 0x556},
{0x559, 0x55f}, {0x561, 0x587}, {0x591, 0x5c7}, {0x5d0, 0x5ea},
{0x5f0, 0x5f4}, {0x606, 0x61b}, {0x61e, 0x6dc}, {0x6de, 0x70d},
{0x710, 0x74a}, {0x74d, 0x7b1}, {0x7c0, 0x7fa}, {0x800, 0x82d},
{0x830, 0x83e}, {0x840, 0x85b}, {0x8a2, 0x8ac}, {0x8e4, 0x8fe},
{0x900, 0x977}, {0x979, 0x97f}, {0x981, 0x983}, {0x985, 0x98c},
{0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9bc, 0x9c4},
{0x9cb, 0x9ce}, {0x9df, 0x9e3}, {0x9e6, 0x9fb}, {0xa01, 0xa03},
{0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa3e, 0xa42},
{0xa4b, 0xa4d}, {0xa59, 0xa5c}, {0xa66, 0xa75}, {0xa81, 0xa83},
{0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0},
{0xab5, 0xab9}, {0xabc, 0xac5}, {0xac7, 0xac9}, {0xacb, 0xacd},
{0xae0, 0xae3}, {0xae6, 0xaf1}, {0xb01, 0xb03}, {0xb05, 0xb0c},
{0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb3c, 0xb44},
{0xb4b, 0xb4d}, {0xb5f, 0xb63}, {0xb66, 0xb77}, {0xb85, 0xb8a},
{0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9},
{0xbbe, 0xbc2}, {0xbc6, 0xbc8}, {0xbca, 0xbcd}, {0xbe6, 0xbfa},
{0xc01, 0xc03}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28},
{0xc2a, 0xc33}, {0xc35, 0xc39}, {0xc3d, 0xc44}, {0xc46, 0xc48},
{0xc4a, 0xc4d}, {0xc60, 0xc63}, {0xc66, 0xc6f}, {0xc78, 0xc7f},
{0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3},
{0xcb5, 0xcb9}, {0xcbc, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd},
{0xce0, 0xce3}, {0xce6, 0xcef}, {0xd05, 0xd0c}, {0xd0e, 0xd10},
{0xd12, 0xd3a}, {0xd3d, 0xd44}, {0xd46, 0xd48}, {0xd4a, 0xd4e},
{0xd60, 0xd63}, {0xd66, 0xd75}, {0xd79, 0xd7f}, {0xd85, 0xd96},
{0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6}, {0xdcf, 0xdd4},
{0xdd8, 0xddf}, {0xdf2, 0xdf4}, {0xe01, 0xe3a}, {0xe3f, 0xe5b},
{0x21, 0x7e}, {0xa1, 0xac}, {0xae, 0x377}, {0x37a, 0x37f},
{0x384, 0x38a}, {0x38e, 0x3a1}, {0x3a3, 0x52f}, {0x531, 0x556},
{0x559, 0x55f}, {0x561, 0x587}, {0x58d, 0x58f}, {0x591, 0x5c7},
{0x5d0, 0x5ea}, {0x5f0, 0x5f4}, {0x606, 0x61b}, {0x61e, 0x6dc},
{0x6de, 0x70d}, {0x710, 0x74a}, {0x74d, 0x7b1}, {0x7c0, 0x7fa},
{0x800, 0x82d}, {0x830, 0x83e}, {0x840, 0x85b}, {0x8a0, 0x8b2},
{0x8e4, 0x983}, {0x985, 0x98c}, {0x993, 0x9a8}, {0x9aa, 0x9b0},
{0x9b6, 0x9b9}, {0x9bc, 0x9c4}, {0x9cb, 0x9ce}, {0x9df, 0x9e3},
{0x9e6, 0x9fb}, {0xa01, 0xa03}, {0xa05, 0xa0a}, {0xa13, 0xa28},
{0xa2a, 0xa30}, {0xa3e, 0xa42}, {0xa4b, 0xa4d}, {0xa59, 0xa5c},
{0xa66, 0xa75}, {0xa81, 0xa83}, {0xa85, 0xa8d}, {0xa8f, 0xa91},
{0xa93, 0xaa8}, {0xaaa, 0xab0}, {0xab5, 0xab9}, {0xabc, 0xac5},
{0xac7, 0xac9}, {0xacb, 0xacd}, {0xae0, 0xae3}, {0xae6, 0xaf1},
{0xb01, 0xb03}, {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30},
{0xb35, 0xb39}, {0xb3c, 0xb44}, {0xb4b, 0xb4d}, {0xb5f, 0xb63},
{0xb66, 0xb77}, {0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95},
{0xba8, 0xbaa}, {0xbae, 0xbb9}, {0xbbe, 0xbc2}, {0xbc6, 0xbc8},
{0xbca, 0xbcd}, {0xbe6, 0xbfa}, {0xc00, 0xc03}, {0xc05, 0xc0c},
{0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39}, {0xc3d, 0xc44},
{0xc46, 0xc48}, {0xc4a, 0xc4d}, {0xc60, 0xc63}, {0xc66, 0xc6f},
{0xc78, 0xc7f}, {0xc81, 0xc83}, {0xc85, 0xc8c}, {0xc8e, 0xc90},
{0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xcbc, 0xcc4},
{0xcc6, 0xcc8}, {0xcca, 0xccd}, {0xce0, 0xce3}, {0xce6, 0xcef},
{0xd01, 0xd03}, {0xd05, 0xd0c}, {0xd0e, 0xd10}, {0xd12, 0xd3a},
{0xd3d, 0xd44}, {0xd46, 0xd48}, {0xd4a, 0xd4e}, {0xd60, 0xd63},
{0xd66, 0xd75}, {0xd79, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1},
{0xdb3, 0xdbb}, {0xdc0, 0xdc6}, {0xdcf, 0xdd4}, {0xdd8, 0xddf},
{0xde6, 0xdef}, {0xdf2, 0xdf4}, {0xe01, 0xe3a}, {0xe3f, 0xe5b},
{0xe94, 0xe97}, {0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb9},
{0xebb, 0xebd}, {0xec0, 0xec4}, {0xec8, 0xecd}, {0xed0, 0xed9},
{0xedc, 0xedf}, {0xf00, 0xf47}, {0xf49, 0xf6c}, {0xf71, 0xf97},
@@ -606,105 +631,123 @@ static const crange graphRangeTable[] = {
{0x1260, 0x1288}, {0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5},
{0x12b8, 0x12be}, {0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310},
{0x1312, 0x1315}, {0x1318, 0x135a}, {0x135d, 0x137c}, {0x1380, 0x1399},
{0x13a0, 0x13f4}, {0x1400, 0x167f}, {0x1681, 0x169c}, {0x16a0, 0x16f0},
{0x13a0, 0x13f4}, {0x1400, 0x167f}, {0x1681, 0x169c}, {0x16a0, 0x16f8},
{0x1700, 0x170c}, {0x170e, 0x1714}, {0x1720, 0x1736}, {0x1740, 0x1753},
{0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17dd}, {0x17e0, 0x17e9},
{0x17f0, 0x17f9}, {0x1800, 0x180d}, {0x1810, 0x1819}, {0x1820, 0x1877},
{0x1880, 0x18aa}, {0x18b0, 0x18f5}, {0x1900, 0x191c}, {0x1920, 0x192b},
{0x1880, 0x18aa}, {0x18b0, 0x18f5}, {0x1900, 0x191e}, {0x1920, 0x192b},
{0x1930, 0x193b}, {0x1944, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab},
{0x19b0, 0x19c9}, {0x19d0, 0x19da}, {0x19de, 0x1a1b}, {0x1a1e, 0x1a5e},
{0x1a60, 0x1a7c}, {0x1a7f, 0x1a89}, {0x1a90, 0x1a99}, {0x1aa0, 0x1aad},
{0x1b00, 0x1b4b}, {0x1b50, 0x1b7c}, {0x1b80, 0x1bf3}, {0x1bfc, 0x1c37},
{0x1c3b, 0x1c49}, {0x1c4d, 0x1c7f}, {0x1cc0, 0x1cc7}, {0x1cd0, 0x1cf6},
{0x1d00, 0x1de6}, {0x1dfc, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45},
{0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4},
{0x1fb6, 0x1fc4}, {0x1fc6, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef},
{0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffe}, {0x2010, 0x2027}, {0x2030, 0x205e},
{0x2074, 0x208e}, {0x2090, 0x209c}, {0x20a0, 0x20ba}, {0x20d0, 0x20f0},
{0x2100, 0x2189}, {0x2190, 0x23f3}, {0x2400, 0x2426}, {0x2440, 0x244a},
{0x2460, 0x26ff}, {0x2701, 0x2b4c}, {0x2b50, 0x2b59}, {0x2c00, 0x2c2e},
{0x2c30, 0x2c5e}, {0x2c60, 0x2cf3}, {0x2cf9, 0x2d25}, {0x2d30, 0x2d67},
{0x2d7f, 0x2d96}, {0x2da0, 0x2da6}, {0x2da8, 0x2dae}, {0x2db0, 0x2db6},
{0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6}, {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6},
{0x2dd8, 0x2dde}, {0x2de0, 0x2e3b}, {0x2e80, 0x2e99}, {0x2e9b, 0x2ef3},
{0x2f00, 0x2fd5}, {0x2ff0, 0x2ffb}, {0x3001, 0x303f}, {0x3041, 0x3096},
{0x3099, 0x30ff}, {0x3105, 0x312d}, {0x3131, 0x318e}, {0x3190, 0x31ba},
{0x31c0, 0x31e3}, {0x31f0, 0x321e}, {0x3220, 0x32fe}, {0x3300, 0x4db5},
{0x4dc0, 0x9fcc}, {0xa000, 0xa48c}, {0xa490, 0xa4c6}, {0xa4d0, 0xa62b},
{0xa640, 0xa697}, {0xa69f, 0xa6f7}, {0xa700, 0xa78e}, {0xa790, 0xa793},
{0xa7a0, 0xa7aa}, {0xa7f8, 0xa82b}, {0xa830, 0xa839}, {0xa840, 0xa877},
{0xa880, 0xa8c4}, {0xa8ce, 0xa8d9}, {0xa8e0, 0xa8fb}, {0xa900, 0xa953},
{0xa95f, 0xa97c}, {0xa980, 0xa9cd}, {0xa9cf, 0xa9d9}, {0xaa00, 0xaa36},
{0xaa40, 0xaa4d}, {0xaa50, 0xaa59}, {0xaa5c, 0xaa7b}, {0xaa80, 0xaac2},
{0xaadb, 0xaaf6}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16},
{0xab20, 0xab26}, {0xab28, 0xab2e}, {0xabc0, 0xabed}, {0xabf0, 0xabf9},
{0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xf900, 0xfa6d},
{0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1d, 0xfb36},
{0xfb38, 0xfb3c}, {0xfb46, 0xfbc1}, {0xfbd3, 0xfd3f}, {0xfd50, 0xfd8f},
{0xfd92, 0xfdc7}, {0xfdf0, 0xfdfd}, {0xfe00, 0xfe19}, {0xfe20, 0xfe26},
{0xfe30, 0xfe52}, {0xfe54, 0xfe66}, {0xfe68, 0xfe6b}, {0xfe70, 0xfe74},
{0xfe76, 0xfefc}, {0xff01, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf},
{0xffd2, 0xffd7}, {0xffda, 0xffdc}, {0xffe0, 0xffe6}, {0xffe8, 0xffee}
{0x1ab0, 0x1abe}, {0x1b00, 0x1b4b}, {0x1b50, 0x1b7c}, {0x1b80, 0x1bf3},
{0x1bfc, 0x1c37}, {0x1c3b, 0x1c49}, {0x1c4d, 0x1c7f}, {0x1cc0, 0x1cc7},
{0x1cd0, 0x1cf6}, {0x1d00, 0x1df5}, {0x1dfc, 0x1f15}, {0x1f18, 0x1f1d},
{0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d},
{0x1f80, 0x1fb4}, {0x1fb6, 0x1fc4}, {0x1fc6, 0x1fd3}, {0x1fd6, 0x1fdb},
{0x1fdd, 0x1fef}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffe}, {0x2010, 0x2027},
{0x2030, 0x205e}, {0x2074, 0x208e}, {0x2090, 0x209c}, {0x20a0, 0x20bd},
{0x20d0, 0x20f0}, {0x2100, 0x2189}, {0x2190, 0x23fa}, {0x2400, 0x2426},
{0x2440, 0x244a}, {0x2460, 0x2b73}, {0x2b76, 0x2b95}, {0x2b98, 0x2bb9},
{0x2bbd, 0x2bc8}, {0x2bca, 0x2bd1}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e},
{0x2c60, 0x2cf3}, {0x2cf9, 0x2d25}, {0x2d30, 0x2d67}, {0x2d7f, 0x2d96},
{0x2da0, 0x2da6}, {0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe},
{0x2dc0, 0x2dc6}, {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde},
{0x2de0, 0x2e42}, {0x2e80, 0x2e99}, {0x2e9b, 0x2ef3}, {0x2f00, 0x2fd5},
{0x2ff0, 0x2ffb}, {0x3001, 0x303f}, {0x3041, 0x3096}, {0x3099, 0x30ff},
{0x3105, 0x312d}, {0x3131, 0x318e}, {0x3190, 0x31ba}, {0x31c0, 0x31e3},
{0x31f0, 0x321e}, {0x3220, 0x32fe}, {0x3300, 0x4db5}, {0x4dc0, 0x9fcc},
{0xa000, 0xa48c}, {0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa69d},
{0xa69f, 0xa6f7}, {0xa700, 0xa78e}, {0xa790, 0xa7ad}, {0xa7f7, 0xa82b},
{0xa830, 0xa839}, {0xa840, 0xa877}, {0xa880, 0xa8c4}, {0xa8ce, 0xa8d9},
{0xa8e0, 0xa8fb}, {0xa900, 0xa953}, {0xa95f, 0xa97c}, {0xa980, 0xa9cd},
{0xa9cf, 0xa9d9}, {0xa9de, 0xa9fe}, {0xaa00, 0xaa36}, {0xaa40, 0xaa4d},
{0xaa50, 0xaa59}, {0xaa5c, 0xaac2}, {0xaadb, 0xaaf6}, {0xab01, 0xab06},
{0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e},
{0xab30, 0xab5f}, {0xabc0, 0xabed}, {0xabf0, 0xabf9}, {0xac00, 0xd7a3},
{0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xdc00, 0xdc3e}, {0xdc40, 0xdc7e},
{0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe}, {0xdd80, 0xddbe}, {0xddc0, 0xddfe},
{0xde80, 0xdebe}, {0xdec0, 0xdefe}, {0xdf00, 0xdf3e}, {0xdf40, 0xdf7e},
{0xf900, 0xfa6d}, {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17},
{0xfb1d, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbc1}, {0xfbd3, 0xfd3f},
{0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfd}, {0xfe00, 0xfe19},
{0xfe20, 0xfe2d}, {0xfe30, 0xfe52}, {0xfe54, 0xfe66}, {0xfe68, 0xfe6b},
{0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff01, 0xffbe}, {0xffc2, 0xffc7},
{0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc}, {0xffe0, 0xffe6},
{0xffe8, 0xffee}
#if TCL_UTF_MAX > 4
,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d},
{0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10100, 0x10102}, {0x10107, 0x10133},
{0x10137, 0x1018a}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c},
{0x102a0, 0x102d0}, {0x10300, 0x1031e}, {0x10320, 0x10323}, {0x10330, 0x1034a},
{0x10380, 0x1039d}, {0x1039f, 0x103c3}, {0x103c8, 0x103d5}, {0x10400, 0x1049d},
{0x104a0, 0x104a9}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855},
{0x10857, 0x1085f}, {0x10900, 0x1091b}, {0x1091f, 0x10939}, {0x10980, 0x109b7},
{0x10a00, 0x10a03}, {0x10a0c, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33},
{0x10a38, 0x10a3a}, {0x10a3f, 0x10a47}, {0x10a50, 0x10a58}, {0x10a60, 0x10a7f},
{0x10b00, 0x10b35}, {0x10b39, 0x10b55}, {0x10b58, 0x10b72}, {0x10b78, 0x10b7f},
{0x10c00, 0x10c48}, {0x10e60, 0x10e7e}, {0x11000, 0x1104d}, {0x11052, 0x1106f},
{0x11080, 0x110bc}, {0x110be, 0x110c1}, {0x110d0, 0x110e8}, {0x110f0, 0x110f9},
{0x11100, 0x11134}, {0x11136, 0x11143}, {0x11180, 0x111c8}, {0x111d0, 0x111d9},
{0x11680, 0x116b7}, {0x116c0, 0x116c9}, {0x12000, 0x1236e}, {0x12400, 0x12462},
{0x12470, 0x12473}, {0x13000, 0x1342e}, {0x16800, 0x16a38}, {0x16f00, 0x16f44},
{0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f}, {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126},
{0x1d129, 0x1d172}, {0x1d17b, 0x1d1dd}, {0x1d200, 0x1d245}, {0x1d300, 0x1d356},
{0x1d360, 0x1d371}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
{0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a},
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e},
{0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb},
{0x1d7ce, 0x1d7ff}, {0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32},
{0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72},
{0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b},
{0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b},
{0x1f030, 0x1f093}, {0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0be}, {0x1f0c1, 0x1f0cf},
{0x1f0d1, 0x1f0df}, {0x1f100, 0x1f10a}, {0x1f110, 0x1f12e}, {0x1f130, 0x1f16b},
{0x1f170, 0x1f19a}, {0x1f1e6, 0x1f202}, {0x1f210, 0x1f23a}, {0x1f240, 0x1f248},
{0x1f300, 0x1f320}, {0x1f330, 0x1f335}, {0x1f337, 0x1f37c}, {0x1f380, 0x1f393},
{0x1f3a0, 0x1f3c4}, {0x1f3c6, 0x1f3ca}, {0x1f3e0, 0x1f3f0}, {0x1f400, 0x1f43e},
{0x1f442, 0x1f4f7}, {0x1f4f9, 0x1f4fc}, {0x1f500, 0x1f53d}, {0x1f540, 0x1f543},
{0x1f550, 0x1f567}, {0x1f5fb, 0x1f640}, {0x1f645, 0x1f64f}, {0x1f680, 0x1f6c5},
{0x1f700, 0x1f773}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d},
{0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef}
{0x10137, 0x1018c}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c},
{0x102a0, 0x102d0}, {0x102e0, 0x102fb}, {0x10300, 0x10323}, {0x10330, 0x1034a},
{0x10350, 0x1037a}, {0x10380, 0x1039d}, {0x1039f, 0x103c3}, {0x103c8, 0x103d5},
{0x10400, 0x1049d}, {0x104a0, 0x104a9}, {0x10500, 0x10527}, {0x10530, 0x10563},
{0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805},
{0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10857, 0x1089e}, {0x108a7, 0x108af},
{0x10900, 0x1091b}, {0x1091f, 0x10939}, {0x10980, 0x109b7}, {0x10a00, 0x10a03},
{0x10a0c, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33}, {0x10a38, 0x10a3a},
{0x10a3f, 0x10a47}, {0x10a50, 0x10a58}, {0x10a60, 0x10a9f}, {0x10ac0, 0x10ae6},
{0x10aeb, 0x10af6}, {0x10b00, 0x10b35}, {0x10b39, 0x10b55}, {0x10b58, 0x10b72},
{0x10b78, 0x10b91}, {0x10b99, 0x10b9c}, {0x10ba9, 0x10baf}, {0x10c00, 0x10c48},
{0x10e60, 0x10e7e}, {0x11000, 0x1104d}, {0x11052, 0x1106f}, {0x1107f, 0x110bc},
{0x110be, 0x110c1}, {0x110d0, 0x110e8}, {0x110f0, 0x110f9}, {0x11100, 0x11134},
{0x11136, 0x11143}, {0x11150, 0x11176}, {0x11180, 0x111c8}, {0x111d0, 0x111da},
{0x111e1, 0x111f4}, {0x11200, 0x11211}, {0x11213, 0x1123d}, {0x112b0, 0x112ea},
{0x112f0, 0x112f9}, {0x11301, 0x11303}, {0x11305, 0x1130c}, {0x11313, 0x11328},
{0x1132a, 0x11330}, {0x11335, 0x11339}, {0x1133c, 0x11344}, {0x1134b, 0x1134d},
{0x1135d, 0x11363}, {0x11366, 0x1136c}, {0x11370, 0x11374}, {0x11480, 0x114c7},
{0x114d0, 0x114d9}, {0x11580, 0x115b5}, {0x115b8, 0x115c9}, {0x11600, 0x11644},
{0x11650, 0x11659}, {0x11680, 0x116b7}, {0x116c0, 0x116c9}, {0x118a0, 0x118f2},
{0x11ac0, 0x11af8}, {0x12000, 0x12398}, {0x12400, 0x1246e}, {0x12470, 0x12474},
{0x13000, 0x1342e}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e}, {0x16a60, 0x16a69},
{0x16ad0, 0x16aed}, {0x16af0, 0x16af5}, {0x16b00, 0x16b45}, {0x16b50, 0x16b59},
{0x16b5b, 0x16b61}, {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f}, {0x16f00, 0x16f44},
{0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c},
{0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99}, {0x1bc9c, 0x1bc9f}, {0x1d000, 0x1d0f5},
{0x1d100, 0x1d126}, {0x1d129, 0x1d172}, {0x1d17b, 0x1d1dd}, {0x1d200, 0x1d245},
{0x1d300, 0x1d356}, {0x1d360, 0x1d371}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c},
{0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505},
{0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539},
{0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5},
{0x1d6a8, 0x1d7cb}, {0x1d7ce, 0x1d7ff}, {0x1e800, 0x1e8c4}, {0x1e8c7, 0x1e8d6},
{0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37},
{0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77},
{0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3},
{0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b}, {0x1f030, 0x1f093},
{0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5},
{0x1f100, 0x1f10c}, {0x1f110, 0x1f12e}, {0x1f130, 0x1f16b}, {0x1f170, 0x1f19a},
{0x1f1e6, 0x1f202}, {0x1f210, 0x1f23a}, {0x1f240, 0x1f248}, {0x1f300, 0x1f32c},
{0x1f330, 0x1f37d}, {0x1f380, 0x1f3ce}, {0x1f3d4, 0x1f3f7}, {0x1f400, 0x1f4fe},
{0x1f500, 0x1f54a}, {0x1f550, 0x1f579}, {0x1f57b, 0x1f5a3}, {0x1f5a5, 0x1f642},
{0x1f645, 0x1f6cf}, {0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6f3}, {0x1f700, 0x1f773},
{0x1f780, 0x1f7d4}, {0x1f800, 0x1f80b}, {0x1f810, 0x1f847}, {0x1f850, 0x1f859},
{0x1f860, 0x1f887}, {0x1f890, 0x1f8ad}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734},
{0x2b740, 0x2b81d}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef}
#endif
};
#define NUM_GRAPH_RANGE (sizeof(graphRangeTable)/sizeof(crange))
static const chr graphCharTable[] = {
0x38c, 0x589, 0x58a, 0x58f, 0x85e, 0x8a0, 0x98f, 0x990, 0x9b2,
0x9c7, 0x9c8, 0x9d7, 0x9dc, 0x9dd, 0xa0f, 0xa10, 0xa32, 0xa33,
0xa35, 0xa36, 0xa38, 0xa39, 0xa3c, 0xa47, 0xa48, 0xa51, 0xa5e,
0xab2, 0xab3, 0xad0, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb47, 0xb48,
0xb56, 0xb57, 0xb5c, 0xb5d, 0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c,
0xb9e, 0xb9f, 0xba3, 0xba4, 0xbd0, 0xbd7, 0xc55, 0xc56, 0xc58,
0xc59, 0xc82, 0xc83, 0xcd5, 0xcd6, 0xcde, 0xcf1, 0xcf2, 0xd02,
0xd03, 0xd57, 0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6, 0xe81, 0xe82,
0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab,
0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940, 0x1f59,
0x1f5b, 0x1f5d, 0x2070, 0x2071, 0x2d27, 0x2d2d, 0x2d6f, 0x2d70, 0xa9de,
0xa9df, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc, 0xfffd
0x38c, 0x589, 0x58a, 0x85e, 0x98f, 0x990, 0x9b2, 0x9c7, 0x9c8,
0x9d7, 0x9dc, 0x9dd, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36,
0xa38, 0xa39, 0xa3c, 0xa47, 0xa48, 0xa51, 0xa5e, 0xab2, 0xab3,
0xad0, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb47, 0xb48, 0xb56, 0xb57,
0xb5c, 0xb5d, 0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f,
0xba3, 0xba4, 0xbd0, 0xbd7, 0xc55, 0xc56, 0xc58, 0xc59, 0xcd5,
0xcd6, 0xcde, 0xcf1, 0xcf2, 0xd57, 0xd82, 0xd83, 0xdbd, 0xdca,
0xdd6, 0xe81, 0xe82, 0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5,
0xea7, 0xeaa, 0xeab, 0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772,
0x1773, 0x1940, 0x1cf8, 0x1cf9, 0x1f59, 0x1f5b, 0x1f5d, 0x2070, 0x2071,
0x2d27, 0x2d2d, 0x2d6f, 0x2d70, 0xa7b0, 0xa7b1, 0xab64, 0xab65, 0xfb3e,
0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc, 0xfffd
#if TCL_UTF_MAX > 4
,0x1003c, 0x1003d, 0x10808, 0x10837, 0x10838, 0x1083c, 0x1093f, 0x109be, 0x109bf,
0x10a05, 0x10a06, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6,
0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42,
0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b,
0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e, 0x1eef0, 0x1eef1, 0x1f250,
0x1f251, 0x1f440
,0x1003c, 0x1003d, 0x101a0, 0x1056f, 0x10808, 0x10837, 0x10838, 0x1083c, 0x1093f,
0x109be, 0x109bf, 0x10a05, 0x10a06, 0x111cd, 0x1130f, 0x11310, 0x11332, 0x11333,
0x11347, 0x11348, 0x11357, 0x118ff, 0x16a6e, 0x16a6f, 0x1b000, 0x1b001, 0x1d49e,
0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, 0x1ee24,
0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52,
0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64,
0x1ee7e, 0x1eef0, 0x1eef1, 0x1f250, 0x1f251
#endif
};
+1 -1
View File
@@ -1345,7 +1345,7 @@ fixempties(
for (s = nfa->states; s != NULL && !NISERR(); s = nexts) {
nexts = s->next;
/* Ensure tmp fields are clear for next step */
assert(s->tmp = NULL);
assert(s->tmp == NULL);
if (s->flag || s->nins != 1) {
continue;
}
+25 -22
View File
@@ -56,10 +56,10 @@ extern "C" {
#define TCL_MAJOR_VERSION 8
#define TCL_MINOR_VERSION 6
#define TCL_RELEASE_LEVEL TCL_FINAL_RELEASE
#define TCL_RELEASE_SERIAL 1
#define TCL_RELEASE_SERIAL 2
#define TCL_VERSION "8.6"
#define TCL_PATCH_LEVEL "8.6.1"
#define TCL_PATCH_LEVEL "8.6.2"
/*
*----------------------------------------------------------------------------
@@ -67,15 +67,12 @@ extern "C" {
* We use this method because there is no autoconf equivalent.
*/
#ifndef __WIN32__
# if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__) || defined(__BORLANDC__) || (defined(__WATCOMC__) && defined(__WINDOWS_386__))
#ifdef _WIN32
# ifndef __WIN32__
# define __WIN32__
# ifndef WIN32
# define WIN32
# endif
# ifndef _WIN32
# define _WIN32
# endif
# endif
# ifndef WIN32
# define WIN32
# endif
#endif
@@ -83,11 +80,11 @@ extern "C" {
* STRICT: See MSDN Article Q83456
*/
#ifdef __WIN32__
#ifdef _WIN32
# ifndef STRICT
# define STRICT
# endif
#endif /* __WIN32__ */
#endif /* _WIN32 */
/*
* Utility macros: STRINGIFY takes an argument and wraps it in "" (double
@@ -191,7 +188,7 @@ extern "C" {
* MSVCRT.
*/
#if (defined(__WIN32__) && (defined(_MSC_VER) || (__BORLANDC__ >= 0x0550) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec))))
#if (defined(_WIN32) && (defined(_MSC_VER) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0550)) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec))))
# define HAVE_DECLSPEC 1
# ifdef STATIC_BUILD
# define DLLIMPORT
@@ -315,14 +312,14 @@ extern "C" {
* VOID. This block is skipped under Cygwin and Mingw.
*/
#if defined(__WIN32__) && !defined(HAVE_WINNT_IGNORE_VOID)
#if defined(_WIN32) && !defined(HAVE_WINNT_IGNORE_VOID)
#ifndef VOID
#define VOID void
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
#endif
#endif /* __WIN32__ && !HAVE_WINNT_IGNORE_VOID */
#endif /* _WIN32 && !HAVE_WINNT_IGNORE_VOID */
/*
* Macro to use instead of "void" for arguments that must have type "void *"
@@ -390,7 +387,7 @@ typedef long LONG;
*/
#if !defined(TCL_WIDE_INT_TYPE)&&!defined(TCL_WIDE_INT_IS_LONG)
# if defined(__WIN32__)
# if defined(_WIN32)
# define TCL_WIDE_INT_TYPE __int64
# ifdef __BORLANDC__
# define TCL_LL_MODIFIER "L"
@@ -400,7 +397,7 @@ typedef long LONG;
# elif defined(__GNUC__)
# define TCL_WIDE_INT_TYPE long long
# define TCL_LL_MODIFIER "ll"
# else /* ! __WIN32__ && ! __GNUC__ */
# else /* ! _WIN32 && ! __GNUC__ */
/*
* Don't know what platform it is and configure hasn't discovered what is
* going on for us. Try to guess...
@@ -415,7 +412,7 @@ typedef long LONG;
# define TCL_WIDE_INT_TYPE long long
# endif
# endif /* NO_LIMITS_H */
# endif /* __WIN32__ */
# endif /* _WIN32 */
#endif /* !TCL_WIDE_INT_TYPE & !TCL_WIDE_INT_IS_LONG */
#ifdef TCL_WIDE_INT_IS_LONG
# undef TCL_WIDE_INT_TYPE
@@ -447,7 +444,7 @@ typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
# define Tcl_DoubleAsWide(val) ((Tcl_WideInt)((double)(val)))
#endif /* TCL_WIDE_INT_IS_LONG */
#if defined(__WIN32__)
#if defined(_WIN32)
# ifdef __BORLANDC__
typedef struct stati64 Tcl_StatBuf;
# elif defined(_WIN64)
@@ -562,7 +559,7 @@ typedef struct Tcl_ZLibStream_ *Tcl_ZlibStream;
* will be called as the main fuction of the new thread created by that call.
*/
#if defined __WIN32__
#if defined _WIN32
typedef unsigned (__stdcall Tcl_ThreadCreateProc) (ClientData clientData);
#else
typedef void (Tcl_ThreadCreateProc) (ClientData clientData);
@@ -574,7 +571,7 @@ typedef void (Tcl_ThreadCreateProc) (ClientData clientData);
* in generic/tclThreadTest.c for it's usage.
*/
#if defined __WIN32__
#if defined _WIN32
# define Tcl_ThreadCreateType unsigned __stdcall
# define TCL_THREAD_CREATE_RETURN return 0
#else
@@ -2436,9 +2433,15 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
/*
* Include platform specific public function declarations that are accessible
* via the stubs table.
* via the stubs table. Make all TclOO symbols MODULE_SCOPE (which only
* has effect on building it as a shared library). See ticket [3010352].
*/
#if defined(BUILD_tcl)
# undef TCLAPI
# define TCLAPI MODULE_SCOPE
#endif
#include "tclPlatDecls.h"
/*
+17 -7
View File
@@ -26,6 +26,7 @@
*- jumpTable testing
*- syntax (?)
*- returnCodeBranch
*- tclooNext, tclooNextClass
*/
#include "tclInt.h"
@@ -49,7 +50,7 @@ typedef enum BasicBlockCatchState {
BBCS_UNKNOWN = 0, /* Catch context has not yet been identified */
BBCS_NONE, /* Block is outside of any catch */
BBCS_INCATCH, /* Block is within a catch context */
BBCS_CAUGHT, /* Block is within a catch context and
BBCS_CAUGHT /* Block is within a catch context and
* may be executed after an exception fires */
} BasicBlockCatchState;
@@ -120,7 +121,7 @@ enum BasicBlockFlags {
* marking it as the start of a 'catch'
* sequence. The 'jumpTarget' is the exception
* exit from the catch block. */
BB_ENDCATCH = (1 << 5), /* Block ends with an 'endCatch' instruction,
BB_ENDCATCH = (1 << 5) /* Block ends with an 'endCatch' instruction,
* unwinding the catch from the exception
* stack. */
};
@@ -183,7 +184,7 @@ typedef enum TalInstType {
* produces N */
ASSEM_SINT1, /* One 1-byte signed-integer operand
* (INCR_STK_IMM) */
ASSEM_SINT4_LVT4, /* Signed 4-byte integer operand followed by
ASSEM_SINT4_LVT4 /* Signed 4-byte integer operand followed by
* LVT entry. Fixed arity */
} TalInstType;
@@ -409,6 +410,10 @@ static const TalInstDesc TalInstructionTable[] = {
{"lappendArray", ASSEM_LVT, (INST_LAPPEND_ARRAY1<<8
| INST_LAPPEND_ARRAY4),2, 1},
{"lappendArrayStk", ASSEM_1BYTE, INST_LAPPEND_ARRAY_STK, 3, 1},
{"lappendList", ASSEM_LVT4, INST_LAPPEND_LIST, 1, 1},
{"lappendListArray",ASSEM_LVT4, INST_LAPPEND_LIST_ARRAY,2, 1},
{"lappendListArrayStk", ASSEM_1BYTE,INST_LAPPEND_LIST_ARRAY_STK, 3, 1},
{"lappendListStk", ASSEM_1BYTE, INST_LAPPEND_LIST_STK, 2, 1},
{"lappendStk", ASSEM_1BYTE, INST_LAPPEND_STK, 2, 1},
{"le", ASSEM_1BYTE, INST_LE, 2, 1},
{"lindexMulti", ASSEM_LINDEX_MULTI,
@@ -437,6 +442,8 @@ static const TalInstDesc TalInstructionTable[] = {
{"nop", ASSEM_1BYTE, INST_NOP, 0, 0},
{"not", ASSEM_1BYTE, INST_LNOT, 1, 1},
{"nsupvar", ASSEM_LVT4, INST_NSUPVAR, 2, 1},
{"numericType", ASSEM_1BYTE, INST_NUM_TYPE, 1, 1},
{"originCmd", ASSEM_1BYTE, INST_ORIGIN_COMMAND, 1, 1},
{"over", ASSEM_OVER, INST_OVER, INT_MIN,-1-1},
{"pop", ASSEM_1BYTE, INST_POP, 1, 0},
{"pushReturnCode", ASSEM_1BYTE, INST_PUSH_RETURN_CODE, 0, 1},
@@ -453,9 +460,9 @@ static const TalInstDesc TalInstructionTable[] = {
| INST_STORE_ARRAY4), 2, 1},
{"storeArrayStk", ASSEM_1BYTE, INST_STORE_ARRAY_STK, 3, 1},
{"storeStk", ASSEM_1BYTE, INST_STORE_STK, 2, 1},
{"strLower", ASSEM_1BYTE, INST_STR_LOWER, 1, 1},
{"strTitle", ASSEM_1BYTE, INST_STR_TITLE, 1, 1},
{"strUpper", ASSEM_1BYTE, INST_STR_UPPER, 1, 1},
{"strcaseLower", ASSEM_1BYTE, INST_STR_LOWER, 1, 1},
{"strcaseTitle", ASSEM_1BYTE, INST_STR_TITLE, 1, 1},
{"strcaseUpper", ASSEM_1BYTE, INST_STR_UPPER, 1, 1},
{"strcmp", ASSEM_1BYTE, INST_STR_CMP, 2, 1},
{"strcat", ASSEM_CONCAT1, INST_STR_CONCAT1, INT_MIN,1},
{"streq", ASSEM_1BYTE, INST_STR_EQ, 2, 1},
@@ -466,6 +473,7 @@ static const TalInstDesc TalInstructionTable[] = {
{"strmatch", ASSEM_BOOL, INST_STR_MATCH, 2, 1},
{"strneq", ASSEM_1BYTE, INST_STR_NEQ, 2, 1},
{"strrange", ASSEM_1BYTE, INST_STR_RANGE, 3, 1},
{"strreplace", ASSEM_1BYTE, INST_STR_REPLACE, 4, 1},
{"strrfind", ASSEM_1BYTE, INST_STR_FIND_LAST, 2, 1},
{"strtrim", ASSEM_1BYTE, INST_STR_TRIM, 2, 1},
{"strtrimLeft", ASSEM_1BYTE, INST_STR_TRIM_LEFT, 2, 1},
@@ -475,6 +483,7 @@ static const TalInstDesc TalInstructionTable[] = {
{"tclooIsObject", ASSEM_1BYTE, INST_TCLOO_IS_OBJECT, 1, 1},
{"tclooNamespace", ASSEM_1BYTE, INST_TCLOO_NS, 1, 1},
{"tclooSelf", ASSEM_1BYTE, INST_TCLOO_SELF, 0, 1},
{"tryCvtToBoolean", ASSEM_1BYTE, INST_TRY_CVT_TO_BOOLEAN,1, 2},
{"tryCvtToNumeric", ASSEM_1BYTE, INST_TRY_CVT_TO_NUMERIC,1, 1},
{"uminus", ASSEM_1BYTE, INST_UMINUS, 1, 1},
{"unset", ASSEM_BOOL_LVT4,INST_UNSET_SCALAR, 0, 0},
@@ -514,7 +523,8 @@ static const unsigned char NonThrowingByteCodes[] = {
INST_RESOLVE_COMMAND, /* 154 */
INST_STR_TRIM, INST_STR_TRIM_LEFT, INST_STR_TRIM_RIGHT, /* 166-168 */
INST_CONCAT_STK, /* 169 */
INST_STR_UPPER, INST_STR_LOWER, INST_STR_TITLE /* 170-172 */
INST_STR_UPPER, INST_STR_LOWER, INST_STR_TITLE, /* 170-172 */
INST_NUM_TYPE /* 180 */
};
/*
+40 -24
View File
@@ -259,7 +259,7 @@ static const CmdInfo builtInCmds[] = {
{"variable", Tcl_VariableObjCmd, TclCompileVariableCmd, NULL, CMD_IS_SAFE},
{"while", Tcl_WhileObjCmd, TclCompileWhileCmd, TclNRWhileObjCmd, CMD_IS_SAFE},
{"yield", NULL, TclCompileYieldCmd, TclNRYieldObjCmd, CMD_IS_SAFE},
{"yieldto", NULL, NULL, TclNRYieldToObjCmd, CMD_IS_SAFE},
{"yieldto", NULL, TclCompileYieldToCmd, TclNRYieldToObjCmd, CMD_IS_SAFE},
/*
* Commands in the OS-interface. Note that many of these are unsafe.
@@ -843,6 +843,8 @@ Tcl_CreateInterp(void)
Tcl_DisassembleObjCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "::tcl::unsupported::representation",
Tcl_RepresentationCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "::tcl::unsupported::gc",
Tcl_GcCmd, NULL, NULL);
/* Adding the bytecode assembler command */
cmdPtr = (Command *) Tcl_NRCreateCommand(interp,
@@ -2085,10 +2087,19 @@ Tcl_CreateCommand(
*/
cmdPtr = Tcl_GetHashValue(hPtr);
oldRefPtr = cmdPtr->importRefPtr;
cmdPtr->importRefPtr = NULL;
cmdPtr->refCount++;
if (cmdPtr->importRefPtr) {
cmdPtr->flags |= CMD_REDEF_IN_PROGRESS;
}
Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
if (cmdPtr->flags & CMD_REDEF_IN_PROGRESS) {
oldRefPtr = cmdPtr->importRefPtr;
cmdPtr->importRefPtr = NULL;
}
TclCleanupCommandMacro(cmdPtr);
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
if (!isNew) {
/*
@@ -2272,10 +2283,19 @@ Tcl_CreateObjCommand(
* intact.
*/
oldRefPtr = cmdPtr->importRefPtr;
cmdPtr->importRefPtr = NULL;
cmdPtr->refCount++;
if (cmdPtr->importRefPtr) {
cmdPtr->flags |= CMD_REDEF_IN_PROGRESS;
}
Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
if (cmdPtr->flags & CMD_REDEF_IN_PROGRESS) {
oldRefPtr = cmdPtr->importRefPtr;
cmdPtr->importRefPtr = NULL;
}
TclCleanupCommandMacro(cmdPtr);
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
if (!isNew) {
/*
@@ -3117,12 +3137,13 @@ Tcl_DeleteCommandFromToken(
* commands were created that refer back to this command. Delete these
* imported commands now.
*/
for (refPtr = cmdPtr->importRefPtr; refPtr != NULL;
refPtr = nextRefPtr) {
nextRefPtr = refPtr->nextPtr;
importCmd = (Tcl_Command) refPtr->importedCmdPtr;
Tcl_DeleteCommandFromToken(interp, importCmd);
if (!(cmdPtr->flags & CMD_REDEF_IN_PROGRESS)) {
for (refPtr = cmdPtr->importRefPtr; refPtr != NULL;
refPtr = nextRefPtr) {
nextRefPtr = refPtr->nextPtr;
importCmd = (Tcl_Command) refPtr->importedCmdPtr;
Tcl_DeleteCommandFromToken(interp, importCmd);
}
}
/*
@@ -8416,8 +8437,7 @@ TclNRYieldToObjCmd(
{
CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;
Tcl_Obj *listPtr, *nsObjPtr;
Tcl_Namespace *nsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
Tcl_Namespace *ns1Ptr;
Tcl_Namespace *nsPtr = TclGetCurrentNamespace(interp);
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "command ?arg ...?");
@@ -8431,11 +8451,13 @@ TclNRYieldToObjCmd(
return TCL_ERROR;
}
/*
* Add the tailcall in the caller env, then just yield.
*
* This is essentially code from TclNRTailcallObjCmd
*/
if (((Namespace *) nsPtr)->flags & NS_DYING) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"yieldto called in deleted namespace", -1));
Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "YIELDTO_IN_DELETED",
NULL);
return TCL_ERROR;
}
/*
* Add the tailcall in the caller env, then just yield.
@@ -8444,15 +8466,9 @@ TclNRYieldToObjCmd(
*/
listPtr = Tcl_NewListObj(objc, objv);
nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1);
if ((TCL_OK != TclGetNamespaceFromObj(interp, nsObjPtr, &ns1Ptr))
|| (nsPtr != ns1Ptr)) {
Tcl_Panic("yieldto failed to find the proper namespace");
}
TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
/*
* Add the callback in the caller's env, then instruct TEBC to yield.
*/
+33 -41
View File
@@ -610,9 +610,7 @@ UpdateStringOfByteArray(
*
* This function appends an array of bytes to a byte array object. Note
* that the object *must* be unshared, and the array of bytes *must not*
* refer to the object being appended to. Also the caller must have
* already checked that the final length of the bytearray after the
* append operations is complete will not overflow the int range.
* refer to the object being appended to.
*
* Results:
* None.
@@ -631,6 +629,7 @@ TclAppendBytesToByteArray(
int len)
{
ByteArray *byteArrayPtr;
int needed;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object","TclAppendBytesToByteArray");
@@ -639,64 +638,57 @@ TclAppendBytesToByteArray(
Tcl_Panic("%s must be called with definite number of bytes to append",
"TclAppendBytesToByteArray");
}
if (len == 0) {
/* Append zero bytes is a no-op. */
return;
}
if (objPtr->typePtr != &tclByteArrayType) {
SetByteArrayFromAny(NULL, objPtr);
}
byteArrayPtr = GET_BYTEARRAY(objPtr);
if (len > INT_MAX - byteArrayPtr->used) {
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
}
needed = byteArrayPtr->used + len;
/*
* If we need to, resize the allocated space in the byte array.
*/
if (byteArrayPtr->used + len > byteArrayPtr->allocated) {
unsigned int attempt, used = byteArrayPtr->used;
ByteArray *tmpByteArrayPtr = NULL;
if (needed > byteArrayPtr->allocated) {
ByteArray *ptr = NULL;
int attempt;
attempt = byteArrayPtr->allocated;
if (attempt < 1) {
/*
* No allocated bytes, so must be none used too. We use this
* method to calculate how many bytes to allocate because we can
* end up with a zero-length buffer otherwise, when doubling can
* cause trouble. [Bug 3067036]
*/
attempt = len + 1;
} else {
do {
attempt *= 2;
} while (attempt < used+len);
if (needed <= INT_MAX/2) {
/* Try to allocate double the total space that is needed. */
attempt = 2 * needed;
ptr = attemptckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
}
if (ptr == NULL) {
/* Try to allocate double the increment that is needed (plus). */
unsigned int limit = INT_MAX - needed;
unsigned int extra = len + TCL_MIN_GROWTH;
int growth = (int) ((extra > limit) ? limit : extra);
if (BYTEARRAY_SIZE(attempt) > BYTEARRAY_SIZE(used)) {
tmpByteArrayPtr = attemptckrealloc(byteArrayPtr,
BYTEARRAY_SIZE(attempt));
attempt = needed + growth;
ptr = attemptckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
}
if (tmpByteArrayPtr == NULL) {
attempt = used + len;
if (BYTEARRAY_SIZE(attempt) < BYTEARRAY_SIZE(used)) {
Tcl_Panic("attempt to allocate a bigger buffer than we can handle");
}
tmpByteArrayPtr = ckrealloc(byteArrayPtr,
BYTEARRAY_SIZE(attempt));
if (ptr == NULL) {
/* Last chance: Try to allocate exactly what is needed. */
attempt = needed;
ptr = ckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
}
byteArrayPtr = tmpByteArrayPtr;
byteArrayPtr = ptr;
byteArrayPtr->allocated = attempt;
byteArrayPtr->used = used;
SET_BYTEARRAY(objPtr, byteArrayPtr);
}
/*
* Do the append if there's any point.
*/
if (len > 0) {
if (bytes) {
memcpy(byteArrayPtr->bytes + byteArrayPtr->used, bytes, len);
byteArrayPtr->used += len;
TclInvalidateStringRep(objPtr);
}
byteArrayPtr->used += len;
TclInvalidateStringRep(objPtr);
}
/*
+58 -30
View File
@@ -19,7 +19,7 @@
* Windows has mktime. The configurators do not check.
*/
#ifdef __WIN32__
#ifdef _WIN32
#define HAVE_MKTIME 1
#endif
@@ -521,6 +521,46 @@ ClockGetdatefieldsObjCmd(
*----------------------------------------------------------------------
*/
static int
FetchEraField(
Tcl_Interp *interp,
Tcl_Obj *dict,
Tcl_Obj *key,
int *storePtr)
{
Tcl_Obj *value = NULL;
if (Tcl_DictObjGet(interp, dict, key, &value) != TCL_OK) {
return TCL_ERROR;
}
if (value == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"expected key(s) not found in dictionary", -1));
return TCL_ERROR;
}
return Tcl_GetIndexFromObj(interp, value, eras, "era", TCL_EXACT, storePtr);
}
static int
FetchIntField(
Tcl_Interp *interp,
Tcl_Obj *dict,
Tcl_Obj *key,
int *storePtr)
{
Tcl_Obj *value = NULL;
if (Tcl_DictObjGet(interp, dict, key, &value) != TCL_OK) {
return TCL_ERROR;
}
if (value == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"expected key(s) not found in dictionary", -1));
return TCL_ERROR;
}
return TclGetIntFromObj(interp, value, storePtr);
}
static int
ClockGetjuliandayfromerayearmonthdayObjCmd(
ClientData clientData, /* Opaque pointer to literal pool, etc. */
@@ -532,7 +572,6 @@ ClockGetjuliandayfromerayearmonthdayObjCmd(
Tcl_Obj *dict;
ClockClientData *data = clientData;
Tcl_Obj *const *literals = data->literals;
Tcl_Obj *fieldPtr;
int changeover;
int copied = 0;
int status;
@@ -547,18 +586,13 @@ ClockGetjuliandayfromerayearmonthdayObjCmd(
return TCL_ERROR;
}
dict = objv[1];
if (Tcl_DictObjGet(interp, dict, literals[LIT_ERA], &fieldPtr) != TCL_OK
|| Tcl_GetIndexFromObj(interp, fieldPtr, eras, "era", TCL_EXACT,
&era) != TCL_OK
|| Tcl_DictObjGet(interp, dict, literals[LIT_YEAR],
&fieldPtr) != TCL_OK
|| TclGetIntFromObj(interp, fieldPtr, &fields.year) != TCL_OK
|| Tcl_DictObjGet(interp, dict, literals[LIT_MONTH],
&fieldPtr) != TCL_OK
|| TclGetIntFromObj(interp, fieldPtr, &fields.month) != TCL_OK
|| Tcl_DictObjGet(interp, dict, literals[LIT_DAYOFMONTH],
&fieldPtr) != TCL_OK
|| TclGetIntFromObj(interp, fieldPtr, &fields.dayOfMonth)!=TCL_OK
if (FetchEraField(interp, dict, literals[LIT_ERA], &era) != TCL_OK
|| FetchIntField(interp, dict, literals[LIT_YEAR], &fields.year)
!= TCL_OK
|| FetchIntField(interp, dict, literals[LIT_MONTH], &fields.month)
!= TCL_OK
|| FetchIntField(interp, dict, literals[LIT_DAYOFMONTH],
&fields.dayOfMonth) != TCL_OK
|| TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) {
return TCL_ERROR;
}
@@ -622,7 +656,6 @@ ClockGetjuliandayfromerayearweekdayObjCmd(
Tcl_Obj *dict;
ClockClientData *data = clientData;
Tcl_Obj *const *literals = data->literals;
Tcl_Obj *fieldPtr;
int changeover;
int copied = 0;
int status;
@@ -637,18 +670,13 @@ ClockGetjuliandayfromerayearweekdayObjCmd(
return TCL_ERROR;
}
dict = objv[1];
if (Tcl_DictObjGet(interp, dict, literals[LIT_ERA], &fieldPtr) != TCL_OK
|| Tcl_GetIndexFromObj(interp, fieldPtr, eras, "era", TCL_EXACT,
&era) != TCL_OK
|| Tcl_DictObjGet(interp, dict, literals[LIT_ISO8601YEAR],
&fieldPtr) != TCL_OK
|| TclGetIntFromObj(interp, fieldPtr, &fields.iso8601Year)!=TCL_OK
|| Tcl_DictObjGet(interp, dict, literals[LIT_ISO8601WEEK],
&fieldPtr) != TCL_OK
|| TclGetIntFromObj(interp, fieldPtr, &fields.iso8601Week)!=TCL_OK
|| Tcl_DictObjGet(interp, dict, literals[LIT_DAYOFWEEK],
&fieldPtr) != TCL_OK
|| TclGetIntFromObj(interp, fieldPtr, &fields.dayOfWeek) != TCL_OK
if (FetchEraField(interp, dict, literals[LIT_ERA], &era) != TCL_OK
|| FetchIntField(interp, dict, literals[LIT_ISO8601YEAR],
&fields.iso8601Year) != TCL_OK
|| FetchIntField(interp, dict, literals[LIT_ISO8601WEEK],
&fields.iso8601Week) != TCL_OK
|| FetchIntField(interp, dict, literals[LIT_DAYOFWEEK],
&fields.dayOfWeek) != TCL_OK
|| TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) {
return TCL_ERROR;
}
@@ -1697,7 +1725,7 @@ ClockClicksObjCmd(
case 1:
break;
case 2:
if (Tcl_GetIndexFromObj(interp, objv[1], clicksSwitches, "switch", 0,
if (Tcl_GetIndexFromObj(interp, objv[1], clicksSwitches, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
@@ -1867,9 +1895,9 @@ ClockParseformatargsObjCmd(
localeObj = litPtr[LIT_C];
timezoneObj = litPtr[LIT__NIL];
for (i = 2; i < objc; i+=2) {
if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", 0,
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
&optionIndex) != TCL_OK) {
Tcl_SetErrorCode(interp, "CLOCK", "badSwitch",
Tcl_SetErrorCode(interp, "CLOCK", "badOption",
Tcl_GetString(objv[i]), NULL);
return TCL_ERROR;
}
+1 -1
View File
@@ -1590,7 +1590,7 @@ FileAttrIsOwnedCmd(
* test for equivalence to the current user.
*/
#if defined(__WIN32__) || defined(__CYGWIN__)
#if defined(_WIN32) || defined(__CYGWIN__)
value = 1;
#else
value = (geteuid() == buf.st_uid);
+25 -16
View File
@@ -29,7 +29,7 @@
typedef struct SortElement {
union { /* The value that we sorting by. */
const char *strValuePtr;
long intValue;
Tcl_WideInt wideValue;
double doubleValue;
Tcl_Obj *objValuePtr;
} collationKey;
@@ -1287,6 +1287,7 @@ TclInfoFrame(
"eval", "eval", "eval", "precompiled", "source", "proc"
};
Proc *procPtr = framePtr->framePtr ? framePtr->framePtr->procPtr : NULL;
int needsFree = -1;
/*
* Pull the information and construct the dictionary to return, as list.
@@ -1360,6 +1361,9 @@ TclInfoFrame(
}
ADD_PAIR("cmd", TclGetSourceFromFrame(fPtr, 0, NULL));
if (fPtr->cmdObj && framePtr->cmdObj == NULL) {
needsFree = lc - 1;
}
TclStackFree(interp, fPtr);
break;
}
@@ -1447,7 +1451,11 @@ TclInfoFrame(
}
}
return Tcl_NewListObj(lc, lv);
tmpObj = Tcl_NewListObj(lc, lv);
if (needsFree >= 0) {
Tcl_DecrRefCount(lv[needsFree]);
}
return tmpObj;
}
/*
@@ -2655,7 +2663,7 @@ Tcl_LrepeatObjCmd(
* number of times.
*/
CLANG_ASSERT(dataArray);
CLANG_ASSERT(dataArray || totalElems == 0 );
if (objc == 1) {
register Tcl_Obj *tmpPtr = objv[0];
@@ -2893,7 +2901,8 @@ Tcl_LsearchObjCmd(
{
const char *bytes, *patternBytes;
int i, match, index, result, listc, length, elemLen, bisect;
int dataType, isIncreasing, lower, upper, patInt, objInt, offset;
int dataType, isIncreasing, lower, upper, offset;
Tcl_WideInt patWide, objWide;
int allMatches, inlineReturn, negatedMatch, returnSubindices, noCase;
double patDouble, objDouble;
SortInfo sortInfo;
@@ -3212,7 +3221,7 @@ Tcl_LsearchObjCmd(
patternBytes = TclGetStringFromObj(patObj, &length);
break;
case INTEGER:
result = TclGetIntFromObj(interp, patObj, &patInt);
result = TclGetWideIntFromObj(interp, patObj, &patWide);
if (result != TCL_OK) {
goto done;
}
@@ -3281,13 +3290,13 @@ Tcl_LsearchObjCmd(
match = DictionaryCompare(patternBytes, bytes);
break;
case INTEGER:
result = TclGetIntFromObj(interp, itemPtr, &objInt);
result = TclGetWideIntFromObj(interp, itemPtr, &objWide);
if (result != TCL_OK) {
goto done;
}
if (patInt == objInt) {
if (patWide == objWide) {
match = 0;
} else if (patInt < objInt) {
} else if (patWide < objWide) {
match = -1;
} else {
match = 1;
@@ -3400,14 +3409,14 @@ Tcl_LsearchObjCmd(
break;
case INTEGER:
result = TclGetIntFromObj(interp, itemPtr, &objInt);
result = TclGetWideIntFromObj(interp, itemPtr, &objWide);
if (result != TCL_OK) {
if (listPtr != NULL) {
Tcl_DecrRefCount(listPtr);
}
goto done;
}
match = (objInt == patInt);
match = (objWide == patWide);
break;
case REAL:
@@ -3971,13 +3980,13 @@ Tcl_LsortObjCmd(
if (sortMode == SORTMODE_ASCII) {
elementArray[i].collationKey.strValuePtr = TclGetString(indexPtr);
} else if (sortMode == SORTMODE_INTEGER) {
long a;
Tcl_WideInt a;
if (TclGetLongFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
if (TclGetWideIntFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
sortInfo.resultCode = TCL_ERROR;
goto done1;
}
elementArray[i].collationKey.intValue = a;
elementArray[i].collationKey.wideValue = a;
} else if (sortMode == SORTMODE_REAL) {
double a;
@@ -4226,10 +4235,10 @@ SortCompare(
order = DictionaryCompare(elemPtr1->collationKey.strValuePtr,
elemPtr2->collationKey.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_INTEGER) {
long a, b;
Tcl_WideInt a, b;
a = elemPtr1->collationKey.intValue;
b = elemPtr2->collationKey.intValue;
a = elemPtr1->collationKey.wideValue;
b = elemPtr2->collationKey.wideValue;
order = ((a >= b) - (a <= b));
} else if (infoPtr->sortMode == SORTMODE_REAL) {
double a, b;
+97 -41
View File
@@ -18,6 +18,7 @@
#include "tclInt.h"
#include "tclRegexp.h"
#include "tclStringTrim.h"
static inline Tcl_Obj * During(Tcl_Interp *interp, int resultCode,
Tcl_Obj *oldOptions, Tcl_Obj *errorInfo);
@@ -35,36 +36,35 @@ static int UniCharIsHexDigit(int character);
/*
* Default set of characters to trim in [string trim] and friends. This is a
* UTF-8 literal string containing all Unicode space characters [TIP #413]
*
* Synch with tclCompCmdsSZ.c
*/
#define DEFAULT_TRIM_SET \
"\x09\x0a\x0b\x0c\x0d " /* ASCII */\
"\xc0\x80" /* nul (U+0000) */\
"\xc2\x85" /* next line (U+0085) */\
"\xc2\xa0" /* non-breaking space (U+00a0) */\
"\xe1\x9a\x80" /* ogham space mark (U+1680) */ \
"\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */\
"\xe2\x80\x80" /* en quad (U+2000) */\
"\xe2\x80\x81" /* em quad (U+2001) */\
"\xe2\x80\x82" /* en space (U+2002) */\
"\xe2\x80\x83" /* em space (U+2003) */\
"\xe2\x80\x84" /* three-per-em space (U+2004) */\
"\xe2\x80\x85" /* four-per-em space (U+2005) */\
"\xe2\x80\x86" /* six-per-em space (U+2006) */\
"\xe2\x80\x87" /* figure space (U+2007) */\
"\xe2\x80\x88" /* punctuation space (U+2008) */\
"\xe2\x80\x89" /* thin space (U+2009) */\
"\xe2\x80\x8a" /* hair space (U+200a) */\
"\xe2\x80\x8b" /* zero width space (U+200b) */\
"\xe2\x80\xa8" /* line separator (U+2028) */\
"\xe2\x80\xa9" /* paragraph separator (U+2029) */\
"\xe2\x80\xaf" /* narrow no-break space (U+202f) */\
"\xe2\x81\x9f" /* medium mathematical space (U+205f) */\
"\xe2\x81\xa0" /* word joiner (U+2060) */\
"\xe3\x80\x80" /* ideographic space (U+3000) */\
const char tclDefaultTrimSet[] =
"\x09\x0a\x0b\x0c\x0d " /* ASCII */
"\xc0\x80" /* nul (U+0000) */
"\xc2\x85" /* next line (U+0085) */
"\xc2\xa0" /* non-breaking space (U+00a0) */
"\xe1\x9a\x80" /* ogham space mark (U+1680) */
"\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */
"\xe2\x80\x80" /* en quad (U+2000) */
"\xe2\x80\x81" /* em quad (U+2001) */
"\xe2\x80\x82" /* en space (U+2002) */
"\xe2\x80\x83" /* em space (U+2003) */
"\xe2\x80\x84" /* three-per-em space (U+2004) */
"\xe2\x80\x85" /* four-per-em space (U+2005) */
"\xe2\x80\x86" /* six-per-em space (U+2006) */
"\xe2\x80\x87" /* figure space (U+2007) */
"\xe2\x80\x88" /* punctuation space (U+2008) */
"\xe2\x80\x89" /* thin space (U+2009) */
"\xe2\x80\x8a" /* hair space (U+200a) */
"\xe2\x80\x8b" /* zero width space (U+200b) */
"\xe2\x80\xa8" /* line separator (U+2028) */
"\xe2\x80\xa9" /* paragraph separator (U+2029) */
"\xe2\x80\xaf" /* narrow no-break space (U+202f) */
"\xe2\x81\x9f" /* medium mathematical space (U+205f) */
"\xe2\x81\xa0" /* word joiner (U+2060) */
"\xe3\x80\x80" /* ideographic space (U+3000) */
"\xef\xbb\xbf" /* zero width no-break space (U+feff) */
;
/*
*----------------------------------------------------------------------
@@ -161,7 +161,7 @@ Tcl_RegexpObjCmd(
if (name[0] != '-') {
break;
}
if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", TCL_EXACT,
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", TCL_EXACT,
&index) != TCL_OK) {
goto optionError;
}
@@ -217,7 +217,7 @@ Tcl_RegexpObjCmd(
endOfForLoop:
if ((objc - i) < (2 - about)) {
Tcl_WrongNumArgs(interp, 1, objv,
"?-switch ...? exp string ?matchVar? ?subMatchVar ...?");
"?-option ...? exp string ?matchVar? ?subMatchVar ...?");
goto optionError;
}
objc -= i;
@@ -231,6 +231,8 @@ Tcl_RegexpObjCmd(
if (doinline && ((objc - 2) != 0)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"regexp match variables not allowed when using -inline", -1));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "REGEXP",
"MIX_VAR_INLINE", NULL);
goto optionError;
}
@@ -519,7 +521,7 @@ Tcl_RegsubObjCmd(
if (name[0] != '-') {
break;
}
if (Tcl_GetIndexFromObj(interp, objv[idx], options, "switch",
if (Tcl_GetIndexFromObj(interp, objv[idx], options, "option",
TCL_EXACT, &index) != TCL_OK) {
goto optionError;
}
@@ -566,7 +568,7 @@ Tcl_RegsubObjCmd(
endOfForLoop:
if (objc-idx < 3 || objc-idx > 4) {
Tcl_WrongNumArgs(interp, 1, objv,
"?-switch ...? exp string subSpec ?varName?");
"?-option ...? exp string subSpec ?varName?");
optionError:
if (startIndex) {
Tcl_DecrRefCount(startIndex);
@@ -2833,6 +2835,59 @@ StringCmpCmd(
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* StringCatCmd --
*
* This procedure is invoked to process the "string cat" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
static int
StringCatCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
int i;
Tcl_Obj *objResultPtr;
if (objc < 2) {
/*
* If there are no args, the result is an empty object.
* Just leave the preset empty interp result.
*/
return TCL_OK;
}
if (objc == 2) {
/*
* Other trivial case, single arg, just return it.
*/
Tcl_SetObjResult(interp, objv[1]);
return TCL_OK;
}
objResultPtr = objv[1];
if (Tcl_IsShared(objResultPtr)) {
objResultPtr = Tcl_DuplicateObj(objResultPtr);
}
for(i = 2;i < objc;i++) {
Tcl_AppendObjToObj(objResultPtr, objv[i]);
}
Tcl_SetObjResult(interp, objResultPtr);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
@@ -3191,8 +3246,8 @@ StringTrimCmd(
if (objc == 3) {
string2 = TclGetStringFromObj(objv[2], &length2);
} else if (objc == 2) {
string2 = DEFAULT_TRIM_SET;
length2 = strlen(DEFAULT_TRIM_SET);
string2 = tclDefaultTrimSet;
length2 = strlen(tclDefaultTrimSet);
} else {
Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?");
return TCL_ERROR;
@@ -3239,8 +3294,8 @@ StringTrimLCmd(
if (objc == 3) {
string2 = TclGetStringFromObj(objv[2], &length2);
} else if (objc == 2) {
string2 = DEFAULT_TRIM_SET;
length2 = strlen(DEFAULT_TRIM_SET);
string2 = tclDefaultTrimSet;
length2 = strlen(tclDefaultTrimSet);
} else {
Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?");
return TCL_ERROR;
@@ -3285,8 +3340,8 @@ StringTrimRCmd(
if (objc == 3) {
string2 = TclGetStringFromObj(objv[2], &length2);
} else if (objc == 2) {
string2 = DEFAULT_TRIM_SET;
length2 = strlen(DEFAULT_TRIM_SET);
string2 = tclDefaultTrimSet;
length2 = strlen(tclDefaultTrimSet);
} else {
Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?");
return TCL_ERROR;
@@ -3328,11 +3383,12 @@ TclInitStringCmd(
{
static const EnsembleImplMap stringImplMap[] = {
{"bytelength", StringBytesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"cat", StringCatCmd, TclCompileStringCatCmd, NULL, NULL, 0},
{"compare", StringCmpCmd, TclCompileStringCmpCmd, NULL, NULL, 0},
{"equal", StringEqualCmd, TclCompileStringEqualCmd, NULL, NULL, 0},
{"first", StringFirstCmd, TclCompileStringFirstCmd, NULL, NULL, 0},
{"index", StringIndexCmd, TclCompileStringIndexCmd, NULL, NULL, 0},
{"is", StringIsCmd, NULL, NULL, NULL, 0},
{"is", StringIsCmd, TclCompileStringIsCmd, NULL, NULL, 0},
{"last", StringLastCmd, TclCompileStringLastCmd, NULL, NULL, 0},
{"length", StringLenCmd, TclCompileStringLenCmd, NULL, NULL, 0},
{"map", StringMapCmd, TclCompileStringMapCmd, NULL, NULL, 0},
@@ -3391,7 +3447,7 @@ TclSubstOptions(
for (i = 0; i < numOpts; i++) {
int optionIndex;
if (Tcl_GetIndexFromObj(interp, opts[i], substOptions, "switch", 0,
if (Tcl_GetIndexFromObj(interp, opts[i], substOptions, "option", 0,
&optionIndex) != TCL_OK) {
return TCL_ERROR;
}
@@ -3591,7 +3647,7 @@ TclNRSwitchObjCmd(
finishedOptions:
if (objc - i < 2) {
Tcl_WrongNumArgs(interp, 1, objv,
"?-switch ...? string ?pattern body ...? ?default body?");
"?-option ...? string ?pattern body ...? ?default body?");
return TCL_ERROR;
}
if (indexVarObj != NULL && mode != OPT_REGEXP) {
@@ -3638,7 +3694,7 @@ TclNRSwitchObjCmd(
if (objc < 1) {
Tcl_WrongNumArgs(interp, 1, savedObjv,
"?-switch ...? string {?pattern body ...? ?default body?}");
"?-option ...? string {?pattern body ...? ?default body?}");
return TCL_ERROR;
}
objv = listv;
+2 -9
View File
@@ -65,13 +65,6 @@ const AuxDataType tclDictUpdateInfoType = {
FreeDictUpdateInfo, /* freeProc */
PrintDictUpdateInfo /* printProc */
};
/*
* The definition of what whitespace is stripped when [concat]enating. Must be
* kept in synch with tclUtil.c
*/
#define CONCAT_WS " \f\v\r\t\n"
/*
*----------------------------------------------------------------------
@@ -285,7 +278,7 @@ TclCompileArraySetCmd(
if (isDataValid && !isDataEven) {
PushStringLiteral(envPtr, "list must have an even number of elements");
PushStringLiteral(envPtr, "-errorCode {TCL ARGUMENT FORMAT}");
PushStringLiteral(envPtr, "-errorcode {TCL ARGUMENT FORMAT}");
TclEmitInstInt4(INST_RETURN_IMM, TCL_ERROR, envPtr);
TclEmitInt4( 0, envPtr);
goto done;
@@ -380,7 +373,7 @@ TclCompileArraySetCmd(
offsetFwd = CurrentOffset(envPtr);
TclEmitInstInt1(INST_JUMP_FALSE1, 0, envPtr);
PushStringLiteral(envPtr, "list must have an even number of elements");
PushStringLiteral(envPtr, "-errorCode {TCL ARGUMENT FORMAT}");
PushStringLiteral(envPtr, "-errorcode {TCL ARGUMENT FORMAT}");
TclEmitInstInt4(INST_RETURN_IMM, TCL_ERROR, envPtr);
TclEmitInt4( 0, envPtr);
TclAdjustStackDepth(-1, envPtr);
+99 -43
View File
@@ -868,28 +868,16 @@ TclCompileLappendCmd(
CompileEnv *envPtr) /* Holds resulting instructions. */
{
Tcl_Token *varTokenPtr, *valueTokenPtr;
int isScalar, localIndex, numWords, i, fwd, offsetFwd;
int isScalar, localIndex, numWords, i;
DefineLineInformation; /* TIP #280 */
/*
* If we're not in a procedure, don't compile.
*/
if (envPtr->procPtr == NULL) {
return TCL_ERROR;
}
/* TODO: Consider support for compiling expanded args. */
numWords = parsePtr->numWords;
if (numWords == 1) {
return TCL_ERROR;
}
if (numWords != 3) {
/*
* LAPPEND instructions currently only handle one value, but we can
* handle some multi-value cases by stringing them together.
*/
if (numWords != 3 || envPtr->procPtr == NULL) {
goto lappendMultiple;
}
@@ -943,42 +931,28 @@ TclCompileLappendCmd(
return TCL_OK;
lappendMultiple:
/*
* Can only handle the case where we are appending to a local scalar when
* there are multiple values to append. Fortunately, this is common.
*/
if (envPtr->procPtr == NULL) {
return TCL_ERROR;
}
varTokenPtr = TokenAfter(parsePtr->tokenPtr);
PushVarNameWord(interp, varTokenPtr, envPtr, TCL_NO_ELEMENT,
PushVarNameWord(interp, varTokenPtr, envPtr, 0,
&localIndex, &isScalar, 1);
if (!isScalar || localIndex < 0) {
return TCL_ERROR;
}
/*
* Definitely appending to a local scalar; generate the words and append
* them.
*/
valueTokenPtr = TokenAfter(varTokenPtr);
for (i = 2 ; i < numWords ; i++) {
CompileWord(envPtr, valueTokenPtr, interp, i);
valueTokenPtr = TokenAfter(valueTokenPtr);
}
TclEmitInstInt4( INST_LIST, numWords-2, envPtr);
TclEmitInstInt4( INST_EXIST_SCALAR, localIndex, envPtr);
offsetFwd = CurrentOffset(envPtr);
TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr);
Emit14Inst( INST_LOAD_SCALAR, localIndex, envPtr);
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
fwd = CurrentOffset(envPtr) - offsetFwd;
TclStoreInt1AtPtr(fwd, envPtr->codeStart+offsetFwd+1);
Emit14Inst( INST_STORE_SCALAR, localIndex, envPtr);
TclEmitInstInt4( INST_LIST, numWords-2, envPtr);
if (isScalar) {
if (localIndex < 0) {
TclEmitOpcode( INST_LAPPEND_LIST_STK, envPtr);
} else {
TclEmitInstInt4(INST_LAPPEND_LIST, localIndex, envPtr);
}
} else {
if (localIndex < 0) {
TclEmitOpcode( INST_LAPPEND_LIST_ARRAY_STK, envPtr);
} else {
TclEmitInstInt4(INST_LAPPEND_LIST_ARRAY, localIndex,envPtr);
}
}
return TCL_OK;
}
@@ -1955,6 +1929,28 @@ TclCompileNamespaceCodeCmd(
return TCL_OK;
}
int
TclCompileNamespaceOriginCmd(
Tcl_Interp *interp, /* Used for error reporting. */
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
* created by Tcl_ParseCommand. */
Command *cmdPtr, /* Points to defintion of command being
* compiled. */
CompileEnv *envPtr) /* Holds resulting instructions. */
{
Tcl_Token *tokenPtr;
DefineLineInformation; /* TIP #280 */
if (parsePtr->numWords != 2) {
return TCL_ERROR;
}
tokenPtr = TokenAfter(parsePtr->tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 1);
TclEmitOpcode( INST_ORIGIN_COMMAND, envPtr);
return TCL_OK;
}
int
TclCompileNamespaceQualifiersCmd(
Tcl_Interp *interp, /* Used for error reporting. */
@@ -3017,6 +3013,66 @@ IndexTailVarIfKnown(
return localIndex;
}
/*
* ----------------------------------------------------------------------
*
* TclCompileObjectNextCmd, TclCompileObjectSelfCmd --
*
* Compilations of the TclOO utility commands [next] and [self].
*
* ----------------------------------------------------------------------
*/
int
TclCompileObjectNextCmd(
Tcl_Interp *interp, /* Used for error reporting. */
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
* created by Tcl_ParseCommand. */
Command *cmdPtr, /* Points to defintion of command being
* compiled. */
CompileEnv *envPtr) /* Holds resulting instructions. */
{
DefineLineInformation; /* TIP #280 */
Tcl_Token *tokenPtr = parsePtr->tokenPtr;
int i;
if (parsePtr->numWords > 255) {
return TCL_ERROR;
}
for (i=0 ; i<parsePtr->numWords ; i++) {
CompileWord(envPtr, tokenPtr, interp, i);
tokenPtr = TokenAfter(tokenPtr);
}
TclEmitInstInt1( INST_TCLOO_NEXT, i, envPtr);
return TCL_OK;
}
int
TclCompileObjectNextToCmd(
Tcl_Interp *interp, /* Used for error reporting. */
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
* created by Tcl_ParseCommand. */
Command *cmdPtr, /* Points to defintion of command being
* compiled. */
CompileEnv *envPtr) /* Holds resulting instructions. */
{
DefineLineInformation; /* TIP #280 */
Tcl_Token *tokenPtr = parsePtr->tokenPtr;
int i;
if (parsePtr->numWords < 2 || parsePtr->numWords > 255) {
return TCL_ERROR;
}
for (i=0 ; i<parsePtr->numWords ; i++) {
CompileWord(envPtr, tokenPtr, interp, i);
tokenPtr = TokenAfter(tokenPtr);
}
TclEmitInstInt1( INST_TCLOO_NEXT_CLASS, i, envPtr);
return TCL_OK;
}
int
TclCompileObjectSelfCmd(
Tcl_Interp *interp, /* Used for error reporting. */
+436 -36
View File
@@ -17,6 +17,7 @@
#include "tclInt.h"
#include "tclCompile.h"
#include "tclStringTrim.h"
/*
* Prototypes for procedures defined later in this file:
@@ -267,6 +268,78 @@ TclCompileSetCmd(
*----------------------------------------------------------------------
*/
int
TclCompileStringCatCmd(
Tcl_Interp *interp, /* Used for error reporting. */
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
* created by Tcl_ParseCommand. */
Command *cmdPtr, /* Points to defintion of command being
* compiled. */
CompileEnv *envPtr) /* Holds resulting instructions. */
{
int i, numWords = parsePtr->numWords, numArgs;
Tcl_Token *wordTokenPtr;
Tcl_Obj *obj, *folded;
DefineLineInformation; /* TIP #280 */
/* Trivial case, no arg */
if (numWords<2) {
PushStringLiteral(envPtr, "");
return TCL_OK;
}
/* General case: issue CONCAT1's (by chunks of 254 if needed), folding
contiguous constants along the way */
numArgs = 0;
folded = NULL;
wordTokenPtr = TokenAfter(parsePtr->tokenPtr);
for (i = 1; i < numWords; i++) {
obj = Tcl_NewObj();
if (TclWordKnownAtCompileTime(wordTokenPtr, obj)) {
if (folded) {
Tcl_AppendObjToObj(folded, obj);
Tcl_DecrRefCount(obj);
} else {
folded = obj;
}
} else {
Tcl_DecrRefCount(obj);
if (folded) {
int len;
const char *bytes = Tcl_GetStringFromObj(folded, &len);
PushLiteral(envPtr, bytes, len);
Tcl_DecrRefCount(folded);
folded = NULL;
numArgs ++;
}
CompileWord(envPtr, wordTokenPtr, interp, i);
numArgs ++;
if (numArgs >= 254) { /* 254 to take care of the possible +1 of "folded" above */
TclEmitInstInt1(INST_STR_CONCAT1, 254, envPtr);
numArgs -= 253; /* concat pushes 1 obj, the result */
}
}
wordTokenPtr = TokenAfter(wordTokenPtr);
}
if (folded) {
int len;
const char *bytes = Tcl_GetStringFromObj(folded, &len);
PushLiteral(envPtr, bytes, len);
Tcl_DecrRefCount(folded);
folded = NULL;
numArgs ++;
}
if (numArgs > 1) {
TclEmitInstInt1(INST_STR_CONCAT1, numArgs, envPtr);
}
return TCL_OK;
}
int
TclCompileStringCmpCmd(
Tcl_Interp *interp, /* Used for error reporting. */
@@ -423,6 +496,284 @@ TclCompileStringIndexCmd(
return TCL_OK;
}
int
TclCompileStringIsCmd(
Tcl_Interp *interp, /* Used for error reporting. */
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
* created by Tcl_ParseCommand. */
Command *cmdPtr, /* Points to defintion of command being
* compiled. */
CompileEnv *envPtr) /* Holds resulting instructions. */
{
DefineLineInformation; /* TIP #280 */
Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
static const char *const isClasses[] = {
"alnum", "alpha", "ascii", "control",
"boolean", "digit", "double", "entier",
"false", "graph", "integer", "list",
"lower", "print", "punct", "space",
"true", "upper", "wideinteger", "wordchar",
"xdigit", NULL
};
enum isClasses {
STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL,
STR_IS_BOOL, STR_IS_DIGIT, STR_IS_DOUBLE, STR_IS_ENTIER,
STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT, STR_IS_LIST,
STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT, STR_IS_SPACE,
STR_IS_TRUE, STR_IS_UPPER, STR_IS_WIDE, STR_IS_WORD,
STR_IS_XDIGIT
};
int t, range, allowEmpty = 0, end;
InstStringClassType strClassType;
Tcl_Obj *isClass;
if (parsePtr->numWords < 3 || parsePtr->numWords > 6) {
return TCL_ERROR;
}
isClass = Tcl_NewObj();
if (!TclWordKnownAtCompileTime(tokenPtr, isClass)) {
Tcl_DecrRefCount(isClass);
return TCL_ERROR;
} else if (Tcl_GetIndexFromObj(interp, isClass, isClasses, "class", 0,
&t) != TCL_OK) {
Tcl_DecrRefCount(isClass);
TclCompileSyntaxError(interp, envPtr);
return TCL_OK;
}
Tcl_DecrRefCount(isClass);
#define GotLiteral(tokenPtr, word) \
((tokenPtr)->type == TCL_TOKEN_SIMPLE_WORD && \
(tokenPtr)[1].size > 1 && \
(tokenPtr)[1].start[0] == word[0] && \
strncmp((tokenPtr)[1].start, (word), (tokenPtr)[1].size) == 0)
/*
* Cannot handle the -failindex option at all, and that's the only legal
* way to have more than 4 arguments.
*/
if (parsePtr->numWords != 3 && parsePtr->numWords != 4) {
return TCL_ERROR;
}
tokenPtr = TokenAfter(tokenPtr);
if (parsePtr->numWords == 3) {
allowEmpty = 1;
} else {
if (!GotLiteral(tokenPtr, "-strict")) {
return TCL_ERROR;
}
tokenPtr = TokenAfter(tokenPtr);
}
#undef GotLiteral
/*
* Compile the code. There are several main classes of check here.
* 1. Character classes
* 2. Booleans
* 3. Integers
* 4. Floats
* 5. Lists
*/
CompileWord(envPtr, tokenPtr, interp, parsePtr->numWords-1);
switch ((enum isClasses) t) {
case STR_IS_ALNUM:
strClassType = STR_CLASS_ALNUM;
goto compileStrClass;
case STR_IS_ALPHA:
strClassType = STR_CLASS_ALPHA;
goto compileStrClass;
case STR_IS_ASCII:
strClassType = STR_CLASS_ASCII;
goto compileStrClass;
case STR_IS_CONTROL:
strClassType = STR_CLASS_CONTROL;
goto compileStrClass;
case STR_IS_DIGIT:
strClassType = STR_CLASS_DIGIT;
goto compileStrClass;
case STR_IS_GRAPH:
strClassType = STR_CLASS_GRAPH;
goto compileStrClass;
case STR_IS_LOWER:
strClassType = STR_CLASS_LOWER;
goto compileStrClass;
case STR_IS_PRINT:
strClassType = STR_CLASS_PRINT;
goto compileStrClass;
case STR_IS_PUNCT:
strClassType = STR_CLASS_PUNCT;
goto compileStrClass;
case STR_IS_SPACE:
strClassType = STR_CLASS_SPACE;
goto compileStrClass;
case STR_IS_UPPER:
strClassType = STR_CLASS_UPPER;
goto compileStrClass;
case STR_IS_WORD:
strClassType = STR_CLASS_WORD;
goto compileStrClass;
case STR_IS_XDIGIT:
strClassType = STR_CLASS_XDIGIT;
compileStrClass:
if (allowEmpty) {
OP1( STR_CLASS, strClassType);
} else {
int over, over2;
OP( DUP);
OP1( STR_CLASS, strClassType);
JUMP1( JUMP_TRUE, over);
OP( POP);
PUSH( "0");
JUMP1( JUMP, over2);
FIXJUMP1(over);
PUSH( "");
OP( STR_NEQ);
FIXJUMP1(over2);
}
return TCL_OK;
case STR_IS_BOOL:
case STR_IS_FALSE:
case STR_IS_TRUE:
OP( TRY_CVT_TO_BOOLEAN);
switch (t) {
int over, over2;
case STR_IS_BOOL:
if (allowEmpty) {
JUMP1( JUMP_TRUE, over);
PUSH( "");
OP( STR_EQ);
JUMP1( JUMP, over2);
FIXJUMP1(over);
OP( POP);
PUSH( "1");
FIXJUMP1(over2);
} else {
OP4( REVERSE, 2);
OP( POP);
}
return TCL_OK;
case STR_IS_TRUE:
JUMP1( JUMP_TRUE, over);
if (allowEmpty) {
PUSH( "");
OP( STR_EQ);
} else {
OP( POP);
PUSH( "0");
}
FIXJUMP1( over);
OP( LNOT);
OP( LNOT);
return TCL_OK;
case STR_IS_FALSE:
JUMP1( JUMP_TRUE, over);
if (allowEmpty) {
PUSH( "");
OP( STR_NEQ);
} else {
OP( POP);
PUSH( "1");
}
FIXJUMP1( over);
OP( LNOT);
return TCL_OK;
}
case STR_IS_DOUBLE: {
int satisfied, isEmpty;
if (allowEmpty) {
OP( DUP);
PUSH( "");
OP( STR_EQ);
JUMP1( JUMP_TRUE, isEmpty);
OP( NUM_TYPE);
JUMP1( JUMP_TRUE, satisfied);
PUSH( "0");
JUMP1( JUMP, end);
FIXJUMP1( isEmpty);
OP( POP);
FIXJUMP1( satisfied);
} else {
OP( NUM_TYPE);
JUMP1( JUMP_TRUE, satisfied);
PUSH( "0");
JUMP1( JUMP, end);
TclAdjustStackDepth(-1, envPtr);
FIXJUMP1( satisfied);
}
PUSH( "1");
FIXJUMP1( end);
return TCL_OK;
}
case STR_IS_INT:
case STR_IS_WIDE:
case STR_IS_ENTIER:
if (allowEmpty) {
int testNumType;
OP( DUP);
OP( NUM_TYPE);
OP( DUP);
JUMP1( JUMP_TRUE, testNumType);
OP( POP);
PUSH( "");
OP( STR_EQ);
JUMP1( JUMP, end);
TclAdjustStackDepth(1, envPtr);
FIXJUMP1( testNumType);
OP4( REVERSE, 2);
OP( POP);
} else {
OP( NUM_TYPE);
OP( DUP);
JUMP1( JUMP_FALSE, end);
}
switch (t) {
case STR_IS_INT:
PUSH( "1");
OP( EQ);
break;
case STR_IS_WIDE:
PUSH( "2");
OP( LE);
break;
case STR_IS_ENTIER:
PUSH( "3");
OP( LE);
break;
}
FIXJUMP1( end);
return TCL_OK;
case STR_IS_LIST:
range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
OP4( BEGIN_CATCH4, range);
ExceptionRangeStarts(envPtr, range);
OP( DUP);
OP( LIST_LENGTH);
OP( POP);
ExceptionRangeEnds(envPtr, range);
ExceptionRangeTarget(envPtr, range, catchOffset);
OP( POP);
OP( PUSH_RETURN_CODE);
OP( END_CATCH);
OP( LNOT);
return TCL_OK;
}
return TclCompileBasicMin0ArgCmd(interp, parsePtr, cmdPtr, envPtr);
}
int
TclCompileStringMatchCmd(
Tcl_Interp *interp, /* Used for error reporting. */
@@ -700,8 +1051,8 @@ TclCompileStringReplaceCmd(
/*
* We handle these replacements specially: first character (where
* idx1=idx2=0) and suffixes (where idx1=idx2=INDEX_END). Anything else
* and the semantics get rather screwy.
* idx1=idx2=0) and last character (where idx1=idx2=INDEX_END). Anything
* else and the semantics get rather screwy.
*/
if (idx1 == 0 && idx2 == 0) {
@@ -787,37 +1138,6 @@ TclCompileStringReplaceCmd(
}
}
/*
* Synch with tclCmdMZ.c
*/
#define DEFAULT_TRIM_SET \
"\x09\x0a\x0b\x0c\x0d " /* ASCII */\
"\xc0\x80" /* nul (U+0000) */\
"\xc2\x85" /* next line (U+0085) */\
"\xc2\xa0" /* non-breaking space (U+00a0) */\
"\xe1\x9a\x80" /* ogham space mark (U+1680) */ \
"\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */\
"\xe2\x80\x80" /* en quad (U+2000) */\
"\xe2\x80\x81" /* em quad (U+2001) */\
"\xe2\x80\x82" /* en space (U+2002) */\
"\xe2\x80\x83" /* em space (U+2003) */\
"\xe2\x80\x84" /* three-per-em space (U+2004) */\
"\xe2\x80\x85" /* four-per-em space (U+2005) */\
"\xe2\x80\x86" /* six-per-em space (U+2006) */\
"\xe2\x80\x87" /* figure space (U+2007) */\
"\xe2\x80\x88" /* punctuation space (U+2008) */\
"\xe2\x80\x89" /* thin space (U+2009) */\
"\xe2\x80\x8a" /* hair space (U+200a) */\
"\xe2\x80\x8b" /* zero width space (U+200b) */\
"\xe2\x80\xa8" /* line separator (U+2028) */\
"\xe2\x80\xa9" /* paragraph separator (U+2029) */\
"\xe2\x80\xaf" /* narrow no-break space (U+202f) */\
"\xe2\x81\x9f" /* medium mathematical space (U+205f) */\
"\xe2\x81\xa0" /* word joiner (U+2060) */\
"\xe3\x80\x80" /* ideographic space (U+3000) */\
"\xef\xbb\xbf" /* zero width no-break space (U+feff) */
int
TclCompileStringTrimLCmd(
Tcl_Interp *interp, /* Used for error reporting. */
@@ -840,7 +1160,7 @@ TclCompileStringTrimLCmd(
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 2);
} else {
PushLiteral(envPtr, DEFAULT_TRIM_SET, strlen(DEFAULT_TRIM_SET));
PushLiteral(envPtr, tclDefaultTrimSet, strlen(tclDefaultTrimSet));
}
OP( STR_TRIM_LEFT);
return TCL_OK;
@@ -868,7 +1188,7 @@ TclCompileStringTrimRCmd(
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 2);
} else {
PushLiteral(envPtr, DEFAULT_TRIM_SET, strlen(DEFAULT_TRIM_SET));
PushLiteral(envPtr, tclDefaultTrimSet, strlen(tclDefaultTrimSet));
}
OP( STR_TRIM_RIGHT);
return TCL_OK;
@@ -896,7 +1216,7 @@ TclCompileStringTrimCmd(
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 2);
} else {
PushLiteral(envPtr, DEFAULT_TRIM_SET, strlen(DEFAULT_TRIM_SET));
PushLiteral(envPtr, tclDefaultTrimSet, strlen(tclDefaultTrimSet));
}
OP( STR_TRIM);
return TCL_OK;
@@ -968,6 +1288,41 @@ TclCompileStringToTitleCmd(
return TCL_OK;
}
/*
* Support definitions for the [string is] compilation.
*/
static int
UniCharIsAscii(
int character)
{
return (character >= 0) && (character < 0x80);
}
static int
UniCharIsHexDigit(
int character)
{
return (character >= 0) && (character < 0x80) && isxdigit(character);
}
StringClassDesc const tclStringClassTable[] = {
{"alnum", Tcl_UniCharIsAlnum},
{"alpha", Tcl_UniCharIsAlpha},
{"ascii", UniCharIsAscii},
{"control", Tcl_UniCharIsControl},
{"digit", Tcl_UniCharIsDigit},
{"graph", Tcl_UniCharIsGraph},
{"lower", Tcl_UniCharIsLower},
{"print", Tcl_UniCharIsPrint},
{"punct", Tcl_UniCharIsPunct},
{"space", Tcl_UniCharIsSpace},
{"upper", Tcl_UniCharIsUpper},
{"word", Tcl_UniCharIsWordChar},
{"xdigit", UniCharIsHexDigit},
{NULL, NULL}
};
/*
*----------------------------------------------------------------------
*
@@ -3474,6 +3829,51 @@ TclCompileYieldCmd(
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclCompileYieldToCmd --
*
* Procedure called to compile the "yieldto" command.
*
* Results:
* Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
* evaluation to runtime.
*
* Side effects:
* Instructions are added to envPtr to execute the "yieldto" command at
* runtime.
*
*----------------------------------------------------------------------
*/
int
TclCompileYieldToCmd(
Tcl_Interp *interp, /* Used for error reporting. */
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
* created by Tcl_ParseCommand. */
Command *cmdPtr, /* Points to defintion of command being
* compiled. */
CompileEnv *envPtr) /* Holds resulting instructions. */
{
DefineLineInformation; /* TIP #280 */
Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
int i;
if (parsePtr->numWords < 2) {
return TCL_ERROR;
}
OP( NS_CURRENT);
for (i = 1 ; i < parsePtr->numWords ; i++) {
CompileWord(envPtr, tokenPtr, interp, i);
tokenPtr = TokenAfter(tokenPtr);
}
OP4( LIST, i);
OP( YIELD_TO_INVOKE);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
+83 -8
View File
@@ -493,6 +493,7 @@ InstructionDesc const tclInstructionTable[] = {
* qualified version, or produces the empty string if no such command
* exists. Never generates errors.
* Stack: ... cmdName => ... fullCmdName */
{"tclooSelf", 1, +1, 0, {OPERAND_NONE}},
/* Push the identity of the current TclOO object (i.e., the name of
* its current public access command) on the stack. */
@@ -594,23 +595,74 @@ InstructionDesc const tclInstructionTable[] = {
* is number of values to concatenate.
* Operation: push concat(stk1 stk2 ... stktop) */
{"strUpper", 1, 0, 0, {OPERAND_NONE}},
{"strcaseUpper", 1, 0, 0, {OPERAND_NONE}},
/* [string toupper] core: converts whole string to upper case using
* the default (extended "C" locale) rules.
* Stack: ... string => ... newString */
{"strLower", 1, 0, 0, {OPERAND_NONE}},
{"strcaseLower", 1, 0, 0, {OPERAND_NONE}},
/* [string tolower] core: converts whole string to upper case using
* the default (extended "C" locale) rules.
* Stack: ... string => ... newString */
{"strTitle", 1, 0, 0, {OPERAND_NONE}},
{"strcaseTitle", 1, 0, 0, {OPERAND_NONE}},
/* [string totitle] core: converts whole string to upper case using
* the default (extended "C" locale) rules.
* Stack: ... string => ... newString */
{"strReplace", 1, -3, 0, {OPERAND_NONE}},
{"strreplace", 1, -3, 0, {OPERAND_NONE}},
/* [string replace] core: replaces a non-empty range of one string
* with the contents of another.
* Stack: ... string fromIdx toIdx replacement => ... newString */
{"originCmd", 1, 0, 0, {OPERAND_NONE}},
/* Reports which command was the origin (via namespace import chain)
* of the command named on the top of the stack.
* Stack: ... cmdName => ... fullOriginalCmdName */
{"tclooNext", 2, INT_MIN, 1, {OPERAND_UINT1}},
/* Call the next item on the TclOO call chain, passing opnd arguments
* (min 1, max 255, *includes* "next"). The result of the invoked
* method implementation will be pushed on the stack in place of the
* arguments (similar to invokeStk).
* Stack: ... "next" arg2 arg3 -- argN => ... result */
{"tclooNextClass", 2, INT_MIN, 1, {OPERAND_UINT1}},
/* Call the following item on the TclOO call chain defined by class
* className, passing opnd arguments (min 2, max 255, *includes*
* "nextto" and the class name). The result of the invoked method
* implementation will be pushed on the stack in place of the
* arguments (similar to invokeStk).
* Stack: ... "nextto" className arg3 arg4 -- argN => ... result */
{"yieldToInvoke", 1, 0, 0, {OPERAND_NONE}},
/* Makes the current coroutine yield the value at the top of the
* stack, invoking the given command/args with resolution in the given
* namespace (all packed into a list), and places the list of values
* that are the response back on top of the stack when it resumes.
* Stack: ... [list ns cmd arg1 ... argN] => ... resumeList */
{"numericType", 1, 0, 0, {OPERAND_NONE}},
/* Pushes the numeric type code of the word at the top of the stack.
* Stack: ... value => ... typeCode */
{"tryCvtToBoolean", 1, +1, 0, {OPERAND_NONE}},
/* Try converting stktop to boolean if possible. No errors.
* Stack: ... value => ... value isStrictBool */
{"strclass", 2, 0, 1, {OPERAND_SCLS1}},
/* See if all the characters of the given string are a member of the
* specified (by opnd) character class. Note that an empty string will
* satisfy the class check (standard definition of "all").
* Stack: ... stringValue => ... boolean */
{"lappendList", 5, 0, 1, {OPERAND_LVT4}},
/* Lappend list to scalar variable at op4 in frame.
* Stack: ... list => ... listVarContents */
{"lappendListArray", 5, -1, 1, {OPERAND_LVT4}},
/* Lappend list to array element; array at op4.
* Stack: ... elem list => ... listVarContents */
{"lappendListArrayStk", 1, -2, 0, {OPERAND_NONE}},
/* Lappend list to array element.
* Stack: ... arrayName elem list => ... listVarContents */
{"lappendListStk", 1, -1, 0, {OPERAND_NONE}},
/* Lappend list to general variable.
* Stack: ... varName list => ... listVarContents */
{NULL, 0, 0, 0, {OPERAND_NONE}}
};
@@ -5058,6 +5110,11 @@ FormatInstruction(
}
Tcl_AppendPrintfToObj(bufferObj, "%%v%u ", (unsigned) opnd);
break;
case OPERAND_SCLS1:
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
Tcl_AppendPrintfToObj(bufferObj, "%s ",
tclStringClassTable[opnd].name);
break;
case OPERAND_NONE:
default:
break;
@@ -5274,7 +5331,7 @@ PrintSourceToObj(
int maxChars) /* Maximum number of chars to print. */
{
register const char *p;
register int i = 0;
register int i = 0, len;
if (stringPtr == NULL) {
Tcl_AppendToObj(appendObj, "\"\"", -1);
@@ -5283,32 +5340,50 @@ PrintSourceToObj(
Tcl_AppendToObj(appendObj, "\"", -1);
p = stringPtr;
for (; (*p != '\0') && (i < maxChars); p++, i++) {
switch (*p) {
for (; (*p != '\0') && (i < maxChars); p+=len) {
Tcl_UniChar ch;
len = TclUtfToUniChar(p, &ch);
switch (ch) {
case '"':
Tcl_AppendToObj(appendObj, "\\\"", -1);
i += 2;
continue;
case '\f':
Tcl_AppendToObj(appendObj, "\\f", -1);
i += 2;
continue;
case '\n':
Tcl_AppendToObj(appendObj, "\\n", -1);
i += 2;
continue;
case '\r':
Tcl_AppendToObj(appendObj, "\\r", -1);
i += 2;
continue;
case '\t':
Tcl_AppendToObj(appendObj, "\\t", -1);
i += 2;
continue;
case '\v':
Tcl_AppendToObj(appendObj, "\\v", -1);
i += 2;
continue;
default:
Tcl_AppendPrintfToObj(appendObj, "%c", *p);
if (ch < 0x20 || ch >= 0x7f) {
Tcl_AppendPrintfToObj(appendObj, "\\u%04x", ch);
i += 6;
} else {
Tcl_AppendPrintfToObj(appendObj, "%c", ch);
i++;
}
continue;
}
}
Tcl_AppendToObj(appendObj, "\"", -1);
if (*p != '\0') {
Tcl_AppendToObj(appendObj, "...", -1);
}
}
#ifdef TCL_COMPILE_STATS
+55 -2
View File
@@ -751,6 +751,8 @@ typedef struct ByteCode {
#define INST_INFO_LEVEL_NUM 152
#define INST_INFO_LEVEL_ARGS 153
#define INST_RESOLVE_COMMAND 154
/* For compilation relating to TclOO */
#define INST_TCLOO_SELF 155
#define INST_TCLOO_CLASS 156
#define INST_TCLOO_NS 157
@@ -786,8 +788,24 @@ typedef struct ByteCode {
#define INST_STR_TITLE 176
#define INST_STR_REPLACE 177
#define INST_ORIGIN_COMMAND 178
#define INST_TCLOO_NEXT 179
#define INST_TCLOO_NEXT_CLASS 180
#define INST_YIELD_TO_INVOKE 181
#define INST_NUM_TYPE 182
#define INST_TRY_CVT_TO_BOOLEAN 183
#define INST_STR_CLASS 184
#define INST_LAPPEND_LIST 185
#define INST_LAPPEND_LIST_ARRAY 186
#define INST_LAPPEND_LIST_ARRAY_STK 187
#define INST_LAPPEND_LIST_STK 188
/* The last opcode */
#define LAST_INST_OPCODE 177
#define LAST_INST_OPCODE 188
/*
* Table describing the Tcl bytecode instructions: their name (for displaying
@@ -812,8 +830,9 @@ typedef enum InstOperandType {
* variable table. */
OPERAND_LVT4, /* Four byte unsigned index into the local
* variable table. */
OPERAND_AUX4 /* Four byte unsigned index into the aux data
OPERAND_AUX4, /* Four byte unsigned index into the aux data
* table. */
OPERAND_SCLS1 /* Index into tclStringClassTable. */
} InstOperandType;
typedef struct InstructionDesc {
@@ -831,6 +850,40 @@ typedef struct InstructionDesc {
MODULE_SCOPE InstructionDesc const tclInstructionTable[];
/*
* Constants used by INST_STRING_CLASS to indicate character classes. These
* correspond closely by name with what [string is] can support, but there is
* no requirement to keep the values the same.
*/
typedef enum InstStringClassType {
STR_CLASS_ALNUM, /* Unicode alphabet or digit characters. */
STR_CLASS_ALPHA, /* Unicode alphabet characters. */
STR_CLASS_ASCII, /* Characters in range U+000000..U+00007F. */
STR_CLASS_CONTROL, /* Unicode control characters. */
STR_CLASS_DIGIT, /* Unicode digit characters. */
STR_CLASS_GRAPH, /* Unicode printing characters, excluding
* space. */
STR_CLASS_LOWER, /* Unicode lower-case alphabet characters. */
STR_CLASS_PRINT, /* Unicode printing characters, including
* spaces. */
STR_CLASS_PUNCT, /* Unicode punctuation characters. */
STR_CLASS_SPACE, /* Unicode space characters. */
STR_CLASS_UPPER, /* Unicode upper-case alphabet characters. */
STR_CLASS_WORD, /* Unicode word (alphabetic, digit, connector
* punctuation) characters. */
STR_CLASS_XDIGIT /* Characters that can be used as digits in
* hexadecimal numbers ([0-9A-Fa-f]). */
} InstStringClassType;
typedef struct StringClassDesc {
const char *name; /* Name of the class. */
int (*comparator)(int); /* Function to test if a single unicode
* character is a member of the class. */
} StringClassDesc;
MODULE_SCOPE StringClassDesc const tclStringClassTable[];
/*
* Compilation of some Tcl constructs such as if commands and the logical or
* (||) and logical and (&&) operators in expressions requires the generation
+12 -12
View File
@@ -63,7 +63,7 @@ EXTERN void Tcl_DbCkfree(char *ptr, const char *file, int line);
/* 8 */
EXTERN char * Tcl_DbCkrealloc(char *ptr, unsigned int size,
const char *file, int line);
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
/* 9 */
EXTERN void Tcl_CreateFileHandler(int fd, int mask,
Tcl_FileProc *proc, ClientData clientData);
@@ -73,7 +73,7 @@ EXTERN void Tcl_CreateFileHandler(int fd, int mask,
EXTERN void Tcl_CreateFileHandler(int fd, int mask,
Tcl_FileProc *proc, ClientData clientData);
#endif /* MACOSX */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
/* 10 */
EXTERN void Tcl_DeleteFileHandler(int fd);
#endif /* UNIX */
@@ -511,7 +511,7 @@ EXTERN Tcl_Interp * Tcl_GetMaster(Tcl_Interp *interp);
EXTERN const char * Tcl_GetNameOfExecutable(void);
/* 166 */
EXTERN Tcl_Obj * Tcl_GetObjResult(Tcl_Interp *interp);
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
/* 167 */
EXTERN int Tcl_GetOpenFile(Tcl_Interp *interp,
const char *chanID, int forWriting,
@@ -1835,19 +1835,19 @@ typedef struct TclStubs {
char * (*tcl_DbCkalloc) (unsigned int size, const char *file, int line); /* 6 */
void (*tcl_DbCkfree) (char *ptr, const char *file, int line); /* 7 */
char * (*tcl_DbCkrealloc) (char *ptr, unsigned int size, const char *file, int line); /* 8 */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
void (*tcl_CreateFileHandler) (int fd, int mask, Tcl_FileProc *proc, ClientData clientData); /* 9 */
#endif /* UNIX */
#if defined(__WIN32__) /* WIN */
#if defined(_WIN32) /* WIN */
void (*reserved9)(void);
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
void (*tcl_CreateFileHandler) (int fd, int mask, Tcl_FileProc *proc, ClientData clientData); /* 9 */
#endif /* MACOSX */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
void (*tcl_DeleteFileHandler) (int fd); /* 10 */
#endif /* UNIX */
#if defined(__WIN32__) /* WIN */
#if defined(_WIN32) /* WIN */
void (*reserved10)(void);
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
@@ -2009,10 +2009,10 @@ typedef struct TclStubs {
Tcl_Interp * (*tcl_GetMaster) (Tcl_Interp *interp); /* 164 */
const char * (*tcl_GetNameOfExecutable) (void); /* 165 */
Tcl_Obj * (*tcl_GetObjResult) (Tcl_Interp *interp); /* 166 */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
int (*tcl_GetOpenFile) (Tcl_Interp *interp, const char *chanID, int forWriting, int checkUsage, ClientData *filePtr); /* 167 */
#endif /* UNIX */
#if defined(__WIN32__) /* WIN */
#if defined(_WIN32) /* WIN */
void (*reserved167)(void);
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
@@ -2513,7 +2513,7 @@ extern const TclStubs *tclStubsPtr;
(tclStubsPtr->tcl_DbCkfree) /* 7 */
#define Tcl_DbCkrealloc \
(tclStubsPtr->tcl_DbCkrealloc) /* 8 */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
#define Tcl_CreateFileHandler \
(tclStubsPtr->tcl_CreateFileHandler) /* 9 */
#endif /* UNIX */
@@ -2521,7 +2521,7 @@ extern const TclStubs *tclStubsPtr;
#define Tcl_CreateFileHandler \
(tclStubsPtr->tcl_CreateFileHandler) /* 9 */
#endif /* MACOSX */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
#define Tcl_DeleteFileHandler \
(tclStubsPtr->tcl_DeleteFileHandler) /* 10 */
#endif /* UNIX */
@@ -2841,7 +2841,7 @@ extern const TclStubs *tclStubsPtr;
(tclStubsPtr->tcl_GetNameOfExecutable) /* 165 */
#define Tcl_GetObjResult \
(tclStubsPtr->tcl_GetObjResult) /* 166 */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
#define Tcl_GetOpenFile \
(tclStubsPtr->tcl_GetOpenFile) /* 167 */
#endif /* UNIX */
+133 -151
View File
@@ -154,6 +154,13 @@ typedef struct Dict {
* dictionaries. */
} Dict;
/*
* Accessor macro for converting between a Tcl_Obj* and a Dict. Note that this
* must be assignable as well as readable.
*/
#define DICT(dictObj) (*((Dict **)&(dictObj)->internalRep.twoPtrValue.ptr1))
/*
* The structure below defines the dictionary object type by means of
* functions that can be invoked by generic object code.
@@ -312,6 +319,7 @@ DeleteChainEntry(
return 0;
} else {
Tcl_Obj *valuePtr = Tcl_GetHashValue(&cPtr->entry);
TclDecrRefCount(valuePtr);
}
@@ -361,7 +369,7 @@ DupDictInternalRep(
Tcl_Obj *srcPtr,
Tcl_Obj *copyPtr)
{
Dict *oldDict = srcPtr->internalRep.twoPtrValue.ptr1;
Dict *oldDict = DICT(srcPtr);
Dict *newDict = ckalloc(sizeof(Dict));
ChainEntry *cPtr;
@@ -396,7 +404,8 @@ DupDictInternalRep(
* Store in the object.
*/
copyPtr->internalRep.twoPtrValue.ptr1 = newDict;
DICT(copyPtr) = newDict;
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
copyPtr->typePtr = &tclDictType;
}
@@ -422,7 +431,7 @@ static void
FreeDictInternalRep(
Tcl_Obj *dictPtr)
{
Dict *dict = dictPtr->internalRep.twoPtrValue.ptr1;
Dict *dict = DICT(dictPtr);
dict->refcount--;
if (dict->refcount <= 0) {
@@ -487,7 +496,7 @@ UpdateStringOfDict(
{
#define LOCAL_SIZE 20
int localFlags[LOCAL_SIZE], *flagPtr = NULL;
Dict *dict = dictPtr->internalRep.twoPtrValue.ptr1;
Dict *dict = DICT(dictPtr);
ChainEntry *cPtr;
Tcl_Obj *keyPtr, *valuePtr;
int i, length, bytesNeeded = 0;
@@ -600,7 +609,7 @@ SetDictFromAny(
Tcl_Obj *objPtr)
{
Tcl_HashEntry *hPtr;
int isNew, result;
int isNew;
Dict *dict = ckalloc(sizeof(Dict));
InitChainTable(dict);
@@ -651,10 +660,9 @@ SetDictFromAny(
const char *elemStart;
int elemSize, literal;
result = TclFindElement(interp, nextElem, (limit - nextElem),
&elemStart, &nextElem, &elemSize, &literal);
if (result != TCL_OK) {
goto errorExit;
if (TclFindDictElement(interp, nextElem, (limit - nextElem),
&elemStart, &nextElem, &elemSize, &literal) != TCL_OK) {
goto errorInFindDictElement;
}
if (elemStart == limit) {
break;
@@ -673,11 +681,10 @@ SetDictFromAny(
keyPtr->bytes);
}
result = TclFindElement(interp, nextElem, (limit - nextElem),
&elemStart, &nextElem, &elemSize, &literal);
if (result != TCL_OK) {
if (TclFindDictElement(interp, nextElem, (limit - nextElem),
&elemStart, &nextElem, &elemSize, &literal) != TCL_OK) {
TclDecrRefCount(keyPtr);
goto errorExit;
goto errorInFindDictElement;
}
if (literal) {
@@ -713,7 +720,8 @@ SetDictFromAny(
dict->epoch = 0;
dict->chain = NULL;
dict->refcount = 1;
objPtr->internalRep.twoPtrValue.ptr1 = dict;
DICT(objPtr) = dict;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = &tclDictType;
return TCL_OK;
@@ -723,15 +731,10 @@ SetDictFromAny(
"missing value to go with key", -1));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL);
}
result = TCL_ERROR;
errorExit:
if (interp != NULL) {
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL);
}
errorInFindDictElement:
DeleteChainTable(dict);
ckfree(dict);
return result;
return TCL_ERROR;
}
/*
@@ -777,12 +780,11 @@ TclTraceDictPath(
Dict *dict, *newDict;
int i;
if (dictPtr->typePtr != &tclDictType) {
if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
return NULL;
}
if (dictPtr->typePtr != &tclDictType
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
return NULL;
}
dict = dictPtr->internalRep.twoPtrValue.ptr1;
dict = DICT(dictPtr);
if (flags & DICT_PATH_UPDATE) {
dict->chain = NULL;
}
@@ -818,14 +820,13 @@ TclTraceDictPath(
Tcl_SetHashValue(hPtr, tmpObj);
} else {
tmpObj = Tcl_GetHashValue(hPtr);
if (tmpObj->typePtr != &tclDictType) {
if (SetDictFromAny(interp, tmpObj) != TCL_OK) {
return NULL;
}
if (tmpObj->typePtr != &tclDictType
&& SetDictFromAny(interp, tmpObj) != TCL_OK) {
return NULL;
}
}
newDict = tmpObj->internalRep.twoPtrValue.ptr1;
newDict = DICT(tmpObj);
if (flags & DICT_PATH_UPDATE) {
if (Tcl_IsShared(tmpObj)) {
TclDecrRefCount(tmpObj);
@@ -833,7 +834,7 @@ TclTraceDictPath(
Tcl_IncrRefCount(tmpObj);
Tcl_SetHashValue(hPtr, tmpObj);
dict->epoch++;
newDict = tmpObj->internalRep.twoPtrValue.ptr1;
newDict = DICT(tmpObj);
}
newDict->chain = dictPtr;
@@ -868,7 +869,7 @@ static void
InvalidateDictChain(
Tcl_Obj *dictObj)
{
Dict *dict = dictObj->internalRep.twoPtrValue.ptr1;
Dict *dict = DICT(dictObj);
do {
TclInvalidateStringRep(dictObj);
@@ -878,7 +879,7 @@ InvalidateDictChain(
break;
}
dict->chain = NULL;
dict = dictObj->internalRep.twoPtrValue.ptr1;
dict = DICT(dictObj);
} while (dict != NULL);
}
@@ -916,18 +917,15 @@ Tcl_DictObjPut(
Tcl_Panic("%s called with shared object", "Tcl_DictObjPut");
}
if (dictPtr->typePtr != &tclDictType) {
int result = SetDictFromAny(interp, dictPtr);
if (result != TCL_OK) {
return result;
}
if (dictPtr->typePtr != &tclDictType
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
return TCL_ERROR;
}
if (dictPtr->bytes != NULL) {
TclInvalidateStringRep(dictPtr);
}
dict = dictPtr->internalRep.twoPtrValue.ptr1;
dict = DICT(dictPtr);
hPtr = CreateChainEntry(dict, keyPtr, &isNew);
Tcl_IncrRefCount(valuePtr);
if (!isNew) {
@@ -970,15 +968,13 @@ Tcl_DictObjGet(
Dict *dict;
Tcl_HashEntry *hPtr;
if (dictPtr->typePtr != &tclDictType) {
int result = SetDictFromAny(interp, dictPtr);
if (result != TCL_OK) {
*valuePtrPtr = NULL;
return result;
}
if (dictPtr->typePtr != &tclDictType
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
*valuePtrPtr = NULL;
return TCL_ERROR;
}
dict = dictPtr->internalRep.twoPtrValue.ptr1;
dict = DICT(dictPtr);
hPtr = Tcl_FindHashEntry(&dict->table, keyPtr);
if (hPtr == NULL) {
*valuePtrPtr = NULL;
@@ -1019,18 +1015,16 @@ Tcl_DictObjRemove(
Tcl_Panic("%s called with shared object", "Tcl_DictObjRemove");
}
if (dictPtr->typePtr != &tclDictType) {
int result = SetDictFromAny(interp, dictPtr);
if (result != TCL_OK) {
return result;
}
if (dictPtr->typePtr != &tclDictType
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
return TCL_ERROR;
}
if (dictPtr->bytes != NULL) {
TclInvalidateStringRep(dictPtr);
}
dict = dictPtr->internalRep.twoPtrValue.ptr1;
dict = DICT(dictPtr);
if (DeleteChainEntry(dict, keyPtr)) {
if (dictPtr->bytes != NULL) {
TclInvalidateStringRep(dictPtr);
}
dict->epoch++;
}
return TCL_OK;
@@ -1062,14 +1056,12 @@ Tcl_DictObjSize(
{
Dict *dict;
if (dictPtr->typePtr != &tclDictType) {
int result = SetDictFromAny(interp, dictPtr);
if (result != TCL_OK) {
return result;
}
if (dictPtr->typePtr != &tclDictType
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
return TCL_ERROR;
}
dict = dictPtr->internalRep.twoPtrValue.ptr1;
dict = DICT(dictPtr);
*sizePtr = dict->table.numEntries;
return TCL_OK;
}
@@ -1116,15 +1108,12 @@ Tcl_DictObjFirst(
Dict *dict;
ChainEntry *cPtr;
if (dictPtr->typePtr != &tclDictType) {
int result = SetDictFromAny(interp, dictPtr);
if (result != TCL_OK) {
return result;
}
if (dictPtr->typePtr != &tclDictType
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
return TCL_ERROR;
}
dict = dictPtr->internalRep.twoPtrValue.ptr1;
dict = DICT(dictPtr);
cPtr = dict->entryChainHead;
if (cPtr == NULL) {
searchPtr->epoch = -1;
@@ -1299,11 +1288,12 @@ Tcl_DictObjPutKeyList(
return TCL_ERROR;
}
dict = dictPtr->internalRep.twoPtrValue.ptr1;
dict = DICT(dictPtr);
hPtr = CreateChainEntry(dict, keyv[keyc-1], &isNew);
Tcl_IncrRefCount(valuePtr);
if (!isNew) {
Tcl_Obj *oldValuePtr = Tcl_GetHashValue(hPtr);
TclDecrRefCount(oldValuePtr);
}
Tcl_SetHashValue(hPtr, valuePtr);
@@ -1355,7 +1345,7 @@ Tcl_DictObjRemoveKeyList(
return TCL_ERROR;
}
dict = dictPtr->internalRep.twoPtrValue.ptr1;
dict = DICT(dictPtr);
DeleteChainEntry(dict, keyv[keyc-1]);
InvalidateDictChain(dictPtr);
return TCL_OK;
@@ -1401,7 +1391,8 @@ Tcl_NewDictObj(void)
dict->epoch = 0;
dict->chain = NULL;
dict->refcount = 1;
dictPtr->internalRep.twoPtrValue.ptr1 = dict;
DICT(dictPtr) = dict;
dictPtr->internalRep.twoPtrValue.ptr2 = NULL;
dictPtr->typePtr = &tclDictType;
return dictPtr;
#endif
@@ -1450,7 +1441,8 @@ Tcl_DbNewDictObj(
dict->epoch = 0;
dict->chain = NULL;
dict->refcount = 1;
dictPtr->internalRep.twoPtrValue.ptr1 = dict;
DICT(dictPtr) = dict;
dictPtr->internalRep.twoPtrValue.ptr2 = NULL;
dictPtr->typePtr = &tclDictType;
return dictPtr;
#else /* !TCL_MEM_DEBUG */
@@ -1504,7 +1496,7 @@ DictCreateCmd(
/*
* The next command is assumed to never fail...
*/
Tcl_DictObjPut(interp, dictObj, objv[i], objv[i+1]);
Tcl_DictObjPut(NULL, dictObj, objv[i], objv[i+1]);
}
Tcl_SetObjResult(interp, dictObj);
return TCL_OK;
@@ -1629,8 +1621,7 @@ DictReplaceCmd(
Tcl_Obj *const *objv)
{
Tcl_Obj *dictPtr;
int i, result;
int allocatedDict = 0;
int i;
if ((objc < 2) || (objc & 1)) {
Tcl_WrongNumArgs(interp, 1, objv, "dictionary ?key value ...?");
@@ -1638,18 +1629,18 @@ DictReplaceCmd(
}
dictPtr = objv[1];
if (dictPtr->typePtr != &tclDictType
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_IsShared(dictPtr)) {
dictPtr = Tcl_DuplicateObj(dictPtr);
allocatedDict = 1;
}
if (dictPtr->bytes != NULL) {
TclInvalidateStringRep(dictPtr);
}
for (i=2 ; i<objc ; i+=2) {
result = Tcl_DictObjPut(interp, dictPtr, objv[i], objv[i+1]);
if (result != TCL_OK) {
if (allocatedDict) {
TclDecrRefCount(dictPtr);
}
return TCL_ERROR;
}
Tcl_DictObjPut(NULL, dictPtr, objv[i], objv[i+1]);
}
Tcl_SetObjResult(interp, dictPtr);
return TCL_OK;
@@ -1681,8 +1672,7 @@ DictRemoveCmd(
Tcl_Obj *const *objv)
{
Tcl_Obj *dictPtr;
int i, result;
int allocatedDict = 0;
int i;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "dictionary ?key ...?");
@@ -1690,18 +1680,18 @@ DictRemoveCmd(
}
dictPtr = objv[1];
if (dictPtr->typePtr != &tclDictType
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_IsShared(dictPtr)) {
dictPtr = Tcl_DuplicateObj(dictPtr);
allocatedDict = 1;
}
if (dictPtr->bytes != NULL) {
TclInvalidateStringRep(dictPtr);
}
for (i=2 ; i<objc ; i++) {
result = Tcl_DictObjRemove(interp, dictPtr, objv[i]);
if (result != TCL_OK) {
if (allocatedDict) {
TclDecrRefCount(dictPtr);
}
return TCL_ERROR;
}
Tcl_DictObjRemove(NULL, dictPtr, objv[i]);
}
Tcl_SetObjResult(interp, dictPtr);
return TCL_OK;
@@ -1750,10 +1740,9 @@ DictMergeCmd(
*/
targetObj = objv[1];
if (targetObj->typePtr != &tclDictType) {
if (SetDictFromAny(interp, targetObj) != TCL_OK) {
return TCL_ERROR;
}
if (targetObj->typePtr != &tclDictType
&& SetDictFromAny(interp, targetObj) != TCL_OK) {
return TCL_ERROR;
}
if (objc == 2) {
@@ -1835,12 +1824,9 @@ DictKeysCmd(
* need. [Bug 1705778, leak K04]
*/
if (objv[1]->typePtr != &tclDictType) {
int result = SetDictFromAny(interp, objv[1]);
if (result != TCL_OK) {
return result;
}
if (objv[1]->typePtr != &tclDictType
&& SetDictFromAny(interp, objv[1]) != TCL_OK) {
return TCL_ERROR;
}
if (objc == 3) {
@@ -2056,13 +2042,11 @@ DictInfoCmd(
}
dictPtr = objv[1];
if (dictPtr->typePtr != &tclDictType) {
int result = SetDictFromAny(interp, dictPtr);
if (result != TCL_OK) {
return result;
}
if (dictPtr->typePtr != &tclDictType
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
return TCL_ERROR;
}
dict = dictPtr->internalRep.twoPtrValue.ptr1;
dict = DICT(dictPtr);
statsStr = Tcl_HashStats(&dict->table);
Tcl_SetObjResult(interp, Tcl_NewStringObj(statsStr, -1));
@@ -2099,7 +2083,7 @@ DictIncrCmd(
Tcl_Obj *dictPtr, *valuePtr = NULL;
if (objc < 3 || objc > 4) {
Tcl_WrongNumArgs(interp, 1, objv, "varName key ?increment?");
Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?increment?");
return TCL_ERROR;
}
@@ -2152,10 +2136,10 @@ DictIncrCmd(
*/
mp_clear(&increment);
Tcl_DictObjPut(interp, dictPtr, objv[2], objv[3]);
Tcl_DictObjPut(NULL, dictPtr, objv[2], objv[3]);
}
} else {
Tcl_DictObjPut(interp, dictPtr, objv[2], Tcl_NewIntObj(1));
Tcl_DictObjPut(NULL, dictPtr, objv[2], Tcl_NewIntObj(1));
}
} else {
/*
@@ -2164,7 +2148,7 @@ DictIncrCmd(
if (Tcl_IsShared(valuePtr)) {
valuePtr = Tcl_DuplicateObj(valuePtr);
Tcl_DictObjPut(interp, dictPtr, objv[2], valuePtr);
Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr);
}
if (objc == 4) {
code = TclIncrObj(interp, valuePtr, objv[3]);
@@ -2173,7 +2157,7 @@ DictIncrCmd(
Tcl_IncrRefCount(incrPtr);
code = TclIncrObj(interp, valuePtr, incrPtr);
Tcl_DecrRefCount(incrPtr);
TclDecrRefCount(incrPtr);
}
}
if (code == TCL_OK) {
@@ -2186,7 +2170,7 @@ DictIncrCmd(
Tcl_SetObjResult(interp, valuePtr);
}
} else if (dictPtr->refCount == 0) {
Tcl_DecrRefCount(dictPtr);
TclDecrRefCount(dictPtr);
}
return code;
}
@@ -2220,7 +2204,7 @@ DictLappendCmd(
int i, allocatedDict = 0, allocatedValue = 0;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "varName key ?value ...?");
Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?value ...?");
return TCL_ERROR;
}
@@ -2264,7 +2248,7 @@ DictLappendCmd(
}
if (allocatedValue) {
Tcl_DictObjPut(interp, dictPtr, objv[2], valuePtr);
Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr);
} else if (dictPtr->bytes != NULL) {
TclInvalidateStringRep(dictPtr);
}
@@ -2307,7 +2291,7 @@ DictAppendCmd(
int i, allocatedDict = 0;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "varName key ?value ...?");
Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?value ...?");
return TCL_ERROR;
}
@@ -2329,17 +2313,15 @@ DictAppendCmd(
if (valuePtr == NULL) {
TclNewObj(valuePtr);
} else {
if (Tcl_IsShared(valuePtr)) {
valuePtr = Tcl_DuplicateObj(valuePtr);
}
} else if (Tcl_IsShared(valuePtr)) {
valuePtr = Tcl_DuplicateObj(valuePtr);
}
for (i=3 ; i<objc ; i++) {
Tcl_AppendObjToObj(valuePtr, objv[i]);
}
Tcl_DictObjPut(interp, dictPtr, objv[2], valuePtr);
Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr);
resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
@@ -2383,7 +2365,7 @@ DictForNRCmd(
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv,
"{keyVar valueVar} dictionary script");
"{keyVarName valueVarName} dictionary script");
return TCL_ERROR;
}
@@ -2397,6 +2379,7 @@ DictForNRCmd(
if (varc != 2) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"must have exactly two variable names", -1));
Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "for", NULL);
return TCL_ERROR;
}
searchPtr = TclStackAlloc(interp, sizeof(Tcl_DictSearch));
@@ -2430,12 +2413,14 @@ DictForNRCmd(
*/
Tcl_IncrRefCount(valueObj);
if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj, TCL_LEAVE_ERR_MSG) == NULL) {
if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj,
TCL_LEAVE_ERR_MSG) == NULL) {
TclDecrRefCount(valueObj);
goto error;
}
TclDecrRefCount(valueObj);
if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj, TCL_LEAVE_ERR_MSG) == NULL) {
if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj,
TCL_LEAVE_ERR_MSG) == NULL) {
goto error;
}
@@ -2574,7 +2559,7 @@ DictMapNRCmd(
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv,
"{keyVar valueVar} dictionary script");
"{keyVarName valueVarName} dictionary script");
return TCL_ERROR;
}
@@ -2588,6 +2573,7 @@ DictMapNRCmd(
if (varc != 2) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"must have exactly two variable names", -1));
Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "map", NULL);
return TCL_ERROR;
}
storagePtr = TclStackAlloc(interp, sizeof(DictMapStorage));
@@ -2782,7 +2768,7 @@ DictSetCmd(
int result, allocatedDict = 0;
if (objc < 4) {
Tcl_WrongNumArgs(interp, 1, objv, "varName key ?key ...? value");
Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?key ...? value");
return TCL_ERROR;
}
@@ -2842,7 +2828,7 @@ DictUnsetCmd(
int result, allocatedDict = 0;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "varName key ?key ...?");
Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?key ...?");
return TCL_ERROR;
}
@@ -2949,12 +2935,12 @@ DictFilterCmd(
Tcl_DictObjDone(&search);
Tcl_DictObjGet(interp, objv[1], objv[3], &valueObj);
if (valueObj != NULL) {
Tcl_DictObjPut(interp, resultObj, objv[3], valueObj);
Tcl_DictObjPut(NULL, resultObj, objv[3], valueObj);
}
} else {
while (!done) {
if (Tcl_StringMatch(TclGetString(keyObj), pattern)) {
Tcl_DictObjPut(interp, resultObj, keyObj, valueObj);
Tcl_DictObjPut(NULL, resultObj, keyObj, valueObj);
}
Tcl_DictObjNext(&search, &keyObj, &valueObj, &done);
}
@@ -2972,7 +2958,7 @@ DictFilterCmd(
for (i=3 ; i<objc ; i++) {
pattern = TclGetString(objv[i]);
if (Tcl_StringMatch(TclGetString(keyObj), pattern)) {
Tcl_DictObjPut(interp, resultObj, keyObj, valueObj);
Tcl_DictObjPut(NULL, resultObj, keyObj, valueObj);
break; /* stop inner loop */
}
}
@@ -2998,7 +2984,7 @@ DictFilterCmd(
for (i=3 ; i<objc ; i++) {
pattern = TclGetString(objv[i]);
if (Tcl_StringMatch(TclGetString(valueObj), pattern)) {
Tcl_DictObjPut(interp, resultObj, keyObj, valueObj);
Tcl_DictObjPut(NULL, resultObj, keyObj, valueObj);
break; /* stop inner loop */
}
}
@@ -3010,7 +2996,7 @@ DictFilterCmd(
case FILTER_SCRIPT:
if (objc != 5) {
Tcl_WrongNumArgs(interp, 1, objv,
"dictionary script {keyVar valueVar} filterScript");
"dictionary script {keyVarName valueVarName} filterScript");
return TCL_ERROR;
}
@@ -3026,6 +3012,7 @@ DictFilterCmd(
if (varc != 2) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"must have exactly two variable names", -1));
Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "filter", NULL);
return TCL_ERROR;
}
keyVarObj = varv[0];
@@ -3064,19 +3051,15 @@ DictFilterCmd(
Tcl_IncrRefCount(valueObj);
if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj,
TCL_LEAVE_ERR_MSG) == NULL) {
Tcl_ResetResult(interp);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't set key variable: \"%s\"",
TclGetString(keyVarObj)));
Tcl_AddErrorInfo(interp,
"\n (\"dict filter\" filter script key variable)");
result = TCL_ERROR;
goto abnormalResult;
}
if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj,
TCL_LEAVE_ERR_MSG) == NULL) {
Tcl_ResetResult(interp);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't set value variable: \"%s\"",
TclGetString(valueVarObj)));
Tcl_AddErrorInfo(interp,
"\n (\"dict filter\" filter script value variable)");
result = TCL_ERROR;
goto abnormalResult;
}
@@ -3099,7 +3082,7 @@ DictFilterCmd(
}
TclDecrRefCount(boolObj);
if (satisfied) {
Tcl_DictObjPut(interp, resultObj, keyObj, valueObj);
Tcl_DictObjPut(NULL, resultObj, keyObj, valueObj);
}
break;
case TCL_BREAK:
@@ -3190,7 +3173,7 @@ DictUpdateCmd(
if (objc < 5 || !(objc & 1)) {
Tcl_WrongNumArgs(interp, 1, objv,
"varName key varName ?key varName ...? script");
"dictVarName key varName ?key varName ...? script");
return TCL_ERROR;
}
@@ -3287,18 +3270,17 @@ FinalizeDictUpdate(
for (i=0 ; i<objc ; i+=2) {
objPtr = Tcl_ObjGetVar2(interp, objv[i+1], NULL, 0);
if (objPtr == NULL) {
Tcl_DictObjRemove(interp, dictPtr, objv[i]);
Tcl_DictObjRemove(NULL, dictPtr, objv[i]);
} else if (objPtr == dictPtr) {
/*
* Someone is messing us around, trying to build a recursive
* structure. [Bug 1786481]
*/
Tcl_DictObjPut(interp, dictPtr, objv[i],
Tcl_DuplicateObj(objPtr));
Tcl_DictObjPut(NULL, dictPtr, objv[i], Tcl_DuplicateObj(objPtr));
} else {
/* Shouldn't fail */
Tcl_DictObjPut(interp, dictPtr, objv[i], objPtr);
Tcl_DictObjPut(NULL, dictPtr, objv[i], objPtr);
}
}
TclDecrRefCount(argsObj);
@@ -3347,7 +3329,7 @@ DictWithCmd(
Tcl_Obj *dictPtr, *keysPtr, *pathPtr;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "dictVar ?key ...? script");
Tcl_WrongNumArgs(interp, 1, objv, "dictVarName ?key ...? script");
return TCL_ERROR;
}
+3 -1
View File
@@ -182,6 +182,7 @@ TCL_DECLARE_MUTEX(encodingMutex)
static Tcl_Encoding defaultEncoding;
static Tcl_Encoding systemEncoding;
Tcl_Encoding tclIdentityEncoding;
/*
* The following variable is used in the sparse matrix code for a
@@ -567,7 +568,7 @@ TclInitEncodingSubsystem(void)
type.freeProc = NULL;
type.nullSize = 1;
type.clientData = NULL;
Tcl_CreateEncoding(&type);
tclIdentityEncoding = Tcl_CreateEncoding(&type);
type.encodingName = "utf-8";
type.toUtfProc = UtfExtToUtfIntProc;
@@ -651,6 +652,7 @@ TclFinalizeEncodingSubsystem(void)
Tcl_MutexLock(&encodingMutex);
encodingsInitialized = 0;
FreeEncoding(systemEncoding);
FreeEncoding(tclIdentityEncoding);
hPtr = Tcl_FirstHashEntry(&encodingTable, &search);
while (hPtr != NULL) {
+52 -8
View File
@@ -2749,15 +2749,9 @@ TclCompileEnsemble(
int ourResult = TCL_ERROR;
unsigned numBytes;
const char *word;
DefineLineInformation;
Tcl_IncrRefCount(replaced);
/*
* This is where we return to if we are parsing multiple nested compiled
* ensembles. [info object] is such a beast.
*/
checkNextWord:
if (parsePtr->numWords < depth + 1) {
goto failed;
}
@@ -2769,6 +2763,12 @@ TclCompileEnsemble(
goto failed;
}
/*
* This is where we return to if we are parsing multiple nested compiled
* ensembles. [info object] is such a beast.
*/
checkNextWord:
word = tokenPtr[1].start;
numBytes = tokenPtr[1].size;
@@ -2979,6 +2979,17 @@ TclCompileEnsemble(
if (cmdPtr->compileProc == TclCompileEnsemble) {
tokenPtr = TokenAfter(tokenPtr);
if (parsePtr->numWords < depth + 1
|| tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
/*
* Too hard because the user has done something unpleasant like
* omitting the sub-ensemble's command name or used a non-constant
* name for a sub-ensemble's command name; we respond by bailing
* out completely (this is a rare case). [Bug 6d2f249a01]
*/
goto cleanup;
}
ensemble = (Tcl_Command) cmdPtr;
goto checkNextWord;
}
@@ -2997,6 +3008,23 @@ TclCompileEnsemble(
goto cleanup;
}
/*
* Throw out any line information generated by the failed compile attempt.
*/
while (mapPtr->nuloc - 1 > eclIndex) {
mapPtr->nuloc--;
ckfree(mapPtr->loc[mapPtr->nuloc].line);
mapPtr->loc[mapPtr->nuloc].line = NULL;
}
/*
* Reset the index of next command. Toss out any from failed nested
* partial compiles.
*/
envPtr->numCommands = mapPtr->nuloc;
/*
* Failed to do a full compile for some reason. Try to do a direct invoke
* instead of going through the ensemble lookup process again.
@@ -3009,8 +3037,24 @@ TclCompileEnsemble(
cmdPtr = oldCmdPtr;
depth--;
}
(void) Tcl_ListObjReplace(NULL, replaced, depth, 2, 0, NULL);
}
/*
* The length of the "replaced" list must be depth-1. Trim back
* any extra elements that might have been appended by failing
* pathways above.
*/
(void) Tcl_ListObjReplace(NULL, replaced, depth-1, INT_MAX, 0, NULL);
/*
* TODO: Reconsider whether we ought to call CompileToInvokedCommand()
* when depth==1. In that case we are choosing to emit the
* INST_INVOKE_REPLACE bytecode when there is in fact no replacing
* to be done. It would be equally functional and presumably more
* performant to fall through to cleanup below, return TCL_ERROR,
* and let the compiler harness emit the INST_INVOKE_STK
* implementation for us.
*/
CompileToInvokedCommand(interp, parsePtr, replaced, cmdPtr, envPtr);
ourResult = TCL_OK;
}
+2 -2
View File
@@ -444,7 +444,7 @@ TclUnsetEnv(
* that no = should be included, and Windows requires it.
*/
#if defined(__WIN32__) || defined(__CYGWIN__)
#if defined(_WIN32) || defined(__CYGWIN__)
string = ckalloc(length + 2);
memcpy(string, name, (size_t) length);
string[length] = '=';
@@ -453,7 +453,7 @@ TclUnsetEnv(
string = ckalloc(length + 1);
memcpy(string, name, (size_t) length);
string[length] = '\0';
#endif /* WIN32 */
#endif /* _WIN32 */
Tcl_UtfToExternalDString(NULL, string, -1, &envString);
string = ckrealloc(string, Tcl_DStringLength(&envString) + 1);
+13 -11
View File
@@ -1299,18 +1299,20 @@ Tcl_FinalizeThread(void)
TclFinalizeAsync();
TclFinalizeThreadObjects();
}
if (TclFullFinalizationRequested()) { /* useless if we are facing a quick-exit */
/*
* Blow away all thread local storage blocks.
*
* Note that Tcl API allows creation of threads which do not use any Tcl
* interp or other Tcl subsytems. Those threads might, however, use thread
* local storage, so we must unconditionally finalize it.
*
* Fix [Bug #571002]
*/
TclFinalizeThreadData();
/*
* Blow away all thread local storage blocks.
*
* Note that Tcl API allows creation of threads which do not use any Tcl
* interp or other Tcl subsytems. Those threads might, however, use thread
* local storage, so we must unconditionally finalize it.
*
* Fix [Bug #571002]
*/
TclFinalizeThreadData();
}
}
/*
+1135 -492
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -517,7 +517,7 @@ CopyRenameOneFile(
* 16 bits and we get collisions. See bug #2015723.
*/
#if !defined(WIN32) && !defined(__CYGWIN__)
#if !defined(_WIN32) && !defined(__CYGWIN__)
if ((sourceStatBuf.st_ino != 0) && (targetStatBuf.st_ino != 0)) {
if ((sourceStatBuf.st_ino == targetStatBuf.st_ino) &&
(sourceStatBuf.st_dev == targetStatBuf.st_dev)) {
@@ -1196,7 +1196,7 @@ TclFileLinkCmd(
static const char *const linkTypes[] = {
"-symbolic", "-hard", NULL
};
if (Tcl_GetIndexFromObj(interp, objv[1], linkTypes, "switch", 0,
if (Tcl_GetIndexFromObj(interp, objv[1], linkTypes, "option", 0,
&linkAction) != TCL_OK) {
return TCL_ERROR;
}
+1474 -2010
View File
File diff suppressed because it is too large Load Diff
+3 -31
View File
@@ -36,6 +36,7 @@
*/
typedef struct ChannelBuffer {
int refCount; /* Current uses count */
int nextAdded; /* The next position into which a character
* will be put in the buffer. */
int nextRemoved; /* Position of next byte to be removed from
@@ -111,6 +112,8 @@ typedef struct Channel {
ChannelBuffer *inQueueHead; /* Points at first buffer in input queue. */
ChannelBuffer *inQueueTail; /* Points at last buffer in input queue. */
int refCount;
} Channel;
/*
@@ -226,11 +229,6 @@ typedef struct ChannelState {
* flushed after every newline. */
#define CHANNEL_UNBUFFERED (1<<5) /* Output to the channel must always
* be flushed immediately. */
#define BUFFER_READY (1<<6) /* Current output buffer (the
* curOutPtr field in the channel
* structure) should be output as soon
* as possible even though it may not
* be full. */
#define BG_FLUSH_SCHEDULED (1<<7) /* A background flush of the queued
* output buffers has been
* scheduled. */
@@ -252,9 +250,6 @@ typedef struct ChannelState {
#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
@@ -274,29 +269,6 @@ typedef struct ChannelState {
* changes. */
#define CHANNEL_RAW_MODE (1<<16) /* When set, notes that the Raw API is
* being used. */
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
#define CHANNEL_TIMER_FEV (1<<17) /* When set the event we are notified
* by is a fileevent generated by a
* timer. We don't know if the driver
* has more data and should not try to
* read from it. If the system needs
* more than is in the buffers out
* read routines will simulate a short
* read (0 characters read) */
#define CHANNEL_HAS_MORE_DATA (1<<18) /* Set by NotifyChannel for a channel
* if and only if the channel is
* configured non-blocking, the driver
* for said channel has no
* blockmodeproc, and data has arrived
* for reading at the OS level). A
* GetInput will pass reading from the
* driver if the channel is
* non-blocking, without blockmode
* proc and the flag has not been set.
* A read will be performed if the
* flag is set. This will reset the
* flag as well. */
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
#define CHANNEL_INCLOSE (1<<19) /* Channel is currently being closed.
* Its structures are still live and
+30 -7
View File
@@ -181,6 +181,7 @@ Tcl_PutsObjCmd(
return TCL_ERROR;
}
TclChannelPreserve(chan);
result = Tcl_WriteObj(chan, string);
if (result < 0) {
goto error;
@@ -191,6 +192,7 @@ Tcl_PutsObjCmd(
goto error;
}
}
TclChannelRelease(chan);
return TCL_OK;
/*
@@ -205,6 +207,7 @@ Tcl_PutsObjCmd(
Tcl_SetObjResult(interp, Tcl_ObjPrintf("error writing \"%s\": %s",
TclGetString(chanObjPtr), Tcl_PosixError(interp)));
}
TclChannelRelease(chan);
return TCL_ERROR;
}
@@ -252,6 +255,7 @@ Tcl_FlushObjCmd(
return TCL_ERROR;
}
TclChannelPreserve(chan);
if (Tcl_Flush(chan) != TCL_OK) {
/*
* TIP #219.
@@ -265,8 +269,10 @@ Tcl_FlushObjCmd(
"error flushing \"%s\": %s",
TclGetString(chanObjPtr), Tcl_PosixError(interp)));
}
TclChannelRelease(chan);
return TCL_ERROR;
}
TclChannelRelease(chan);
return TCL_OK;
}
@@ -299,6 +305,7 @@ Tcl_GetsObjCmd(
int lineLen; /* Length of line just read. */
int mode; /* Mode in which channel is opened. */
Tcl_Obj *linePtr, *chanObjPtr;
int code = TCL_OK;
if ((objc != 2) && (objc != 3)) {
Tcl_WrongNumArgs(interp, 1, objv, "channelId ?varName?");
@@ -315,6 +322,7 @@ Tcl_GetsObjCmd(
return TCL_ERROR;
}
TclChannelPreserve(chan);
linePtr = Tcl_NewObj();
lineLen = Tcl_GetsObj(chan, linePtr);
if (lineLen < 0) {
@@ -333,20 +341,24 @@ Tcl_GetsObjCmd(
"error reading \"%s\": %s",
TclGetString(chanObjPtr), Tcl_PosixError(interp)));
}
return TCL_ERROR;
code = TCL_ERROR;
goto done;
}
lineLen = -1;
}
if (objc == 3) {
if (Tcl_ObjSetVar2(interp, objv[2], NULL, linePtr,
TCL_LEAVE_ERR_MSG) == NULL) {
return TCL_ERROR;
code = TCL_ERROR;
goto done;
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(lineLen));
} else {
Tcl_SetObjResult(interp, linePtr);
}
return TCL_OK;
done:
TclChannelRelease(chan);
return code;
}
/*
@@ -453,6 +465,7 @@ Tcl_ReadObjCmd(
resultPtr = Tcl_NewObj();
Tcl_IncrRefCount(resultPtr);
TclChannelPreserve(chan);
charactersRead = Tcl_ReadChars(chan, resultPtr, toRead, 0);
if (charactersRead < 0) {
/*
@@ -467,6 +480,7 @@ Tcl_ReadObjCmd(
"error reading \"%s\": %s",
TclGetString(chanObjPtr), Tcl_PosixError(interp)));
}
TclChannelRelease(chan);
Tcl_DecrRefCount(resultPtr);
return TCL_ERROR;
}
@@ -485,6 +499,7 @@ Tcl_ReadObjCmd(
}
}
Tcl_SetObjResult(interp, resultPtr);
TclChannelRelease(chan);
Tcl_DecrRefCount(resultPtr);
return TCL_OK;
}
@@ -544,6 +559,7 @@ Tcl_SeekObjCmd(
mode = modeArray[optionIndex];
}
TclChannelPreserve(chan);
result = Tcl_Seek(chan, offset, mode);
if (result == Tcl_LongAsWide(-1)) {
/*
@@ -558,8 +574,10 @@ Tcl_SeekObjCmd(
"error during seek on \"%s\": %s",
TclGetString(objv[1]), Tcl_PosixError(interp)));
}
TclChannelRelease(chan);
return TCL_ERROR;
}
TclChannelRelease(chan);
return TCL_OK;
}
@@ -590,6 +608,7 @@ Tcl_TellObjCmd(
{
Tcl_Channel chan; /* The channel to tell on. */
Tcl_WideInt newLoc;
int code;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channelId");
@@ -605,6 +624,7 @@ Tcl_TellObjCmd(
return TCL_ERROR;
}
TclChannelPreserve(chan);
newLoc = Tcl_Tell(chan);
/*
@@ -613,7 +633,10 @@ Tcl_TellObjCmd(
* them into the regular interpreter result.
*/
if (TclChanCaughtErrorBypass(interp, chan)) {
code = TclChanCaughtErrorBypass(interp, chan);
TclChannelRelease(chan);
if (code) {
return TCL_ERROR;
}
@@ -896,7 +919,7 @@ Tcl_ExecObjCmd(
if (string[0] != '-') {
break;
}
if (Tcl_GetIndexFromObj(interp, objv[skip], options, "switch",
if (Tcl_GetIndexFromObj(interp, objv[skip], options, "option",
TCL_EXACT, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -910,7 +933,7 @@ Tcl_ExecObjCmd(
}
}
if (objc <= skip) {
Tcl_WrongNumArgs(interp, 1, objv, "?-switch ...? arg ?arg ...?");
Tcl_WrongNumArgs(interp, 1, objv, "?-option ...? arg ?arg ...?");
return TCL_ERROR;
}
@@ -1673,7 +1696,7 @@ Tcl_FcopyObjCmd(
toRead = -1;
cmdPtr = NULL;
for (i = 3; i < objc; i += 2) {
if (Tcl_GetIndexFromObj(interp, objv[i], switches, "switch", 0,
if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
+105 -71
View File
@@ -210,7 +210,27 @@ struct TransformChannelData {
* a transformation of incoming data. Also
* serves as buffer of all data not yet
* consumed by the reader. */
int refCount;
};
static void
PreserveData(
TransformChannelData *dataPtr)
{
dataPtr->refCount++;
}
static void
ReleaseData(
TransformChannelData *dataPtr)
{
if (--dataPtr->refCount) {
return;
}
ResultClear(&dataPtr->result);
Tcl_DecrRefCount(dataPtr->command);
ckfree(dataPtr);
}
/*
*----------------------------------------------------------------------
@@ -240,6 +260,7 @@ TclChannelTransform(
Channel *chanPtr; /* The actual channel. */
ChannelState *statePtr; /* State info for channel. */
int mode; /* Read/write mode of the channel. */
int objc;
TransformChannelData *dataPtr;
Tcl_DString ds;
@@ -247,6 +268,12 @@ TclChannelTransform(
return TCL_ERROR;
}
if (TCL_OK != Tcl_ListObjLength(interp, cmdObjPtr, &objc)) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("-command value is not a list", -1));
return TCL_ERROR;
}
chanPtr = (Channel *) chan;
statePtr = chanPtr->state;
chanPtr = statePtr->topChanPtr;
@@ -261,6 +288,7 @@ TclChannelTransform(
dataPtr = ckalloc(sizeof(TransformChannelData));
dataPtr->refCount = 1;
Tcl_DStringInit(&ds);
Tcl_GetChannelOption(interp, chan, "-blocking", &ds);
dataPtr->readIsFlushed = 0;
@@ -270,7 +298,6 @@ TclChannelTransform(
}
Tcl_DStringFree(&ds);
dataPtr->self = chan;
dataPtr->watchMask = 0;
dataPtr->mode = mode;
dataPtr->timer = NULL;
@@ -286,19 +313,20 @@ TclChannelTransform(
if (dataPtr->self == NULL) {
Tcl_AppendPrintfToObj(Tcl_GetObjResult(interp),
"\nfailed to stack channel \"%s\"", Tcl_GetChannelName(chan));
Tcl_DecrRefCount(dataPtr->command);
ResultClear(&dataPtr->result);
ckfree(dataPtr);
ReleaseData(dataPtr);
return TCL_ERROR;
}
Tcl_Preserve(dataPtr->self);
/*
* At last initialize the transformation at the script level.
*/
PreserveData(dataPtr);
if ((dataPtr->mode & TCL_WRITABLE) && ExecuteCallback(dataPtr, NULL,
A_CREATE_WRITE, NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE) != TCL_OK){
Tcl_UnstackChannel(interp, chan);
ReleaseData(dataPtr);
return TCL_ERROR;
}
@@ -307,9 +335,11 @@ TclChannelTransform(
ExecuteCallback(dataPtr, NULL, A_DELETE_WRITE, NULL, 0, TRANSMIT_DONT,
P_NO_PRESERVE);
Tcl_UnstackChannel(interp, chan);
ReleaseData(dataPtr);
return TCL_ERROR;
}
ReleaseData(dataPtr);
return TCL_OK;
}
@@ -350,7 +380,10 @@ ExecuteCallback(
unsigned char *resBuf;
Tcl_InterpState state = NULL;
int res = TCL_OK;
Tcl_Obj *command = Tcl_DuplicateObj(dataPtr->command);
Tcl_Obj *command = TclListObjCopy(NULL, dataPtr->command);
Tcl_Interp *eval = dataPtr->interp;
Tcl_Preserve(eval);
/*
* Step 1, create the complete command to execute. Do this by appending
@@ -361,26 +394,18 @@ ExecuteCallback(
*/
if (preserve == P_PRESERVE) {
state = Tcl_SaveInterpState(dataPtr->interp, res);
state = Tcl_SaveInterpState(eval, res);
}
Tcl_IncrRefCount(command);
res = Tcl_ListObjAppendElement(dataPtr->interp, command,
Tcl_NewStringObj((char *) op, -1));
if (res != TCL_OK) {
goto cleanup;
}
Tcl_ListObjAppendElement(NULL, command, Tcl_NewStringObj((char *) op, -1));
/*
* Use a byte-array to prevent the misinterpretation of binary data coming
* through as UTF while at the tcl level.
*/
res = Tcl_ListObjAppendElement(dataPtr->interp, command,
Tcl_NewByteArrayObj(buf, bufLen));
if (res != TCL_OK) {
goto cleanup;
}
Tcl_ListObjAppendElement(NULL, command, Tcl_NewByteArrayObj(buf, bufLen));
/*
* Step 2, execute the command at the global level of the interpreter used
@@ -390,13 +415,14 @@ ExecuteCallback(
* current interpreter. Don't copy if in preservation mode.
*/
res = Tcl_EvalObjEx(dataPtr->interp, command, TCL_EVAL_GLOBAL);
res = Tcl_EvalObjEx(eval, command, TCL_EVAL_GLOBAL);
Tcl_DecrRefCount(command);
command = NULL;
if ((res != TCL_OK) && (interp != NULL) && (dataPtr->interp != interp)
if ((res != TCL_OK) && (interp != NULL) && (eval != interp)
&& (preserve == P_NO_PRESERVE)) {
Tcl_SetObjResult(interp, Tcl_GetObjResult(dataPtr->interp));
Tcl_SetObjResult(interp, Tcl_GetObjResult(eval));
Tcl_Release(eval);
return res;
}
@@ -411,20 +437,26 @@ ExecuteCallback(
break;
case TRANSMIT_DOWN:
resObj = Tcl_GetObjResult(dataPtr->interp);
if (dataPtr->self == NULL) {
break;
}
resObj = Tcl_GetObjResult(eval);
resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen);
Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self), (char *) resBuf,
resLen);
break;
case TRANSMIT_SELF:
resObj = Tcl_GetObjResult(dataPtr->interp);
if (dataPtr->self == NULL) {
break;
}
resObj = Tcl_GetObjResult(eval);
resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen);
Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen);
break;
case TRANSMIT_IBUF:
resObj = Tcl_GetObjResult(dataPtr->interp);
resObj = Tcl_GetObjResult(eval);
resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen);
ResultAdd(&dataPtr->result, resBuf, resLen);
break;
@@ -434,24 +466,16 @@ ExecuteCallback(
* Interpret result as integer number.
*/
resObj = Tcl_GetObjResult(dataPtr->interp);
TclGetIntFromObj(dataPtr->interp, resObj, &dataPtr->maxRead);
resObj = Tcl_GetObjResult(eval);
TclGetIntFromObj(eval, resObj, &dataPtr->maxRead);
break;
}
Tcl_ResetResult(dataPtr->interp);
Tcl_ResetResult(eval);
if (preserve == P_PRESERVE) {
(void) Tcl_RestoreInterpState(dataPtr->interp, state);
}
return res;
cleanup:
if (preserve == P_PRESERVE) {
(void) Tcl_RestoreInterpState(dataPtr->interp, state);
}
if (command != NULL) {
Tcl_DecrRefCount(command);
(void) Tcl_RestoreInterpState(eval, state);
}
Tcl_Release(eval);
return res;
}
@@ -535,6 +559,7 @@ TransformCloseProc(
* system rely on (f.e. signaling the close to interested parties).
*/
PreserveData(dataPtr);
if (dataPtr->mode & TCL_WRITABLE) {
ExecuteCallback(dataPtr, interp, A_FLUSH_WRITE, NULL, 0,
TRANSMIT_DOWN, P_PRESERVE);
@@ -554,14 +579,15 @@ TransformCloseProc(
ExecuteCallback(dataPtr, interp, A_DELETE_READ, NULL, 0,
TRANSMIT_DONT, P_PRESERVE);
}
ReleaseData(dataPtr);
/*
* General cleanup.
*/
ResultClear(&dataPtr->result);
Tcl_DecrRefCount(dataPtr->command);
ckfree(dataPtr);
Tcl_Release(dataPtr->self);
dataPtr->self = NULL;
ReleaseData(dataPtr);
return TCL_OK;
}
@@ -596,7 +622,7 @@ TransformInputProc(
* Should assert(dataPtr->mode & TCL_READABLE);
*/
if (toRead == 0) {
if (toRead == 0 || dataPtr->self == NULL) {
/*
* Catch a no-op.
*/
@@ -606,6 +632,7 @@ TransformInputProc(
gotBytes = 0;
downChan = Tcl_GetStackedChannel(dataPtr->self);
PreserveData(dataPtr);
while (toRead > 0) {
/*
* Loop until the request is satisfied (or no data is available from
@@ -623,7 +650,7 @@ TransformInputProc(
* break out of the loop and return to the caller.
*/
return gotBytes;
break;
}
/*
@@ -647,7 +674,7 @@ TransformInputProc(
}
} /* else: 'maxRead < 0' == Accept the current value of toRead. */
if (toRead <= 0) {
return gotBytes;
break;
}
/*
@@ -656,44 +683,40 @@ TransformInputProc(
read = Tcl_ReadRaw(downChan, buf, toRead);
if (read < 0) {
/*
* Report errors to caller. EAGAIN is a special situation. If we
* had some data before we report that instead of the request to
* re-try.
*/
int error = Tcl_GetErrno();
if (Tcl_InputBlocked(downChan) && (gotBytes > 0)) {
/*
* Zero bytes available from downChan because blocked.
* But nonzero bytes already copied, so total is a
* valid blocked short read. Return to caller.
*/
if ((error == EAGAIN) && (gotBytes > 0)) {
return gotBytes;
break;
}
*errorCodePtr = error;
return -1;
/*
* Either downChan is not blocked (there's a real error).
* or it is and there are no bytes copied yet. In either
* case we want to pass the "error" along to the caller,
* either to report an error, or to signal to the caller
* that zero bytes are available because blocked.
*/
*errorCodePtr = Tcl_GetErrno();
gotBytes = -1;
break;
} else if (read == 0) {
/*
* Check wether we hit on EOF in the underlying channel or not. If
* not differentiate between blocking and non-blocking modes. In
* non-blocking mode we ran temporarily out of data. Signal this
* to the caller via EWOULDBLOCK and error return (-1). In the
* other cases we simply return what we got and let the caller
* wait for more. On the other hand, if we got an EOF we have to
* convert and flush all waiting partial data.
*/
if (!Tcl_Eof(downChan)) {
if ((gotBytes == 0) && (dataPtr->flags & CHANNEL_ASYNC)) {
*errorCodePtr = EWOULDBLOCK;
return -1;
}
return gotBytes;
}
/*
* Zero returned from Tcl_ReadRaw() always indicates EOF
* on the down channel.
*/
if (dataPtr->readIsFlushed) {
/*
* Already flushed, nothing to do anymore.
*/
return gotBytes;
break;
}
dataPtr->readIsFlushed = 1;
@@ -705,7 +728,7 @@ TransformInputProc(
* We had nothing to flush.
*/
return gotBytes;
break;
}
continue; /* at: while (toRead > 0) */
@@ -719,9 +742,11 @@ TransformInputProc(
if (ExecuteCallback(dataPtr, NULL, A_READ, UCHARP(buf), read,
TRANSMIT_IBUF, P_PRESERVE) != TCL_OK) {
*errorCodePtr = EINVAL;
return -1;
gotBytes = -1;
break;
}
} /* while toRead > 0 */
ReleaseData(dataPtr);
return gotBytes;
}
@@ -763,11 +788,13 @@ TransformOutputProc(
return 0;
}
PreserveData(dataPtr);
if (ExecuteCallback(dataPtr, NULL, A_WRITE, UCHARP(buf), toWrite,
TRANSMIT_DOWN, P_NO_PRESERVE) != TCL_OK) {
*errorCodePtr = EINVAL;
return -1;
toWrite = -1;
}
ReleaseData(dataPtr);
return toWrite;
}
@@ -820,6 +847,7 @@ TransformSeekProc(
* request down, unchanged.
*/
PreserveData(dataPtr);
if (dataPtr->mode & TCL_WRITABLE) {
ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN,
P_NO_PRESERVE);
@@ -831,6 +859,7 @@ TransformSeekProc(
ResultClear(&dataPtr->result);
dataPtr->readIsFlushed = 0;
}
ReleaseData(dataPtr);
return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset, mode,
errorCodePtr);
@@ -891,6 +920,7 @@ TransformWideSeekProc(
* request down, unchanged.
*/
PreserveData(dataPtr);
if (dataPtr->mode & TCL_WRITABLE) {
ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN,
P_NO_PRESERVE);
@@ -902,6 +932,7 @@ TransformWideSeekProc(
ResultClear(&dataPtr->result);
dataPtr->readIsFlushed = 0;
}
ReleaseData(dataPtr);
/*
* If we have a wide seek capability, we should stick with that.
@@ -1056,6 +1087,9 @@ TransformWatchProc(
* unchanged.
*/
if (dataPtr->self == NULL) {
return;
}
downChan = Tcl_GetStackedChannel(dataPtr->self);
Tcl_GetChannelType(downChan)->watchProc(
+136 -227
View File
@@ -99,31 +99,9 @@ typedef struct {
Tcl_ThreadId thread; /* Thread the 'interp' belongs to. == Handler thread */
Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */
#endif
/* See [==] as well.
* Storage for the command prefix and the additional words required for
* the invocation of methods in the command handler.
*
* argv [0] ... [.] | [argc-2] [argc-1] | [argc] [argc+2]
* cmd ... pfx | method chan | detail1 detail2
* ~~~~ CT ~~~ ~~ CT ~~
*
* CT = Belongs to the 'Command handler Thread'.
*/
int argc; /* Number of preallocated words - 2 */
Tcl_Obj **argv; /* Preallocated array for calling the handler.
* args[0] is placeholder for cmd word.
* Followed by the arguments in the prefix,
* plus 4 placeholders for method, channel,
* and at most two varying (method specific)
* words. */
int methods; /* Bitmask of supported methods */
/*
* NOTE (9): Should we have predefined shared literals for the method
* names?
*/
Tcl_Obj *cmd; /* Callback command prefix */
Tcl_Obj *methods; /* Methods to append to command prefix */
Tcl_Obj *name; /* Name of the channel as created */
int mode; /* Mask of R/W mode */
int interest; /* Mask of events the channel is interested
@@ -450,15 +428,15 @@ static ReflectedChannel * NewReflectedChannel(Tcl_Interp *interp,
Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj);
static Tcl_Obj * NextHandle(void);
static void FreeReflectedChannel(ReflectedChannel *rcPtr);
static void FreeReflectedChannelArgs(ReflectedChannel *rcPtr);
static int InvokeTclMethod(ReflectedChannel *rcPtr,
const char *method, Tcl_Obj *argOneObj,
MethodName method, Tcl_Obj *argOneObj,
Tcl_Obj *argTwoObj, Tcl_Obj **resultObjPtr);
static ReflectedChannelMap * GetReflectedChannelMap(Tcl_Interp *interp);
static void DeleteReflectedChannelMap(ClientData clientData,
Tcl_Interp *interp);
static int ErrnoReturn(ReflectedChannel *rcPtr, Tcl_Obj *resObj);
static void MarkDead(ReflectedChannel *rcPtr);
/*
* Global constant strings (messages). ==================
@@ -467,16 +445,14 @@ static int ErrnoReturn(ReflectedChannel *rcPtr, Tcl_Obj *resObj);
* list-quoting to keep the words of the message together. See also [x].
*/
static const char *msg_read_unsup = "{read not supported by Tcl driver}";
static const char *msg_read_toomuch = "{read delivered more than requested}";
static const char *msg_write_unsup = "{write not supported by Tcl driver}";
static const char *msg_write_toomuch = "{write wrote more than requested}";
static const char *msg_write_nothing = "{write wrote nothing}";
static const char *msg_seek_beforestart = "{Tried to seek before origin}";
#ifdef TCL_THREADS
static const char *msg_send_originlost = "{Channel thread lost}";
static const char *msg_send_dstlost = "{Owner lost}";
#endif /* TCL_THREADS */
static const char *msg_send_dstlost = "{Owner lost}";
static const char *msg_dstlost = "-code 1 -level 0 -errorcode NONE -errorinfo {} -errorline 1 {Owner lost}";
/*
@@ -583,10 +559,6 @@ TclChanCreateObjCmd(
rcId = NextHandle();
rcPtr = NewReflectedChannel(interp, cmdObj, mode, rcId);
chan = Tcl_CreateChannel(&tclRChannelType, TclGetString(rcId), rcPtr,
mode);
rcPtr->chan = chan;
chanPtr = (Channel *) chan;
/*
* Invoke 'initialize' and validate that the handler is present and ok.
@@ -600,7 +572,7 @@ TclChanCreateObjCmd(
modeObj = DecodeEventMask(mode);
/* assert modeObj.refCount == 1 */
result = InvokeTclMethod(rcPtr, "initialize", modeObj, NULL, &resObj);
result = InvokeTclMethod(rcPtr, METH_INIT, modeObj, NULL, &resObj);
Tcl_DecrRefCount(modeObj);
if (result != TCL_OK) {
@@ -683,7 +655,11 @@ TclChanCreateObjCmd(
* Everything is fine now.
*/
rcPtr->methods = methods;
chan = Tcl_CreateChannel(&tclRChannelType, TclGetString(rcId), rcPtr,
mode);
rcPtr->chan = chan;
TclChannelPreserve(chan);
chanPtr = (Channel *) chan;
if ((methods & NULLABLE_METHODS) != NULLABLE_METHODS) {
/*
@@ -744,12 +720,10 @@ TclChanCreateObjCmd(
return TCL_OK;
error:
/*
* Signal to ReflectClose to not call 'finalize'.
*/
rcPtr->methods = 0;
Tcl_Close(interp, chan);
Tcl_DecrRefCount(rcPtr->name);
Tcl_DecrRefCount(rcPtr->methods);
Tcl_DecrRefCount(rcPtr->cmd);
ckfree((char*) rcPtr);
return TCL_ERROR;
#undef MODE
@@ -1138,6 +1112,7 @@ ReflectClose(
ReflectedChannelMap *rcmPtr;/* Map of reflected channels with handlers in
* this interp */
Tcl_HashEntry *hPtr; /* Entry in the above map */
const Tcl_ChannelType *tctPtr;
if (TclInThreadExit()) {
/*
@@ -1175,18 +1150,11 @@ ReflectClose(
}
#endif
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
return EOK;
}
/*
* -- No -- ASSERT rcPtr->methods & FLAG(METH_FINAL)
*
* A cleaned method mask here implies that the channel creation was
* aborted, and "finalize" must not be called.
*/
if (rcPtr->methods == 0) {
tctPtr = ((Channel *)rcPtr->chan)->typePtr;
if (tctPtr && tctPtr != &tclRChannelType) {
ckfree((char *)tctPtr);
((Channel *)rcPtr->chan)->typePtr = NULL;
}
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
return EOK;
}
@@ -1208,14 +1176,12 @@ ReflectClose(
Tcl_DeleteEvents(ReflectEventDelete, rcPtr);
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
if (result != TCL_OK) {
PassReceivedErrorInterp(interp, &p);
}
} else {
#endif
result = InvokeTclMethod(rcPtr, "finalize", NULL, NULL, &resObj);
result = InvokeTclMethod(rcPtr, METH_FINAL, NULL, NULL, &resObj);
if ((result != TCL_OK) && (interp != NULL)) {
Tcl_SetChannelErrorInterp(interp, resObj);
}
@@ -1251,12 +1217,14 @@ ReflectClose(
if (hPtr) {
Tcl_DeleteHashEntry(hPtr);
}
#endif
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
#ifdef TCL_THREADS
}
#endif
tctPtr = ((Channel *)rcPtr->chan)->typePtr;
if (tctPtr && tctPtr != &tclRChannelType) {
ckfree((char *)tctPtr);
((Channel *)rcPtr->chan)->typePtr = NULL;
}
Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
return (result == TCL_OK) ? EOK : EINVAL;
}
@@ -1289,18 +1257,6 @@ ReflectInput(
unsigned char *bytev; /* Array of returned bytes */
Tcl_Obj *resObj; /* Result data for 'read' */
/*
* The following check can be done before thread redirection, because we
* are reading from an item which is readonly, i.e. will never change
* during the lifetime of the channel.
*/
if (!(rcPtr->methods & FLAG(METH_READ))) {
SetChannelErrorStr(rcPtr->chan, msg_read_unsup);
*errorCodePtr = EINVAL;
return -1;
}
/*
* Are we in the correct thread?
*/
@@ -1339,7 +1295,7 @@ ReflectInput(
toReadObj = Tcl_NewIntObj(toRead);
Tcl_IncrRefCount(toReadObj);
if (InvokeTclMethod(rcPtr, "read", toReadObj, NULL, &resObj)!=TCL_OK) {
if (InvokeTclMethod(rcPtr, METH_READ, toReadObj, NULL, &resObj)!=TCL_OK) {
int code = ErrnoReturn(rcPtr, resObj);
if (code < 0) {
@@ -1404,18 +1360,6 @@ ReflectOutput(
Tcl_Obj *resObj; /* Result data for 'write' */
int written;
/*
* The following check can be done before thread redirection, because we
* are reading from an item which is readonly, i.e. will never change
* during the lifetime of the channel.
*/
if (!(rcPtr->methods & FLAG(METH_WRITE))) {
SetChannelErrorStr(rcPtr->chan, msg_write_unsup);
*errorCodePtr = EINVAL;
return -1;
}
/*
* Are we in the correct thread?
*/
@@ -1450,11 +1394,12 @@ ReflectOutput(
/* ASSERT: rcPtr->mode & TCL_WRITABLE */
Tcl_Preserve(rcPtr);
Tcl_Preserve(rcPtr->interp);
bufObj = Tcl_NewByteArrayObj((unsigned char *) buf, toWrite);
Tcl_IncrRefCount(bufObj);
if (InvokeTclMethod(rcPtr, "write", bufObj, NULL, &resObj) != TCL_OK) {
if (InvokeTclMethod(rcPtr, METH_WRITE, bufObj, NULL, &resObj) != TCL_OK) {
int code = ErrnoReturn(rcPtr, resObj);
if (code < 0) {
@@ -1466,6 +1411,14 @@ ReflectOutput(
goto invalid;
}
if (Tcl_InterpDeleted(rcPtr->interp)) {
/*
* The interp was destroyed during InvokeTclMethod().
*/
SetChannelErrorStr(rcPtr->chan, msg_send_dstlost);
goto invalid;
}
if (Tcl_GetIntFromObj(rcPtr->interp, resObj, &written) != TCL_OK) {
Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp));
goto invalid;
@@ -1495,6 +1448,7 @@ ReflectOutput(
stop:
Tcl_DecrRefCount(bufObj);
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
Tcl_Release(rcPtr->interp);
Tcl_Release(rcPtr);
return written;
invalid:
@@ -1568,7 +1522,7 @@ ReflectSeekWide(
Tcl_IncrRefCount(offObj);
Tcl_IncrRefCount(baseObj);
if (InvokeTclMethod(rcPtr, "seek", offObj, baseObj, &resObj) != TCL_OK) {
if (InvokeTclMethod(rcPtr, METH_SEEK, offObj, baseObj, &resObj)!=TCL_OK) {
Tcl_SetChannelError(rcPtr->chan, resObj);
goto invalid;
}
@@ -1639,8 +1593,6 @@ ReflectWatch(
ReflectedChannel *rcPtr = clientData;
Tcl_Obj *maskObj;
/* ASSERT rcPtr->methods & FLAG(METH_WATCH) */
/*
* We restrict the interest to what the channel can support. IOW there
* will never be write events for a channel which is not writable.
@@ -1683,7 +1635,7 @@ ReflectWatch(
maskObj = DecodeEventMask(mask);
/* assert maskObj.refCount == 1 */
(void) InvokeTclMethod(rcPtr, "watch", maskObj, NULL, NULL);
(void) InvokeTclMethod(rcPtr, METH_WATCH, maskObj, NULL, NULL);
Tcl_DecrRefCount(maskObj);
Tcl_Release(rcPtr);
@@ -1742,7 +1694,7 @@ ReflectBlock(
Tcl_Preserve(rcPtr);
if (InvokeTclMethod(rcPtr, "blocking", blockObj, NULL, &resObj)!=TCL_OK) {
if (InvokeTclMethod(rcPtr,METH_BLOCKING,blockObj,NULL,&resObj)!=TCL_OK) {
Tcl_SetChannelError(rcPtr->chan, resObj);
errorNum = EINVAL;
} else {
@@ -1854,7 +1806,7 @@ ReflectSetOption(
Tcl_IncrRefCount(optionObj);
Tcl_IncrRefCount(valueObj);
result = InvokeTclMethod(rcPtr, "configure",optionObj,valueObj, &resObj);
result = InvokeTclMethod(rcPtr, METH_CONFIGURE,optionObj,valueObj, &resObj);
if (result != TCL_OK) {
UnmarshallErrorResult(interp, resObj);
}
@@ -1899,7 +1851,7 @@ ReflectGetOption(
Tcl_Obj *resObj; /* Result data for 'configure' */
int listc, result = TCL_OK;
Tcl_Obj **listv;
const char *method;
MethodName method;
/*
* Are we in the correct thread?
@@ -1938,14 +1890,14 @@ ReflectGetOption(
* Retrieve all options.
*/
method = "cgetall";
method = METH_CGETALL;
optionObj = NULL;
} else {
/*
* Retrieve the value of one option.
*/
method = "cget";
method = METH_CGET;
optionObj = Tcl_NewStringObj(optionName, -1);
Tcl_IncrRefCount(optionObj);
}
@@ -2159,16 +2111,13 @@ NewReflectedChannel(
Tcl_Obj *handleObj)
{
ReflectedChannel *rcPtr;
int i, listc;
Tcl_Obj **listv;
MethodName mn = METH_BLOCKING;
rcPtr = ckalloc(sizeof(ReflectedChannel));
/* rcPtr->chan: Assigned by caller. Dummy data here. */
/* rcPtr->methods: Assigned by caller. Dummy data here. */
rcPtr->chan = NULL;
rcPtr->methods = 0;
rcPtr->interp = interp;
rcPtr->dead = 0;
#ifdef TCL_THREADS
@@ -2177,54 +2126,17 @@ NewReflectedChannel(
rcPtr->mode = mode;
rcPtr->interest = 0; /* Initially no interest registered */
/*
* Method placeholder.
*/
/* ASSERT: cmdpfxObj is a Tcl List */
Tcl_ListObjGetElements(interp, cmdpfxObj, &listc, &listv);
/*
* See [==] as well.
* Storage for the command prefix and the additional words required for
* the invocation of methods in the command handler.
*
* listv [0] [listc-1] | [listc] [listc+1] |
* argv [0] ... [.] | [argc-2] [argc-1] | [argc] [argc+2]
* cmd ... pfx | method chan | detail1 detail2
*/
rcPtr->argc = listc + 2;
rcPtr->argv = ckalloc(sizeof(Tcl_Obj *) * (listc+4));
/*
* Duplicate object references.
*/
for (i=0; i<listc ; i++) {
Tcl_Obj *word = rcPtr->argv[i] = listv[i];
Tcl_IncrRefCount(word);
rcPtr->cmd = TclListObjCopy(NULL, cmdpfxObj);
Tcl_IncrRefCount(rcPtr->cmd);
rcPtr->methods = Tcl_NewListObj(METH_WRITE + 1, NULL);
while (mn <= METH_WRITE) {
Tcl_ListObjAppendElement(NULL, rcPtr->methods,
Tcl_NewStringObj(methodNames[mn++], -1));
}
i++; /* Skip placeholder for method */
/*
* [Bug 1667990]: See [x] in FreeReflectedChannel for release
*/
rcPtr->argv[i] = handleObj;
Tcl_IncrRefCount(handleObj);
/*
* The next two objects are kept empty, varying arguments.
*/
/*
* Initialization complete.
*/
Tcl_IncrRefCount(rcPtr->methods);
rcPtr->name = handleObj;
Tcl_IncrRefCount(rcPtr->name);
return rcPtr;
}
@@ -2271,45 +2183,21 @@ NextHandle(void)
}
static void
FreeReflectedChannelArgs(
ReflectedChannel *rcPtr)
{
int i, n = rcPtr->argc - 2;
if (n < 0) {
return;
}
for (i=0; i<n; i++) {
Tcl_DecrRefCount(rcPtr->argv[i]);
}
/*
* [Bug 1667990]: See [x] in NewReflectedChannel for lock. n+1 = argc-1.
*/
Tcl_DecrRefCount(rcPtr->argv[n+1]);
rcPtr->argc = 1;
}
static void
FreeReflectedChannel(
ReflectedChannel *rcPtr)
{
Channel *chanPtr = (Channel *) rcPtr->chan;
if (chanPtr->typePtr != &tclRChannelType) {
/*
* Delete a cloned ChannelType structure.
*/
ckfree(chanPtr->typePtr);
chanPtr->typePtr = NULL;
TclChannelRelease((Tcl_Channel)chanPtr);
if (rcPtr->name) {
Tcl_DecrRefCount(rcPtr->name);
}
if (rcPtr->methods) {
Tcl_DecrRefCount(rcPtr->methods);
}
if (rcPtr->cmd) {
Tcl_DecrRefCount(rcPtr->cmd);
}
FreeReflectedChannelArgs(rcPtr);
ckfree(rcPtr->argv);
ckfree(rcPtr);
}
@@ -2340,16 +2228,16 @@ FreeReflectedChannel(
static int
InvokeTclMethod(
ReflectedChannel *rcPtr,
const char *method,
MethodName method,
Tcl_Obj *argOneObj, /* NULL'able */
Tcl_Obj *argTwoObj, /* NULL'able */
Tcl_Obj **resultObjPtr) /* NULL'able */
{
int cmdc; /* #words in constructed command */
Tcl_Obj *methObj = NULL; /* Method name in object form */
Tcl_InterpState sr; /* State of handler interp */
int result; /* Result code of method invokation */
Tcl_Obj *resObj = NULL; /* Result of method invokation. */
Tcl_Obj *cmd;
if (rcPtr->dead) {
/*
@@ -2372,19 +2260,15 @@ InvokeTclMethod(
}
/*
* NOTE (5): Decide impl. issue: Cache objects with method names? Needs
* TSD data as reflections can be created in many different threads.
* NO: Caching of command resolutions means storage per channel.
*/
/*
* Insert method into the pre-allocated area, after the command prefix,
* Insert method into the callback command, after the command prefix,
* before the channel id.
*/
methObj = Tcl_NewStringObj(method, -1);
Tcl_IncrRefCount(methObj);
rcPtr->argv[rcPtr->argc - 2] = methObj;
cmd = TclListObjCopy(NULL, rcPtr->cmd);
Tcl_ListObjIndex(NULL, rcPtr->methods, method, &methObj);
Tcl_ListObjAppendElement(NULL, cmd, methObj);
Tcl_ListObjAppendElement(NULL, cmd, rcPtr->name);
/*
* Append the additional argument containing method specific details
@@ -2394,13 +2278,10 @@ InvokeTclMethod(
* The objects will survive the Tcl_EvalObjv without change.
*/
cmdc = rcPtr->argc;
if (argOneObj) {
rcPtr->argv[cmdc] = argOneObj;
cmdc++;
Tcl_ListObjAppendElement(NULL, cmd, argOneObj);
if (argTwoObj) {
rcPtr->argv[cmdc] = argTwoObj;
cmdc++;
Tcl_ListObjAppendElement(NULL, cmd, argTwoObj);
}
}
@@ -2409,9 +2290,10 @@ InvokeTclMethod(
* existing state intact.
*/
Tcl_IncrRefCount(cmd);
sr = Tcl_SaveInterpState(rcPtr->interp, 0 /* Dummy */);
Tcl_Preserve(rcPtr->interp);
result = Tcl_EvalObjv(rcPtr->interp, cmdc, rcPtr->argv, TCL_EVAL_GLOBAL);
result = Tcl_EvalObjEx(rcPtr->interp, cmd, TCL_EVAL_GLOBAL);
/*
* We do not try to extract the result information if the caller has no
@@ -2437,7 +2319,6 @@ InvokeTclMethod(
*/
if (result != TCL_ERROR) {
Tcl_Obj *cmd = Tcl_NewListObj(cmdc, rcPtr->argv);
int cmdLen;
const char *cmdString = Tcl_GetStringFromObj(cmd, &cmdLen);
@@ -2451,24 +2332,16 @@ InvokeTclMethod(
result = TCL_ERROR;
}
Tcl_AppendObjToErrorInfo(rcPtr->interp, Tcl_ObjPrintf(
"\n (chan handler subcommand \"%s\")", method));
"\n (chan handler subcommand \"%s\")",
methodNames[method]));
resObj = MarshallError(rcPtr->interp);
}
Tcl_IncrRefCount(resObj);
}
Tcl_DecrRefCount(cmd);
Tcl_RestoreInterpState(rcPtr->interp, sr);
Tcl_Release(rcPtr->interp);
/*
* Cleanup of the dynamic parts of the command.
*
* The detail objects survived the Tcl_EvalObjv without change because of
* the contract. Therefore there is no need to decrement the refcounts. Only
* the internal method object has to be disposed of.
*/
Tcl_DecrRefCount(methObj);
/*
* The resObj has a ref count of 1 at this location. This means that the
* caller of InvokeTclMethod has to dispose of it (but only if it was
@@ -2589,6 +2462,28 @@ GetReflectedChannelMap(
*----------------------------------------------------------------------
*/
static void
MarkDead(
ReflectedChannel *rcPtr)
{
if (rcPtr->dead) {
return;
}
if (rcPtr->name) {
Tcl_DecrRefCount(rcPtr->name);
rcPtr->name = NULL;
}
if (rcPtr->methods) {
Tcl_DecrRefCount(rcPtr->methods);
rcPtr->methods = NULL;
}
if (rcPtr->cmd) {
Tcl_DecrRefCount(rcPtr->cmd);
rcPtr->cmd = NULL;
}
rcPtr->dead = 1;
}
static void
DeleteReflectedChannelMap(
ClientData clientData, /* The per-interpreter data structure. */
@@ -2624,7 +2519,7 @@ DeleteReflectedChannelMap(
chan = Tcl_GetHashValue(hPtr);
rcPtr = Tcl_GetChannelInstanceData(chan);
rcPtr->dead = 1;
MarkDead(rcPtr);
Tcl_DeleteHashEntry(hPtr);
}
Tcl_DeleteHashTable(&rcmPtr->map);
@@ -2657,6 +2552,11 @@ DeleteReflectedChannelMap(
/*
* The receiver for the event exited, before processing the event. We
* detach the result now, wake the originator up and signal failure.
*
* Attention: Results may have been detached already, by either the
* receiver, or this thread, as part of other parts in the thread
* teardown. Such results are ignored. See ticket [b47b176adf] for the
* identical race condition in Tcl 8.6 IORTrans.
*/
evPtr = resultPtr->evPtr;
@@ -2666,6 +2566,9 @@ DeleteReflectedChannelMap(
continue;
}
paramPtr = evPtr->param;
if (!evPtr) {
continue;
}
evPtr->resultPtr = NULL;
resultPtr->evPtr = NULL;
@@ -2699,8 +2602,7 @@ DeleteReflectedChannelMap(
continue;
}
rcPtr->dead = 1;
FreeReflectedChannelArgs(rcPtr);
MarkDead(rcPtr);
Tcl_DeleteHashEntry(hPtr);
}
#endif
@@ -2797,6 +2699,11 @@ DeleteThreadReflectedChannelMap(
/*
* The receiver for the event exited, before processing the event. We
* detach the result now, wake the originator up and signal failure.
*
* Attention: Results may have been detached already, by either the
* receiver, or this thread, as part of other parts in the thread
* teardown. Such results are ignored. See ticket [b47b176adf] for the
* identical race condition in Tcl 8.6 IORTrans.
*/
evPtr = resultPtr->evPtr;
@@ -2806,6 +2713,9 @@ DeleteThreadReflectedChannelMap(
continue;
}
paramPtr = evPtr->param;
if (!evPtr) {
continue;
}
evPtr->resultPtr = NULL;
resultPtr->evPtr = NULL;
@@ -2839,8 +2749,7 @@ DeleteThreadReflectedChannelMap(
Tcl_Channel chan = Tcl_GetHashValue(hPtr);
ReflectedChannel *rcPtr = Tcl_GetChannelInstanceData(chan);
rcPtr->dead = 1;
FreeReflectedChannelArgs(rcPtr);
MarkDead(rcPtr);
Tcl_DeleteHashEntry(hPtr);
}
ckfree(rcmPtr);
@@ -3018,17 +2927,17 @@ ForwardProc(
* call upon for the driver.
*/
case ForwardedClose:
case ForwardedClose: {
/*
* No parameters/results.
*/
if (InvokeTclMethod(rcPtr, "finalize", NULL, NULL, &resObj)!=TCL_OK) {
if (InvokeTclMethod(rcPtr, METH_FINAL, NULL, NULL, &resObj)!=TCL_OK) {
ForwardSetObjError(paramPtr, resObj);
}
/*
* Freeing is done here, in the origin thread, because the argv[]
* Freeing is done here, in the origin thread, callback command
* objects belong to this thread. Deallocating them in a different
* thread is not allowed
*
@@ -3046,16 +2955,16 @@ ForwardProc(
hPtr = Tcl_FindHashEntry(&rcmPtr->map,
Tcl_GetChannelName(rcPtr->chan));
Tcl_DeleteHashEntry(hPtr);
FreeReflectedChannelArgs(rcPtr);
MarkDead(rcPtr);
break;
}
case ForwardedInput: {
Tcl_Obj *toReadObj = Tcl_NewIntObj(paramPtr->input.toRead);
Tcl_IncrRefCount(toReadObj);
Tcl_Preserve(rcPtr);
if (InvokeTclMethod(rcPtr, "read", toReadObj, NULL, &resObj)!=TCL_OK){
if (InvokeTclMethod(rcPtr, METH_READ, toReadObj, NULL, &resObj)!=TCL_OK){
int code = ErrnoReturn(rcPtr, resObj);
if (code < 0) {
@@ -3095,7 +3004,7 @@ ForwardProc(
Tcl_IncrRefCount(bufObj);
Tcl_Preserve(rcPtr);
if (InvokeTclMethod(rcPtr, "write", bufObj, NULL, &resObj) != TCL_OK) {
if (InvokeTclMethod(rcPtr, METH_WRITE, bufObj, NULL, &resObj) != TCL_OK) {
int code = ErrnoReturn(rcPtr, resObj);
if (code < 0) {
@@ -3138,7 +3047,7 @@ ForwardProc(
Tcl_IncrRefCount(baseObj);
Tcl_Preserve(rcPtr);
if (InvokeTclMethod(rcPtr, "seek", offObj, baseObj, &resObj)!=TCL_OK){
if (InvokeTclMethod(rcPtr, METH_SEEK, offObj, baseObj, &resObj)!=TCL_OK){
ForwardSetObjError(paramPtr, resObj);
paramPtr->seek.offset = -1;
} else {
@@ -3174,7 +3083,7 @@ ForwardProc(
/* assert maskObj.refCount == 1 */
Tcl_Preserve(rcPtr);
(void) InvokeTclMethod(rcPtr, "watch", maskObj, NULL, NULL);
(void) InvokeTclMethod(rcPtr, METH_WATCH, maskObj, NULL, NULL);
Tcl_DecrRefCount(maskObj);
Tcl_Release(rcPtr);
break;
@@ -3185,7 +3094,7 @@ ForwardProc(
Tcl_IncrRefCount(blockObj);
Tcl_Preserve(rcPtr);
if (InvokeTclMethod(rcPtr, "blocking", blockObj, NULL,
if (InvokeTclMethod(rcPtr, METH_BLOCKING, blockObj, NULL,
&resObj) != TCL_OK) {
ForwardSetObjError(paramPtr, resObj);
}
@@ -3201,7 +3110,7 @@ ForwardProc(
Tcl_IncrRefCount(optionObj);
Tcl_IncrRefCount(valueObj);
Tcl_Preserve(rcPtr);
if (InvokeTclMethod(rcPtr, "configure", optionObj, valueObj,
if (InvokeTclMethod(rcPtr, METH_CONFIGURE, optionObj, valueObj,
&resObj) != TCL_OK) {
ForwardSetObjError(paramPtr, resObj);
}
@@ -3220,7 +3129,7 @@ ForwardProc(
Tcl_IncrRefCount(optionObj);
Tcl_Preserve(rcPtr);
if (InvokeTclMethod(rcPtr, "cget", optionObj, NULL, &resObj)!=TCL_OK){
if (InvokeTclMethod(rcPtr, METH_CGET, optionObj, NULL, &resObj)!=TCL_OK){
ForwardSetObjError(paramPtr, resObj);
} else {
TclDStringAppendObj(paramPtr->getOpt.value, resObj);
@@ -3236,7 +3145,7 @@ ForwardProc(
*/
Tcl_Preserve(rcPtr);
if (InvokeTclMethod(rcPtr, "cgetall", NULL, NULL, &resObj) != TCL_OK){
if (InvokeTclMethod(rcPtr, METH_CGETALL, NULL, NULL, &resObj) != TCL_OK){
ForwardSetObjError(paramPtr, resObj);
} else {
/*
+47 -53
View File
@@ -457,8 +457,7 @@ static void TimerKill(ReflectedTransform *rtPtr);
static void TimerSetup(ReflectedTransform *rtPtr);
static void TimerRun(ClientData clientData);
static int TransformRead(ReflectedTransform *rtPtr,
int *errorCodePtr, unsigned char *buf,
int toRead);
int *errorCodePtr, Tcl_Obj *bufObj);
static int TransformWrite(ReflectedTransform *rtPtr,
int *errorCodePtr, unsigned char *buf,
int toWrite);
@@ -1063,6 +1062,7 @@ ReflectInput(
{
ReflectedTransform *rtPtr = clientData;
int gotBytes, copied, readBytes;
Tcl_Obj *bufObj;
/*
* The following check can be done before thread redirection, because we
@@ -1078,6 +1078,9 @@ ReflectInput(
Tcl_Preserve(rtPtr);
/* TODO: Consider a more appropriate buffer size. */
bufObj = Tcl_NewByteArrayObj(NULL, toRead);
Tcl_IncrRefCount(bufObj);
gotBytes = 0;
while (toRead > 0) {
/*
@@ -1129,52 +1132,40 @@ ReflectInput(
goto stop;
}
readBytes = Tcl_ReadRaw(rtPtr->parent, buf, toRead);
if (readBytes < 0) {
/*
* Report errors to caller. The state of the seek system is
* unchanged!
*/
if ((Tcl_GetErrno() == EAGAIN) && (gotBytes > 0)) {
readBytes = Tcl_ReadRaw(rtPtr->parent,
(char *) Tcl_SetByteArrayLength(bufObj, toRead), toRead);
if (readBytes < 0) {
if (Tcl_InputBlocked(rtPtr->parent) && (gotBytes > 0)) {
/*
* EAGAIN is a special situation. If we had some data before
* we report that instead of the request to re-try.
* Down channel is blocked and offers zero additional bytes.
* The nonzero gotBytes already returned makes the total
* operation a valid short read. Return to caller.
*/
goto stop;
}
/*
* Either the down channel is not blocked (a real error)
* or it is and there are gotBytes==0 byte copied so far.
* In either case, pass up the error, so we either report
* any real error, or do not mistakenly signal EOF by
* returning 0 to the caller.
*/
*errorCodePtr = Tcl_GetErrno();
goto error;
}
if (readBytes == 0) {
/*
* Check wether we hit on EOF in 'parent' or not. If not
* differentiate between blocking and non-blocking modes. In
* non-blocking mode we ran temporarily out of data. Signal this
* to the caller via EWOULDBLOCK and error return (-1). In the
* other cases we simply return what we got and let the caller
* wait for more. On the other hand, if we got an EOF we have to
* convert and flush all waiting partial data.
* Zero returned from Tcl_ReadRaw() always indicates EOF
* on the down channel.
*/
if (!Tcl_Eof(rtPtr->parent)) {
/*
* The state of the seek system is unchanged!
*/
if ((gotBytes == 0) && rtPtr->nonblocking) {
*errorCodePtr = EWOULDBLOCK;
goto error;
}
goto stop;
} else {
/*
* Eof in parent.
*/
if (rtPtr->readIsDrained) {
goto stop;
}
@@ -1198,13 +1189,7 @@ ReflectInput(
goto stop;
}
/*
* Reset eof, force caller to drain result buffer.
*/
((Channel *) rtPtr->parent)->state->flags &= ~CHANNEL_EOF;
continue; /* at: while (toRead > 0) */
}
} /* readBytes == 0 */
/*
@@ -1213,12 +1198,20 @@ ReflectInput(
* iteration will put it into the result.
*/
if (!TransformRead(rtPtr, errorCodePtr, UCHARP(buf), readBytes)) {
Tcl_SetByteArrayLength(bufObj, readBytes);
if (!TransformRead(rtPtr, errorCodePtr, bufObj)) {
goto error;
}
if (Tcl_IsShared(bufObj)) {
Tcl_DecrRefCount(bufObj);
bufObj = Tcl_NewObj();
Tcl_IncrRefCount(bufObj);
}
Tcl_SetByteArrayLength(bufObj, 0);
} /* while toRead > 0 */
stop:
Tcl_DecrRefCount(bufObj);
Tcl_Release(rtPtr);
return gotBytes;
@@ -2010,6 +2003,7 @@ InvokeTclMethod(
sr = Tcl_SaveInterpState(rtPtr->interp, 0 /* Dummy */);
Tcl_Preserve(rtPtr);
Tcl_Preserve(rtPtr->interp);
result = Tcl_EvalObjv(rtPtr->interp, cmdc, rtPtr->argv, TCL_EVAL_GLOBAL);
/*
@@ -2054,6 +2048,7 @@ InvokeTclMethod(
Tcl_IncrRefCount(resObj);
}
Tcl_RestoreInterpState(rtPtr->interp, sr);
Tcl_Release(rtPtr->interp);
Tcl_Release(rtPtr);
/*
@@ -2230,6 +2225,9 @@ DeleteReflectedTransformMap(
*/
evPtr = resultPtr->evPtr;
if (evPtr == NULL) {
continue;
}
paramPtr = evPtr->param;
evPtr->resultPtr = NULL;
@@ -2355,6 +2353,9 @@ DeleteThreadReflectedTransformMap(
*/
evPtr = resultPtr->evPtr;
if (evPtr == NULL) {
continue;
}
paramPtr = evPtr->param;
evPtr->resultPtr = NULL;
@@ -3065,10 +3066,8 @@ static int
TransformRead(
ReflectedTransform *rtPtr,
int *errorCodePtr,
unsigned char *buf,
int toRead)
Tcl_Obj *bufObj)
{
Tcl_Obj *bufObj;
Tcl_Obj *resObj;
int bytec; /* Number of returned bytes */
unsigned char *bytev; /* Array of returned bytes */
@@ -3081,8 +3080,8 @@ TransformRead(
if (rtPtr->thread != Tcl_GetCurrentThread()) {
ForwardParam p;
p.transform.buf = (char *) buf;
p.transform.size = toRead;
p.transform.buf = (char *) Tcl_GetByteArrayFromObj(bufObj,
&(p.transform.size));
ForwardOpToOwnerThread(rtPtr, ForwardedInput, &p);
@@ -3102,12 +3101,8 @@ TransformRead(
/* ASSERT: rtPtr->method & FLAG(METH_READ) */
/* ASSERT: rtPtr->mode & TCL_READABLE */
bufObj = Tcl_NewByteArrayObj((unsigned char *) buf, toRead);
Tcl_IncrRefCount(bufObj);
if (InvokeTclMethod(rtPtr, "read", bufObj, NULL, &resObj) != TCL_OK) {
Tcl_SetChannelError(rtPtr->chan, resObj);
Tcl_DecrRefCount(bufObj);
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
*errorCodePtr = EINVAL;
return 0;
@@ -3116,7 +3111,6 @@ TransformRead(
bytev = Tcl_GetByteArrayFromObj(resObj, &bytec);
ResultAdd(&rtPtr->result, bytev, bytec);
Tcl_DecrRefCount(bufObj);
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
return 1;
}
@@ -3184,7 +3178,7 @@ TransformWrite(
}
if (res < 0) {
*errorCodePtr = EINVAL;
*errorCodePtr = Tcl_GetErrno();
return 0;
}
@@ -3294,7 +3288,7 @@ TransformFlush(
}
if (res < 0) {
*errorCodePtr = EINVAL;
*errorCodePtr = Tcl_GetErrno();
return 0;
}
+89 -5
View File
@@ -19,11 +19,17 @@
*/
#include "tclInt.h"
#ifdef __WIN32__
#ifdef _WIN32
# include "tclWinInt.h"
#endif
#include "tclFileSystem.h"
#ifdef TCL_TEMPLOAD_NO_UNLINK
#ifndef NO_FSTATFS
#include <sys/statfs.h>
#endif
#endif
/*
* struct FilesystemRecord --
*
@@ -792,7 +798,7 @@ TclFinalizeFilesystem(void)
* filesystem is likely to fail.
*/
#ifdef __WIN32__
#ifdef _WIN32
TclWinEncodingsCleanup();
#endif
}
@@ -819,7 +825,7 @@ TclResetFilesystem(void)
filesystemList = &nativeFilesystemRecord;
theFilesystemEpoch++;
#ifdef __WIN32__
#ifdef _WIN32
/*
* Cleans up the win32 API filesystem proc lookup table. This must happen
* very late in finalization so that deleting of copied dlls can occur.
@@ -3110,6 +3116,82 @@ Tcl_FSLoadFile(
*----------------------------------------------------------------------
*/
/*
* Workaround for issue with modern HPUX which do allow the unlink (no ETXTBSY
* error) yet somehow trash some internal data structures which prevents the
* second and further shared libraries from getting properly loaded. Only the
* first is ok. We try to get around the issue by not unlinking,
* i.e. emulating the behaviour of the older HPUX which denied removal.
*
* Doing the unlink is also an issue within docker containers, whose AUFS
* bungles this as well, see
* https://github.com/dotcloud/docker/issues/1911
*
* For these situations the change below makes the execution of the unlink
* semi-controllable at runtime.
*
* An AUFS filesystem (if it can be detected) will force avoidance of
* unlink. The env variable TCL_TEMPLOAD_NO_UNLINK allows detection of a
* users general request (unlink and not.
*
* By default the unlink is done (if not in AUFS). However if the variable is
* present and set to true (any integer > 0) then the unlink is skipped.
*/
int
TclSkipUnlink (Tcl_Obj* shlibFile)
{
/* Order of testing:
* 1. On hpux we generally want to skip unlink in general
*
* Outside of hpux then:
* 2. For a general user request (TCL_TEMPLOAD_NO_UNLINK present, non-empty, => int)
* 3. For general AUFS environment (statfs, if available).
*
* Ad 2: This variable can disable/override the AUFS detection, i.e. for
* testing if a newer AUFS does not have the bug any more.
*
* Ad 3: This is conditionally compiled in. Condition currently must be set manually.
* This part needs proper tests in the configure(.in).
*/
#ifdef hpux
return 1;
#else
char* skipstr;
skipstr = getenv ("TCL_TEMPLOAD_NO_UNLINK");
if (skipstr && (skipstr[0] != '\0')) {
return atoi(skipstr);
}
#ifdef TCL_TEMPLOAD_NO_UNLINK
#ifndef NO_FSTATFS
{
struct statfs fs;
/* Have fstatfs. May not have the AUFS super magic ... Indeed our build
* box is too old to have it directly in the headers. Define taken from
* http://mooon.googlecode.com/svn/trunk/linux_include/linux/aufs_type.h
* http://aufs.sourceforge.net/
* Better reference will be gladly taken.
*/
#ifndef AUFS_SUPER_MAGIC
#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
#endif /* AUFS_SUPER_MAGIC */
if ((statfs(Tcl_GetString (shlibFile), &fs) == 0) &&
(fs.f_type == AUFS_SUPER_MAGIC)) {
return 1;
}
}
#endif /* ... NO_FSTATFS */
#endif /* ... TCL_TEMPLOAD_NO_UNLINK */
/* Fallback: !hpux, no EV override, no AUFS (detection, nor detected):
* Don't skip */
return 0;
#endif /* hpux */
}
int
Tcl_LoadFile(
Tcl_Interp *interp, /* Used for error reporting. */
@@ -3255,7 +3337,7 @@ Tcl_LoadFile(
return TCL_ERROR;
}
#ifndef __WIN32__
#ifndef _WIN32
/*
* Do we need to set appropriate permissions on the file? This may be
* required on some systems. On Unix we could loop over the file
@@ -3300,7 +3382,9 @@ Tcl_LoadFile(
* avoids any worries about leaving the copy laying around on exit.
*/
if (Tcl_FSDeleteFile(copyToPtr) == TCL_OK) {
if (
!TclSkipUnlink (copyToPtr) &&
(Tcl_FSDeleteFile(copyToPtr) == TCL_OK)) {
Tcl_DecrRefCount(copyToPtr);
/*
+92
View File
@@ -1686,6 +1686,7 @@ typedef struct Command {
#define CMD_TRACE_ACTIVE 0x2
#define CMD_HAS_EXEC_TRACES 0x4
#define CMD_COMPILES_EXPANDED 0x8
#define CMD_REDEF_IN_PROGRESS 0x10
/*
*----------------------------------------------------------------
@@ -1733,6 +1734,41 @@ enum PkgPreferOptions {
PKG_PREFER_LATEST, PKG_PREFER_STABLE
};
/*
*----------------------------------------------------------------
* These structures support gc
*----------------------------------------------------------------
*/
/*
* Header starting each chunk of Tcl_Obj, to chain them for use by gc
*/
typedef struct ObjChunkHeader {
struct ObjChunkHeader *next; /* chaining */
Tcl_Obj *end; /* address of last+1 */
} ObjChunkHeader;
MODULE_SCOPE ObjChunkHeader *tclObjChunkList; /* initialised in tclObj.c */
/*
* Cell of temporary sorted array of chunk ranges and counters, for
* dichotomic search in gc
*/
typedef struct ObjChunkInfo {
Tcl_Obj *beg,*end; /* [beg,end[ is the chunk's range */
long free; /* temporary counter for gc ; long for word-aligt */
} ObjChunkInfo;
MODULE_SCOPE void TclpLockAlloc(void);
MODULE_SCOPE void TclpUnlockAlloc(void);
MODULE_SCOPE Tcl_Obj **TclpGetGlobalFreeObj(void);
MODULE_SCOPE Tcl_Obj **TclpGetLocalFreeObj(void);
MODULE_SCOPE void TclpRecomputeGlobalNumObj(void);
MODULE_SCOPE void TclpRecomputeLocalNumObj(void);
/*
*----------------------------------------------------------------
* This structure shadows the first few fields of the memory cache for the
@@ -2451,6 +2487,30 @@ typedef struct List {
TclGetIntForIndex(interp, objPtr, ignore, idxPtr)
#endif
/*
* Macro used to save a function call for common uses of
* Tcl_GetWideIntFromObj(). The ANSI C "prototype" is:
*
* MODULE_SCOPE int TclGetWideIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
* Tcl_WideInt *wideIntPtr);
*/
#ifdef TCL_WIDE_INT_IS_LONG
#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \
(((objPtr)->typePtr == &tclIntType) \
? (*(wideIntPtr) = (Tcl_WideInt) \
((objPtr)->internalRep.longValue), TCL_OK) : \
Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))
#else /* !TCL_WIDE_INT_IS_LONG */
#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \
(((objPtr)->typePtr == &tclWideIntType) \
? (*(wideIntPtr) = (objPtr)->internalRep.wideValue, TCL_OK) : \
((objPtr)->typePtr == &tclIntType) \
? (*(wideIntPtr) = (Tcl_WideInt) \
((objPtr)->internalRep.longValue), TCL_OK) : \
Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))
#endif /* TCL_WIDE_INT_IS_LONG */
/*
* Flag values for TclTraceDictPath().
*
@@ -2639,6 +2699,8 @@ MODULE_SCOPE char *tclMemDumpFileName;
MODULE_SCOPE TclPlatformType tclPlatform;
MODULE_SCOPE Tcl_NotifierProcs tclNotifierHooks;
MODULE_SCOPE Tcl_Encoding tclIdentityEncoding;
/*
* TIP #233 (Virtualized Time)
* Data for the time hooks, if any.
@@ -2837,6 +2899,8 @@ MODULE_SCOPE int TclByteArrayMatch(const unsigned char *string,
int strLen, const unsigned char *pattern,
int ptnLen, int flags);
MODULE_SCOPE double TclCeil(const mp_int *a);
MODULE_SCOPE void TclChannelPreserve(Tcl_Channel chan);
MODULE_SCOPE void TclChannelRelease(Tcl_Channel chan);
MODULE_SCOPE int TclCheckBadOctal(Tcl_Interp *interp,
const char *value);
MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp,
@@ -2854,6 +2918,10 @@ MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr,
MODULE_SCOPE int TclConvertElement(const char *src, int length,
char *dst, int flags);
MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr);
MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp,
const char *dict, int dictLength,
const char **elementPtr, const char **nextPtr,
int *sizePtr, int *literalPtr);
/* TIP #280 - Modified token based evulation, with line information. */
MODULE_SCOPE int TclEvalEx(Tcl_Interp *interp, const char *script,
int numBytes, int flags, int line,
@@ -2893,6 +2961,7 @@ MODULE_SCOPE void TclFinalizeObjects(void);
MODULE_SCOPE void TclFinalizePreserve(void);
MODULE_SCOPE void TclFinalizeSynchronization(void);
MODULE_SCOPE void TclFinalizeThreadAlloc(void);
MODULE_SCOPE void TclFinalizeThreadAllocThread(void);
MODULE_SCOPE void TclFinalizeThreadData(void);
MODULE_SCOPE void TclFinalizeThreadObjects(void);
MODULE_SCOPE double TclFloor(const mp_int *a);
@@ -2918,6 +2987,8 @@ MODULE_SCOPE int TclGetOpenModeEx(Tcl_Interp *interp,
MODULE_SCOPE Tcl_Obj * TclGetProcessGlobalValue(ProcessGlobalValue *pgvPtr);
MODULE_SCOPE Tcl_Obj * TclGetSourceFromFrame(CmdFrame *cfPtr, int objc,
Tcl_Obj *const objv[]);
MODULE_SCOPE char * TclGetStringStorage(Tcl_Obj *objPtr,
unsigned int *sizePtr);
MODULE_SCOPE int TclGlob(Tcl_Interp *interp, char *pattern,
Tcl_Obj *unquotedPrefix, int globFlags,
Tcl_GlobTypeData *types);
@@ -3249,6 +3320,9 @@ MODULE_SCOPE int Tcl_ForeachObjCmd(ClientData clientData,
MODULE_SCOPE int Tcl_FormatObjCmd(ClientData dummy,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
MODULE_SCOPE int Tcl_GcCmd(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
MODULE_SCOPE int Tcl_GetsObjCmd(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
@@ -3571,6 +3645,9 @@ MODULE_SCOPE int TclCompileNamespaceCodeCmd(Tcl_Interp *interp,
MODULE_SCOPE int TclCompileNamespaceCurrentCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileNamespaceOriginCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileNamespaceQualifiersCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
@@ -3586,6 +3663,12 @@ MODULE_SCOPE int TclCompileNamespaceWhichCmd(Tcl_Interp *interp,
MODULE_SCOPE int TclCompileNoOp(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileObjectNextCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileObjectNextToCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileObjectSelfCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
@@ -3601,6 +3684,9 @@ MODULE_SCOPE int TclCompileReturnCmd(Tcl_Interp *interp,
MODULE_SCOPE int TclCompileSetCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileStringCatCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileStringCmpCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
@@ -3613,6 +3699,9 @@ MODULE_SCOPE int TclCompileStringFirstCmd(Tcl_Interp *interp,
MODULE_SCOPE int TclCompileStringIndexCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileStringIsCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileStringLastCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
@@ -3679,6 +3768,9 @@ MODULE_SCOPE int TclCompileWhileCmd(Tcl_Interp *interp,
MODULE_SCOPE int TclCompileYieldCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileYieldToCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileBasic0ArgCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
+14 -8
View File
@@ -13,7 +13,7 @@
#ifndef _TCLINTPLATDECLS
#define _TCLINTPLATDECLS
#ifdef __WIN32__
#ifdef _WIN32
# define Tcl_DirEntry void
# define DIR void
#endif
@@ -45,7 +45,7 @@ extern "C" {
* Exported function declarations:
*/
#if !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
/* 0 */
EXTERN void TclGetAndDetachPids(Tcl_Interp *interp,
Tcl_Channel chan);
@@ -104,7 +104,7 @@ EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
Tcl_Obj *resultingNameObj);
#endif /* UNIX */
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
/* 0 */
EXTERN void TclWinConvertError(DWORD errCode);
/* 1 */
@@ -258,7 +258,7 @@ typedef struct TclIntPlatStubs {
int magic;
void *hooks;
#if !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 0 */
int (*tclpCloseFile) (TclFile file); /* 1 */
Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 2 */
@@ -291,7 +291,7 @@ typedef struct TclIntPlatStubs {
int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */
int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */
#endif /* UNIX */
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
void (*tclWinConvertError) (DWORD errCode); /* 0 */
void (*tclWinConvertWSAError) (DWORD errCode); /* 1 */
struct servent * (*tclWinGetServByName) (const char *nm, const char *proto); /* 2 */
@@ -371,7 +371,7 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
* Inline function declarations:
*/
#if !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
#define TclGetAndDetachPids \
(tclIntPlatStubsPtr->tclGetAndDetachPids) /* 0 */
#define TclpCloseFile \
@@ -420,7 +420,7 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
#define TclUnixOpenTemporaryFile \
(tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */
#endif /* UNIX */
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
#define TclWinConvertError \
(tclIntPlatStubsPtr->tclWinConvertError) /* 0 */
#define TclWinConvertWSAError \
@@ -550,9 +550,15 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
#undef TclpInetNtoa
#define TclpInetNtoa inet_ntoa
#if defined(__WIN32__) || defined(__CYGWIN__)
#if defined(_WIN32)
# undef TclWinNToHS
# undef TclWinGetServByName
# undef TclWinGetSockOpt
# undef TclWinSetSockOpt
# define TclWinNToHS ntohs
# define TclWinGetServByName getservbyname
# define TclWinGetSockOpt getsockopt
# define TclWinSetSockOpt setsockopt
#else
# undef TclpGetPid
# define TclpGetPid(pid) ((unsigned long) (pid))
+2 -2
View File
@@ -830,7 +830,7 @@ Tcl_UnloadObjCmd(
* Unload the shared library from the application memory...
*/
#if defined(TCL_UNLOAD_DLLS) || defined(__WIN32__)
#if defined(TCL_UNLOAD_DLLS) || defined(_WIN32)
/*
* Some Unix dlls are poorly behaved - registering things like atexit
* calls that can't be unregistered. If you unload such dlls, you get
@@ -1151,7 +1151,7 @@ TclFinalizeLoad(void)
pkgPtr = firstPackagePtr;
firstPackagePtr = pkgPtr->nextPtr;
#if defined(TCL_UNLOAD_DLLS) || defined(__WIN32__)
#if defined(TCL_UNLOAD_DLLS) || defined(_WIN32)
/*
* Some Unix dlls are poorly behaved - registering things like atexit
* calls that can't be unregistered. If you unload such dlls, you get
+3 -1
View File
@@ -104,7 +104,9 @@ TclpLoadMemory(
int size, /* Dummy: unused by this implementation */
int codeSize, /* Dummy: unused by this implementation */
Tcl_LoadHandle *loadHandle, /* Dummy: unused by this implementation */
Tcl_FSUnloadFileProc **unloadProcPtr)
Tcl_FSUnloadFileProc **unloadProcPtr,
/* Dummy: unused by this implementation */
int flags)
/* Dummy: unused by this implementation */
{
Tcl_SetObjResult(interp, Tcl_NewStringObj("dynamic loading from memory "
+1 -1
View File
@@ -47,7 +47,7 @@
* we have to translate that to strcmp here.
*/
#ifndef __WIN32__
#ifndef _WIN32
# define TCHAR char
# define TEXT(arg) arg
# define _tcscmp strcmp
+1 -1
View File
@@ -171,7 +171,7 @@ static const EnsembleImplMap defaultNamespaceMap[] = {
{"forget", NamespaceForgetCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
{"import", NamespaceImportCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
{"inscope", NamespaceInscopeCmd, NULL, NRNamespaceInscopeCmd, NULL, 0},
{"origin", NamespaceOriginCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"origin", NamespaceOriginCmd, TclCompileNamespaceOriginCmd, NULL, NULL, 0},
{"parent", NamespaceParentCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
{"path", NamespacePathCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
{"qualifiers", NamespaceQualifiersCmd, TclCompileNamespaceQualifiersCmd, NULL, NULL, 0},
+14 -4
View File
@@ -394,6 +394,7 @@ InitFoundation(
fPtr->classCls->flags |= ROOT_CLASS;
TclOOAddToInstances(fPtr->objectCls->thisPtr, fPtr->classCls);
TclOOAddToInstances(fPtr->classCls->thisPtr, fPtr->classCls);
TclOOAddToSubclasses(fPtr->classCls, fPtr->objectCls);
AddRef(fPtr->objectCls->thisPtr);
AddRef(fPtr->objectCls);
@@ -437,10 +438,12 @@ InitFoundation(
* ensemble.
*/
Tcl_CreateObjCommand(interp, "::oo::Helpers::next", TclOONextObjCmd, NULL,
NULL);
Tcl_CreateObjCommand(interp, "::oo::Helpers::nextto", TclOONextToObjCmd,
NULL, NULL);
cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "::oo::Helpers::next",
NULL, TclOONextObjCmd, NULL, NULL);
cmdPtr->compileProc = TclCompileObjectNextCmd;
cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "::oo::Helpers::nextto",
NULL, TclOONextToObjCmd, NULL, NULL);
cmdPtr->compileProc = TclCompileObjectNextToCmd;
cmdPtr = (Command *) Tcl_CreateObjCommand(interp, "::oo::Helpers::self",
TclOOSelfObjCmd, NULL, NULL);
cmdPtr->compileProc = TclCompileObjectSelfCmd;
@@ -1006,6 +1009,12 @@ ReleaseClassContents(
}
if (!Deleted(instancePtr)) {
Tcl_DeleteCommandFromToken(interp, instancePtr->command);
/*
* Tcl_DeleteCommandFromToken() may have done to whole
* job for us. Roll back and check again.
*/
i--;
continue;
}
DelRef(instancePtr);
}
@@ -1278,6 +1287,7 @@ TclOORemoveFromInstances(
removeInstance:
if (Deleted(clsPtr->thisPtr)) {
DelRef(clsPtr->instances.list[i]);
clsPtr->instances.list[i] = NULL;
} else {
clsPtr->instances.num--;
+1
View File
@@ -18,6 +18,7 @@ library tclOO
interface tclOO
hooks tclOOInt
scspec TCLAPI
declare 0 {
Tcl_Object Tcl_CopyObjectInstance(Tcl_Interp *interp,
+1 -1
View File
@@ -24,7 +24,7 @@
* win/tclooConfig.sh
*/
#define TCLOO_VERSION "1.0.1"
#define TCLOO_VERSION "1.0.2"
#define TCLOO_PATCHLEVEL TCLOO_VERSION
#include "tcl.h"
+25 -18
View File
@@ -17,16 +17,11 @@
#include "tclOOInt.h"
static inline Tcl_Object *AddConstructionFinalizer(Tcl_Interp *interp);
static int AfterNRDestructor(ClientData data[],
Tcl_Interp *interp, int result);
static int DecrRefsPostClassConstructor(ClientData data[],
Tcl_Interp *interp, int result);
static int FinalizeConstruction(ClientData data[],
Tcl_Interp *interp, int result);
static int FinalizeEval(ClientData data[],
Tcl_Interp *interp, int result);
static int RestoreFrame(ClientData data[],
Tcl_Interp *interp, int result);
static Tcl_NRPostProc AfterNRDestructor;
static Tcl_NRPostProc DecrRefsPostClassConstructor;
static Tcl_NRPostProc FinalizeConstruction;
static Tcl_NRPostProc FinalizeEval;
static Tcl_NRPostProc NextRestoreFrame;
/*
* ----------------------------------------------------------------------
@@ -808,7 +803,7 @@ TclOONextObjCmd(
* that this is like [uplevel 1] and not [eval].
*/
TclNRAddCallback(interp, RestoreFrame, framePtr, NULL, NULL, NULL);
TclNRAddCallback(interp, NextRestoreFrame, framePtr, NULL,NULL,NULL);
iPtr->varFramePtr = framePtr->callerVarPtr;
return TclNRObjectContextInvokeNext(interp, context, objc, objv, 1);
}
@@ -826,6 +821,7 @@ TclOONextToObjCmd(
CallContext *contextPtr;
int i;
Tcl_Object object;
const char *methodType;
/*
* Start with sanity checks on the calling context to make sure that we
@@ -877,8 +873,8 @@ TclOONextToObjCmd(
* context. Note that this is like [uplevel 1] and not [eval].
*/
TclNRAddCallback(interp, RestoreFrame, framePtr, contextPtr,
INT2PTR(contextPtr->index), NULL);
TclNRAddCallback(interp, NextRestoreFrame, framePtr,
contextPtr, INT2PTR(contextPtr->index), NULL);
contextPtr->index = i-1;
iPtr->varFramePtr = framePtr->callerVarPtr;
return TclNRObjectContextInvokeNext(interp,
@@ -891,24 +887,35 @@ TclOONextToObjCmd(
* is on the chain but unreachable, or not on the chain at all.
*/
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
methodType = "constructor";
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
methodType = "destructor";
} else {
methodType = "method";
}
for (i=contextPtr->index ; i>=0 ; i--) {
struct MInvoke *miPtr = contextPtr->callPtr->chain + i;
if (!miPtr->isFilter && miPtr->mPtr->declaringClassPtr == classPtr) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"method implementation by \"%s\" not reachable from here",
TclGetString(objv[1])));
"%s implementation by \"%s\" not reachable from here",
methodType, TclGetString(objv[1])));
Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_REACHABLE",
NULL);
return TCL_ERROR;
}
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"method has no non-filter implementation by \"%s\"",
TclGetString(objv[1])));
"%s has no non-filter implementation by \"%s\"",
methodType, TclGetString(objv[1])));
Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", NULL);
return TCL_ERROR;
}
static int
RestoreFrame(
NextRestoreFrame(
ClientData data[],
Tcl_Interp *interp,
int result)
+72 -27
View File
@@ -38,6 +38,12 @@ struct ChainBuilder {
#define DEFINITE_PUBLIC 0x200000
#define KNOWN_STATE (DEFINITE_PROTECTED | DEFINITE_PUBLIC)
#define SPECIAL (CONSTRUCTOR | DESTRUCTOR | FORCE_UNKNOWN)
#define BUILDING_MIXINS 0x400000
#define TRAVERSED_MIXIN 0x800000
#define OBJECT_MIXIN 0x1000000
#define MIXIN_CONSISTENT(flags) \
(((flags) & OBJECT_MIXIN) || \
!((flags) & BUILDING_MIXINS) == !((flags) & TRAVERSED_MIXIN))
/*
* Function declarations for things defined in this file.
@@ -45,13 +51,13 @@ struct ChainBuilder {
static void AddClassFiltersToCallContext(Object *const oPtr,
Class *clsPtr, struct ChainBuilder *const cbPtr,
Tcl_HashTable *const doneFilters);
Tcl_HashTable *const doneFilters, int flags);
static void AddClassMethodNames(Class *clsPtr, const int flags,
Tcl_HashTable *const namesPtr);
static inline void AddMethodToCallChain(Method *const mPtr,
struct ChainBuilder *const cbPtr,
Tcl_HashTable *const doneFilters,
Class *const filterDecl);
Class *const filterDecl, int flags);
static inline void AddSimpleChainToCallContext(Object *const oPtr,
Tcl_Obj *const methodNameObj,
struct ChainBuilder *const cbPtr,
@@ -150,7 +156,7 @@ void
TclOODeleteChain(
CallChain *callPtr)
{
if (--callPtr->refCount >= 1) {
if (callPtr == NULL || --callPtr->refCount >= 1) {
return;
}
if (callPtr->chain != callPtr->staticChain) {
@@ -434,7 +440,7 @@ TclOOGetSortedMethodList(
AddClassMethodNames(oPtr->selfCls, flags, &names);
FOREACH(mixinPtr, oPtr->mixins) {
AddClassMethodNames(mixinPtr, flags, &names);
AddClassMethodNames(mixinPtr, flags|TRAVERSED_MIXIN, &names);
}
/*
@@ -598,7 +604,7 @@ AddClassMethodNames(
/* TODO: Beware of infinite loops! */
FOREACH(mixinPtr, clsPtr->mixins) {
AddClassMethodNames(mixinPtr, flags, namesPtr);
AddClassMethodNames(mixinPtr, flags|TRAVERSED_MIXIN, namesPtr);
}
}
@@ -695,13 +701,13 @@ AddSimpleChainToCallContext(
FOREACH(mixinPtr, oPtr->mixins) {
AddSimpleClassChainToCallContext(mixinPtr, methodNameObj, cbPtr,
doneFilters, flags, filterDecl);
doneFilters, flags|TRAVERSED_MIXIN, filterDecl);
}
if (oPtr->methodsPtr) {
hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char*) methodNameObj);
if (hPtr != NULL) {
AddMethodToCallChain(Tcl_GetHashValue(hPtr), cbPtr,
doneFilters, filterDecl);
doneFilters, filterDecl, flags);
}
}
}
@@ -732,9 +738,15 @@ AddMethodToCallChain(
* processed. If NULL, not processing filters.
* Note that this function does not update
* this hashtable. */
Class *const filterDecl) /* The class that declared the filter. If
Class *const filterDecl, /* The class that declared the filter. If
* NULL, either the filter was declared by the
* object or this isn't a filter. */
int flags) /* Used to check if we're mixin-consistent
* only. Mixin-consistent means that either
* we're looking to add things from a mixin
* and we have passed a mixin, or we're not
* looking to add things from a mixin and have
* not passed a mixin. */
{
register CallChain *callPtr = cbPtr->callChainPtr;
int i;
@@ -743,9 +755,11 @@ AddMethodToCallChain(
* Return if this is just an entry used to record whether this is a public
* method. If so, there's nothing real to call and so nothing to add to
* the call chain.
*
* This is also where we enforce mixin-consistency.
*/
if (mPtr == NULL || mPtr->typePtr == NULL) {
if (mPtr == NULL || mPtr->typePtr == NULL || !MIXIN_CONSISTENT(flags)) {
return;
}
@@ -1000,6 +1014,8 @@ TclOOGetCallContext(
*/
if (flags & FORCE_UNKNOWN) {
AddSimpleChainToCallContext(oPtr, oPtr->fPtr->unknownMethodNameObj,
&cb, NULL, BUILDING_MIXINS, NULL);
AddSimpleChainToCallContext(oPtr, oPtr->fPtr->unknownMethodNameObj,
&cb, NULL, 0, NULL);
callPtr->flags |= OO_UNKNOWN_METHOD;
@@ -1024,21 +1040,32 @@ TclOOGetCallContext(
doFilters = 1;
Tcl_InitObjHashTable(&doneFilters);
FOREACH(mixinPtr, oPtr->mixins) {
AddClassFiltersToCallContext(oPtr, mixinPtr, &cb, &doneFilters);
AddClassFiltersToCallContext(oPtr, mixinPtr, &cb, &doneFilters,
TRAVERSED_MIXIN|BUILDING_MIXINS|OBJECT_MIXIN);
AddClassFiltersToCallContext(oPtr, mixinPtr, &cb, &doneFilters,
OBJECT_MIXIN);
}
FOREACH(filterObj, oPtr->filters) {
AddSimpleChainToCallContext(oPtr, filterObj, &cb, &doneFilters,
BUILDING_MIXINS, NULL);
AddSimpleChainToCallContext(oPtr, filterObj, &cb, &doneFilters, 0,
NULL);
}
AddClassFiltersToCallContext(oPtr, oPtr->selfCls, &cb, &doneFilters);
AddClassFiltersToCallContext(oPtr, oPtr->selfCls, &cb, &doneFilters,
BUILDING_MIXINS);
AddClassFiltersToCallContext(oPtr, oPtr->selfCls, &cb, &doneFilters,
0);
Tcl_DeleteHashTable(&doneFilters);
}
count = cb.filterLength = callPtr->numChain;
/*
* Add the actual method implementations.
* Add the actual method implementations. We have to do this twice to
* handle class mixins right.
*/
AddSimpleChainToCallContext(oPtr, methodNameObj, &cb, NULL,
flags|BUILDING_MIXINS, NULL);
AddSimpleChainToCallContext(oPtr, methodNameObj, &cb, NULL, flags, NULL);
/*
@@ -1057,6 +1084,8 @@ TclOOGetCallContext(
TclOODeleteChain(callPtr);
return NULL;
}
AddSimpleChainToCallContext(oPtr, oPtr->fPtr->unknownMethodNameObj,
&cb, NULL, BUILDING_MIXINS, NULL);
AddSimpleChainToCallContext(oPtr, oPtr->fPtr->unknownMethodNameObj,
&cb, NULL, 0, NULL);
callPtr->flags |= OO_UNKNOWN_METHOD;
@@ -1201,7 +1230,9 @@ TclOOGetStereotypeCallChain(
*/
Tcl_InitObjHashTable(&doneFilters);
AddClassFiltersToCallContext(&obj, clsPtr, &cb, &doneFilters);
AddClassFiltersToCallContext(&obj, clsPtr, &cb, &doneFilters,
BUILDING_MIXINS);
AddClassFiltersToCallContext(&obj, clsPtr, &cb, &doneFilters, 0);
Tcl_DeleteHashTable(&doneFilters);
count = cb.filterLength = callPtr->numChain;
@@ -1209,6 +1240,8 @@ TclOOGetStereotypeCallChain(
* Add the actual method implementations.
*/
AddSimpleChainToCallContext(&obj, methodNameObj, &cb, NULL,
flags|BUILDING_MIXINS, NULL);
AddSimpleChainToCallContext(&obj, methodNameObj, &cb, NULL, flags, NULL);
/*
@@ -1218,6 +1251,8 @@ TclOOGetStereotypeCallChain(
*/
if (count == callPtr->numChain) {
AddSimpleChainToCallContext(&obj, fPtr->unknownMethodNameObj, &cb,
NULL, BUILDING_MIXINS, NULL);
AddSimpleChainToCallContext(&obj, fPtr->unknownMethodNameObj, &cb,
NULL, 0, NULL);
callPtr->flags |= OO_UNKNOWN_METHOD;
@@ -1259,12 +1294,15 @@ AddClassFiltersToCallContext(
Class *clsPtr, /* Class to get the filters from. */
struct ChainBuilder *const cbPtr,
/* Context to fill with call chain entries. */
Tcl_HashTable *const doneFilters)
Tcl_HashTable *const doneFilters,
/* Where to record what filters have been
* processed. Keys are objects, values are
* ignored. */
int flags) /* Whether we've gone along a mixin link
* yet. */
{
int i;
int i, clearedFlags =
flags & ~(TRAVERSED_MIXIN|OBJECT_MIXIN|BUILDING_MIXINS);
Class *superPtr, *mixinPtr;
Tcl_Obj *filterObj;
@@ -1279,7 +1317,8 @@ AddClassFiltersToCallContext(
*/
FOREACH(mixinPtr, clsPtr->mixins) {
AddClassFiltersToCallContext(oPtr, mixinPtr, cbPtr, doneFilters);
AddClassFiltersToCallContext(oPtr, mixinPtr, cbPtr, doneFilters,
flags|TRAVERSED_MIXIN);
}
/*
@@ -1288,13 +1327,18 @@ AddClassFiltersToCallContext(
* override how filters work to extend their behaviour.
*/
FOREACH(filterObj, clsPtr->filters) {
int isNew;
if (MIXIN_CONSISTENT(flags)) {
FOREACH(filterObj, clsPtr->filters) {
int isNew;
(void) Tcl_CreateHashEntry(doneFilters, (char *) filterObj, &isNew);
if (isNew) {
AddSimpleChainToCallContext(oPtr, filterObj, cbPtr, doneFilters,
0, clsPtr);
(void) Tcl_CreateHashEntry(doneFilters, (char *) filterObj,
&isNew);
if (isNew) {
AddSimpleChainToCallContext(oPtr, filterObj, cbPtr,
doneFilters, clearedFlags|BUILDING_MIXINS, clsPtr);
AddSimpleChainToCallContext(oPtr, filterObj, cbPtr,
doneFilters, clearedFlags, clsPtr);
}
}
}
@@ -1308,7 +1352,8 @@ AddClassFiltersToCallContext(
goto tailRecurse;
default:
FOREACH(superPtr, clsPtr->superclasses) {
AddClassFiltersToCallContext(oPtr, superPtr, cbPtr, doneFilters);
AddClassFiltersToCallContext(oPtr, superPtr, cbPtr, doneFilters,
flags);
}
case 0:
return;
@@ -1355,16 +1400,16 @@ AddSimpleClassChainToCallContext(
tailRecurse:
FOREACH(superPtr, classPtr->mixins) {
AddSimpleClassChainToCallContext(superPtr, methodNameObj, cbPtr,
doneFilters, flags, filterDecl);
doneFilters, flags|TRAVERSED_MIXIN, filterDecl);
}
if (flags & CONSTRUCTOR) {
AddMethodToCallChain(classPtr->constructorPtr, cbPtr, doneFilters,
filterDecl);
filterDecl, flags);
} else if (flags & DESTRUCTOR) {
AddMethodToCallChain(classPtr->destructorPtr, cbPtr, doneFilters,
filterDecl);
filterDecl, flags);
} else {
Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&classPtr->classMethods,
(char *) methodNameObj);
@@ -1383,7 +1428,7 @@ AddSimpleClassChainToCallContext(
flags |= DEFINITE_PROTECTED;
}
}
AddMethodToCallChain(mPtr, cbPtr, doneFilters, filterDecl);
AddMethodToCallChain(mPtr, cbPtr, doneFilters, filterDecl, flags);
}
}
+38 -40
View File
@@ -5,19 +5,19 @@
#ifndef _TCLOODECLS
#define _TCLOODECLS
#undef TCL_STORAGE_CLASS
#ifdef BUILD_tcl
# define TCL_STORAGE_CLASS DLLEXPORT
#else
# ifdef USE_TCL_STUBS
# undef USE_TCLOO_STUBS
# define USE_TCLOO_STUBS
# define TCL_STORAGE_CLASS
#ifndef TCLAPI
# ifdef BUILD_tcl
# define TCLAPI extern DLLEXPORT
# else
# define TCL_STORAGE_CLASS DLLIMPORT
# define TCLAPI extern DLLIMPORT
# endif
#endif
#ifdef USE_TCL_STUBS
# undef USE_TCLOO_STUBS
# define USE_TCLOO_STUBS
#endif
/* !BEGIN!: Do not edit below this line. */
#ifdef __cplusplus
@@ -29,92 +29,92 @@ extern "C" {
*/
/* 0 */
EXTERN Tcl_Object Tcl_CopyObjectInstance(Tcl_Interp *interp,
TCLAPI Tcl_Object Tcl_CopyObjectInstance(Tcl_Interp *interp,
Tcl_Object sourceObject,
const char *targetName,
const char *targetNamespaceName);
/* 1 */
EXTERN Tcl_Object Tcl_GetClassAsObject(Tcl_Class clazz);
TCLAPI Tcl_Object Tcl_GetClassAsObject(Tcl_Class clazz);
/* 2 */
EXTERN Tcl_Class Tcl_GetObjectAsClass(Tcl_Object object);
TCLAPI Tcl_Class Tcl_GetObjectAsClass(Tcl_Object object);
/* 3 */
EXTERN Tcl_Command Tcl_GetObjectCommand(Tcl_Object object);
TCLAPI Tcl_Command Tcl_GetObjectCommand(Tcl_Object object);
/* 4 */
EXTERN Tcl_Object Tcl_GetObjectFromObj(Tcl_Interp *interp,
TCLAPI Tcl_Object Tcl_GetObjectFromObj(Tcl_Interp *interp,
Tcl_Obj *objPtr);
/* 5 */
EXTERN Tcl_Namespace * Tcl_GetObjectNamespace(Tcl_Object object);
TCLAPI Tcl_Namespace * Tcl_GetObjectNamespace(Tcl_Object object);
/* 6 */
EXTERN Tcl_Class Tcl_MethodDeclarerClass(Tcl_Method method);
TCLAPI Tcl_Class Tcl_MethodDeclarerClass(Tcl_Method method);
/* 7 */
EXTERN Tcl_Object Tcl_MethodDeclarerObject(Tcl_Method method);
TCLAPI Tcl_Object Tcl_MethodDeclarerObject(Tcl_Method method);
/* 8 */
EXTERN int Tcl_MethodIsPublic(Tcl_Method method);
TCLAPI int Tcl_MethodIsPublic(Tcl_Method method);
/* 9 */
EXTERN int Tcl_MethodIsType(Tcl_Method method,
TCLAPI int Tcl_MethodIsType(Tcl_Method method,
const Tcl_MethodType *typePtr,
ClientData *clientDataPtr);
/* 10 */
EXTERN Tcl_Obj * Tcl_MethodName(Tcl_Method method);
TCLAPI Tcl_Obj * Tcl_MethodName(Tcl_Method method);
/* 11 */
EXTERN Tcl_Method Tcl_NewInstanceMethod(Tcl_Interp *interp,
TCLAPI Tcl_Method Tcl_NewInstanceMethod(Tcl_Interp *interp,
Tcl_Object object, Tcl_Obj *nameObj,
int isPublic, const Tcl_MethodType *typePtr,
ClientData clientData);
/* 12 */
EXTERN Tcl_Method Tcl_NewMethod(Tcl_Interp *interp, Tcl_Class cls,
TCLAPI Tcl_Method Tcl_NewMethod(Tcl_Interp *interp, Tcl_Class cls,
Tcl_Obj *nameObj, int isPublic,
const Tcl_MethodType *typePtr,
ClientData clientData);
/* 13 */
EXTERN Tcl_Object Tcl_NewObjectInstance(Tcl_Interp *interp,
TCLAPI Tcl_Object Tcl_NewObjectInstance(Tcl_Interp *interp,
Tcl_Class cls, const char *nameStr,
const char *nsNameStr, int objc,
Tcl_Obj *const *objv, int skip);
/* 14 */
EXTERN int Tcl_ObjectDeleted(Tcl_Object object);
TCLAPI int Tcl_ObjectDeleted(Tcl_Object object);
/* 15 */
EXTERN int Tcl_ObjectContextIsFiltering(
TCLAPI int Tcl_ObjectContextIsFiltering(
Tcl_ObjectContext context);
/* 16 */
EXTERN Tcl_Method Tcl_ObjectContextMethod(Tcl_ObjectContext context);
TCLAPI Tcl_Method Tcl_ObjectContextMethod(Tcl_ObjectContext context);
/* 17 */
EXTERN Tcl_Object Tcl_ObjectContextObject(Tcl_ObjectContext context);
TCLAPI Tcl_Object Tcl_ObjectContextObject(Tcl_ObjectContext context);
/* 18 */
EXTERN int Tcl_ObjectContextSkippedArgs(
TCLAPI int Tcl_ObjectContextSkippedArgs(
Tcl_ObjectContext context);
/* 19 */
EXTERN ClientData Tcl_ClassGetMetadata(Tcl_Class clazz,
TCLAPI ClientData Tcl_ClassGetMetadata(Tcl_Class clazz,
const Tcl_ObjectMetadataType *typePtr);
/* 20 */
EXTERN void Tcl_ClassSetMetadata(Tcl_Class clazz,
TCLAPI void Tcl_ClassSetMetadata(Tcl_Class clazz,
const Tcl_ObjectMetadataType *typePtr,
ClientData metadata);
/* 21 */
EXTERN ClientData Tcl_ObjectGetMetadata(Tcl_Object object,
TCLAPI ClientData Tcl_ObjectGetMetadata(Tcl_Object object,
const Tcl_ObjectMetadataType *typePtr);
/* 22 */
EXTERN void Tcl_ObjectSetMetadata(Tcl_Object object,
TCLAPI void Tcl_ObjectSetMetadata(Tcl_Object object,
const Tcl_ObjectMetadataType *typePtr,
ClientData metadata);
/* 23 */
EXTERN int Tcl_ObjectContextInvokeNext(Tcl_Interp *interp,
TCLAPI int Tcl_ObjectContextInvokeNext(Tcl_Interp *interp,
Tcl_ObjectContext context, int objc,
Tcl_Obj *const *objv, int skip);
/* 24 */
EXTERN Tcl_ObjectMapMethodNameProc * Tcl_ObjectGetMethodNameMapper(
TCLAPI Tcl_ObjectMapMethodNameProc * Tcl_ObjectGetMethodNameMapper(
Tcl_Object object);
/* 25 */
EXTERN void Tcl_ObjectSetMethodNameMapper(Tcl_Object object,
TCLAPI void Tcl_ObjectSetMethodNameMapper(Tcl_Object object,
Tcl_ObjectMapMethodNameProc *mapMethodNameProc);
/* 26 */
EXTERN void Tcl_ClassSetConstructor(Tcl_Interp *interp,
TCLAPI void Tcl_ClassSetConstructor(Tcl_Interp *interp,
Tcl_Class clazz, Tcl_Method method);
/* 27 */
EXTERN void Tcl_ClassSetDestructor(Tcl_Interp *interp,
TCLAPI void Tcl_ClassSetDestructor(Tcl_Interp *interp,
Tcl_Class clazz, Tcl_Method method);
/* 28 */
EXTERN Tcl_Obj * Tcl_GetObjectName(Tcl_Interp *interp,
TCLAPI Tcl_Obj * Tcl_GetObjectName(Tcl_Interp *interp,
Tcl_Object object);
typedef struct {
@@ -231,6 +231,4 @@ extern const TclOOStubs *tclOOStubsPtr;
/* !END!: Do not edit above this line. */
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TCLOODECLS */
+16 -29
View File
@@ -5,17 +5,6 @@
#ifndef _TCLOOINTDECLS
#define _TCLOOINTDECLS
#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
/* !BEGIN!: Do not edit below this line. */
#ifdef __cplusplus
@@ -27,46 +16,46 @@ extern "C" {
*/
/* 0 */
EXTERN Tcl_Object TclOOGetDefineCmdContext(Tcl_Interp *interp);
TCLAPI Tcl_Object TclOOGetDefineCmdContext(Tcl_Interp *interp);
/* 1 */
EXTERN Tcl_Method TclOOMakeProcInstanceMethod(Tcl_Interp *interp,
TCLAPI Tcl_Method TclOOMakeProcInstanceMethod(Tcl_Interp *interp,
Object *oPtr, int flags, Tcl_Obj *nameObj,
Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
const Tcl_MethodType *typePtr,
ClientData clientData, Proc **procPtrPtr);
/* 2 */
EXTERN Tcl_Method TclOOMakeProcMethod(Tcl_Interp *interp,
TCLAPI Tcl_Method TclOOMakeProcMethod(Tcl_Interp *interp,
Class *clsPtr, int flags, Tcl_Obj *nameObj,
const char *namePtr, Tcl_Obj *argsObj,
Tcl_Obj *bodyObj,
const Tcl_MethodType *typePtr,
ClientData clientData, Proc **procPtrPtr);
/* 3 */
EXTERN Method * TclOONewProcInstanceMethod(Tcl_Interp *interp,
TCLAPI Method * TclOONewProcInstanceMethod(Tcl_Interp *interp,
Object *oPtr, int flags, Tcl_Obj *nameObj,
Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
ProcedureMethod **pmPtrPtr);
/* 4 */
EXTERN Method * TclOONewProcMethod(Tcl_Interp *interp, Class *clsPtr,
TCLAPI Method * TclOONewProcMethod(Tcl_Interp *interp, Class *clsPtr,
int flags, Tcl_Obj *nameObj,
Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
ProcedureMethod **pmPtrPtr);
/* 5 */
EXTERN int TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp,
TCLAPI int TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv,
int publicOnly, Class *startCls);
/* 6 */
EXTERN int TclOOIsReachable(Class *targetPtr, Class *startPtr);
TCLAPI int TclOOIsReachable(Class *targetPtr, Class *startPtr);
/* 7 */
EXTERN Method * TclOONewForwardMethod(Tcl_Interp *interp,
TCLAPI Method * TclOONewForwardMethod(Tcl_Interp *interp,
Class *clsPtr, int isPublic,
Tcl_Obj *nameObj, Tcl_Obj *prefixObj);
/* 8 */
EXTERN Method * TclOONewForwardInstanceMethod(Tcl_Interp *interp,
TCLAPI Method * TclOONewForwardInstanceMethod(Tcl_Interp *interp,
Object *oPtr, int isPublic, Tcl_Obj *nameObj,
Tcl_Obj *prefixObj);
/* 9 */
EXTERN Tcl_Method TclOONewProcInstanceMethodEx(Tcl_Interp *interp,
TCLAPI Tcl_Method TclOONewProcInstanceMethodEx(Tcl_Interp *interp,
Tcl_Object oPtr,
TclOO_PreCallProc *preCallPtr,
TclOO_PostCallProc *postCallPtr,
@@ -75,7 +64,7 @@ EXTERN Tcl_Method TclOONewProcInstanceMethodEx(Tcl_Interp *interp,
Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
int flags, void **internalTokenPtr);
/* 10 */
EXTERN Tcl_Method TclOONewProcMethodEx(Tcl_Interp *interp,
TCLAPI Tcl_Method TclOONewProcMethodEx(Tcl_Interp *interp,
Tcl_Class clsPtr,
TclOO_PreCallProc *preCallPtr,
TclOO_PostCallProc *postCallPtr,
@@ -84,22 +73,22 @@ EXTERN Tcl_Method TclOONewProcMethodEx(Tcl_Interp *interp,
Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
int flags, void **internalTokenPtr);
/* 11 */
EXTERN int TclOOInvokeObject(Tcl_Interp *interp,
TCLAPI int TclOOInvokeObject(Tcl_Interp *interp,
Tcl_Object object, Tcl_Class startCls,
int publicPrivate, int objc,
Tcl_Obj *const *objv);
/* 12 */
EXTERN void TclOOObjectSetFilters(Object *oPtr, int numFilters,
TCLAPI void TclOOObjectSetFilters(Object *oPtr, int numFilters,
Tcl_Obj *const *filters);
/* 13 */
EXTERN void TclOOClassSetFilters(Tcl_Interp *interp,
TCLAPI void TclOOClassSetFilters(Tcl_Interp *interp,
Class *classPtr, int numFilters,
Tcl_Obj *const *filters);
/* 14 */
EXTERN void TclOOObjectSetMixins(Object *oPtr, int numMixins,
TCLAPI void TclOOObjectSetMixins(Object *oPtr, int numMixins,
Class *const *mixins);
/* 15 */
EXTERN void TclOOClassSetMixins(Tcl_Interp *interp,
TCLAPI void TclOOClassSetMixins(Tcl_Interp *interp,
Class *classPtr, int numMixins,
Class *const *mixins);
@@ -174,6 +163,4 @@ extern const TclOOIntStubs *tclOOIntStubsPtr;
/* !END!: Do not edit above this line. */
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TCLOOINTDECLS */
+292 -2
View File
@@ -51,6 +51,8 @@ Tcl_Mutex tclObjMutex;
char tclEmptyString = '\0';
char *tclEmptyStringRep = &tclEmptyString;
ObjChunkHeader *tclObjChunkList = NULL;
#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
/*
* Structure for tracking the source file and line number where a given
@@ -1237,8 +1239,9 @@ Tcl_DbNewObj(
void
TclAllocateFreeObjects(void)
{
size_t bytesToAlloc = (OBJS_TO_ALLOC_EACH_TIME * sizeof(Tcl_Obj));
size_t bytesToAlloc = (sizeof(ObjChunkHeader) + OBJS_TO_ALLOC_EACH_TIME * sizeof(Tcl_Obj));
char *basePtr;
ObjChunkHeader *header;
register Tcl_Obj *prevPtr, *objPtr;
register int i;
@@ -1251,7 +1254,12 @@ TclAllocateFreeObjects(void)
* Purify apparently can't figure that out, and fires a false alarm.
*/
basePtr = ckalloc(bytesToAlloc);
header = (ObjChunkHeader *) ckalloc(bytesToAlloc);
header->next = tclObjChunkList;
header->end = (Tcl_Obj *)(((char *)header) + bytesToAlloc);
tclObjChunkList = header;
basePtr = (char *) (header + 1);
prevPtr = NULL;
objPtr = (Tcl_Obj *) basePtr;
@@ -4490,6 +4498,288 @@ Tcl_RepresentationCmd(
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_GcCmd --
*
* Implementation of the "tcl::unsupported::gc" command.
*
* Results:
* {purged $nbobj chunks {$start $total $used $start $total $used ...}}
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static void
BailOut(void)
{
exit(127);
}
static void
GcLog(
const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
static int
ComparePointers(
const void *a,
const void *b)
{
char *aa = *(char **)a;
char *bb = *(char **)b;
/*
* BEWARE: ptr difference (aa-bb) is *not* a proper order
* (an extra bit is needed for that)
* Hence we resort to explicit pointer comparison
* Which stores this bit in the Carry flag.
*/
return (aa<bb)?-1:((aa>bb)?1:0);
}
#define GC_BISECT_MIN_RECURS 4
static ObjChunkInfo *
GC_FindChunkInfo(
Tcl_Obj *obj,
ObjChunkInfo *itab,
int len)
{
while (1) {
int mid;
if (len <= GC_BISECT_MIN_RECURS) {
int i;
for(i = 0; i < len; i++, itab++) {
if ((obj>=itab->beg)&&(obj<itab->end)) {
return itab;
}
}
/* no Panic : avoid dumping core with a huge heap */
GcLog("### GC internal error: no chunk enclosing obj %p\n",obj);
BailOut();
}
mid = len / 2;
if (obj >= itab[mid].beg) {
itab += mid;
len -= mid;
} else {
len = mid;
}
}
}
#ifndef USE_THREAD_ALLOC
void
TclpLockAlloc(void)
{
Tcl_MutexLock(&tclObjMutex);
}
void
TclpUnlockAlloc(void)
{
Tcl_MutexUnlock(&tclObjMutex);
}
Tcl_Obj **
TclpGetGlobalFreeObj(void)
{
return &tclFreeObjList;
}
Tcl_Obj **
TclpGetLocalFreeObj(void)
{
return NULL;
}
void
TclpRecomputeGlobalNumObj(void)
{
}
void
TclpRecomputeLocalNumObj(void)
{
}
# define FREE_INTERNAL ckfree
#else
# define FREE_INTERNAL free
#endif
static Tcl_Obj *
DerefIf(
Tcl_Obj **src)
{
return (src ? (*src) : NULL);
}
#define NEXT_OBJ(objPtr) \
((objPtr)->internalRep.twoPtrValue.ptr1)
int
Tcl_GcCmd(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
int nch, i, npurge;
ObjChunkHeader *chunk, **tmp;
ObjChunkInfo *info, *infotab;
Tcl_Obj *obj;
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
TclpLockAlloc();
GcLog("GC Phase 1: prepare sorted list of chunk info\n");
nch = 0;
for (chunk = tclObjChunkList; chunk; chunk = chunk->next) {
nch++;
}
infotab = (ObjChunkInfo *) malloc(nch * sizeof(ObjChunkInfo));
tmp = (ObjChunkHeader **) infotab; /* pointers are smaller, so they fit */
for (chunk = tclObjChunkList; chunk; chunk = chunk->next) {
*(tmp++) = chunk;
}
qsort(infotab, nch, sizeof(ObjChunkHeader *), ComparePointers);
/* in-place cacheing of chunk headers into chunk infos */
for(i = nch - 1; i >= 0; i--) {
chunk = ((ObjChunkHeader **) infotab)[i];
info = infotab + i;
info->beg = (Tcl_Obj *)(chunk + 1);
info->end = chunk->end;
info->free = 0;
}
GcLog("GC Phase 2: scan free lists, locating each obj's chunk and "
"updating its free count\n");
for (obj = DerefIf(TclpGetLocalFreeObj()); obj != NULL;
obj = (Tcl_Obj *) NEXT_OBJ(obj)) {
info = GC_FindChunkInfo(obj, infotab, nch);
if (info) {
info->free++;
}
}
for (obj = DerefIf(TclpGetGlobalFreeObj()); obj != NULL;
obj = (Tcl_Obj *) NEXT_OBJ(obj)) {
info = GC_FindChunkInfo(obj, infotab, nch);
if (info) {
info->free++;
}
}
GcLog("GC Phase 3: locate chunks entirely made of free objs and mark them "
"with chunk->end=NULL and info->free=-1\n");
npurge = 0;
for (i = 0, info = infotab; i < nch; i++, info++) {
int room, delta;
room = info->end - info->beg;
delta = info->free - room;
chunk = ((ObjChunkHeader *)info->beg) - 1;
if (delta > 0) {
GcLog("# GC internal error: chunk at %p counts %ld frees but has "
"room for %d only !\n", chunk, info->free, room);
BailOut();
}
if (delta < 0) {
#if 0
GcLog(" . chunk %p : %d / %d\n", chunk, -delta, room);
#endif
continue;
}
/* here we have a purgeable chunk */
npurge += room;
chunk->end = NULL ; /* mark it for final sweep of chunks */
info->free = -1 ; /* mark it for final sweep of objs*/
#if 0
GcLog(" PURGE chunk %p : 0 / %d\n", chunk, room);
#endif
}
if (!npurge) {
GcLog(" Sorry - nothing to purge :(\n");
} else {
GcLog("GC Phase 4: remove the soon-to-be-purged objs from free "
"lists\n");
{
Tcl_Obj **pobj;
int n, p;
n = p = 0;
for (pobj = TclpGetLocalFreeObj(); *pobj != NULL ;) {
n++;
info = GC_FindChunkInfo(*pobj, infotab, nch);
if (info->free != -1) {
pobj = (Tcl_Obj **) & NEXT_OBJ(*pobj);
} else {
*pobj = (Tcl_Obj *) NEXT_OBJ(*pobj);
p++;
}
}
TclpRecomputeLocalNumObj();
GcLog(" (local: purge %d / %d\n", p, n);
n = p = 0;
for (pobj = TclpGetGlobalFreeObj(); *pobj != NULL ;) {
n++;
info = GC_FindChunkInfo(*pobj, infotab, nch);
if (info->free != -1) {
pobj = (Tcl_Obj **) & NEXT_OBJ(*pobj);
} else {
*pobj = (Tcl_Obj *) NEXT_OBJ(*pobj);
p++;
}
}
TclpRecomputeGlobalNumObj();
GcLog(" (global: purge %d / %d\n", p, n);
}
GcLog("GC Phase 5: free the located chunks, totalling %d objs\n",
npurge);
{
ObjChunkHeader **pchunk;
for (pchunk = &tclObjChunkList; (chunk = *pchunk) != NULL; ) {
if (chunk->end) {
pchunk = &chunk->next;
} else {
*pchunk = chunk->next;
FREE_INTERNAL(chunk);
}
}
}
free(infotab);
}
TclpUnlockAlloc();
return TCL_OK;
}
/*
* Local Variables:
* mode: c
+9 -15
View File
@@ -512,7 +512,7 @@ TclFSGetPathType(
if (PATHFLAGS(pathPtr) == 0) {
/* The path is not absolute... */
#ifdef __WIN32__
#ifdef _WIN32
/* ... on Windows we must make another call to determine whether
* it's relative or volumerelative [Bug 2571597]. */
return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr,
@@ -1956,7 +1956,7 @@ Tcl_FSGetNormalizedPath(
/*
* We have a refCount on the cwd.
*/
#ifdef __WIN32__
#ifdef _WIN32
} else if (type == TCL_PATH_VOLUME_RELATIVE) {
/*
* Only Windows has volume-relative paths.
@@ -1969,7 +1969,7 @@ Tcl_FSGetNormalizedPath(
return NULL;
}
pureNormalized = 0;
#endif /* __WIN32__ */
#endif /* _WIN32 */
}
}
@@ -2437,19 +2437,13 @@ SetFsPathFromAny(
}
TclDecrRefCount(parts);
} else {
/*
* Simple case. "rest" is relative path. Just join it. The
* "rest" object will be freed when Tcl_FSJoinToPath returns
* (unless something else claims a refCount on it).
*/
Tcl_Obj *pair[2];
Tcl_Obj *joined;
Tcl_Obj *rest = Tcl_NewStringObj(name+split+1, -1);
Tcl_IncrRefCount(transPtr);
joined = Tcl_FSJoinToPath(transPtr, 1, &rest);
TclDecrRefCount(transPtr);
transPtr = joined;
pair[0] = transPtr;
pair[1] = Tcl_NewStringObj(name+split+1, -1);
transPtr = TclJoinPath(2, pair);
Tcl_DecrRefCount(pair[0]);
Tcl_DecrRefCount(pair[1]);
}
}
} else {
+3 -3
View File
@@ -50,7 +50,7 @@ extern "C" {
* Exported function declarations:
*/
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
/* 0 */
EXTERN TCHAR * Tcl_WinUtfToTChar(const char *str, int len,
Tcl_DString *dsPtr);
@@ -75,7 +75,7 @@ typedef struct TclPlatStubs {
int magic;
void *hooks;
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
TCHAR * (*tcl_WinUtfToTChar) (const char *str, int len, Tcl_DString *dsPtr); /* 0 */
char * (*tcl_WinTCharToUtf) (const TCHAR *str, int len, Tcl_DString *dsPtr); /* 1 */
#endif /* WIN */
@@ -97,7 +97,7 @@ extern const TclPlatStubs *tclPlatStubsPtr;
* Inline function declarations:
*/
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
#define Tcl_WinUtfToTChar \
(tclPlatStubsPtr->tcl_WinUtfToTChar) /* 0 */
#define Tcl_WinTCharToUtf \
+32 -40
View File
@@ -1855,9 +1855,39 @@ InterpProcNR2(
}
/*
* Process the result code.
* Free the stack-allocated compiled locals and CallFrame. It is important
* to pop the call frame without freeing it first: the compiledLocals
* cannot be freed before the frame is popped, as the local variables must
* be deleted. But the compiledLocals must be freed first, as they were
* allocated later on the stack.
*/
if (result != TCL_OK) {
goto process;
}
done:
if (TCL_DTRACE_PROC_RESULT_ENABLED()) {
int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
Tcl_Obj *r = Tcl_GetObjResult(interp);
TCL_DTRACE_PROC_RESULT(l < iPtr->varFramePtr->objc ?
TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result,
TclGetString(r), r);
}
freePtr = iPtr->framePtr;
Tcl_PopCallFrame(interp); /* Pop but do not free. */
TclStackFree(interp, freePtr->compiledLocals);
/* Free compiledLocals. */
TclStackFree(interp, freePtr); /* Free CallFrame. */
return result;
/*
* Process any non-TCL_OK result code.
*/
process:
switch (result) {
case TCL_RETURN:
/*
@@ -1892,46 +1922,8 @@ InterpProcNR2(
*/
errorProc(interp, procNameObj);
default:
/*
* Process other results (OK and non-standard) by doing nothing
* special, skipping directly to the code afterwards that cleans up
* associated memory.
*
* Non-standard results are processed by passing them through quickly.
* This means they all work as exceptions, unwinding the stack quickly
* and neatly. Who knows how well they are handled by third-party code
* though...
*/
(void) 0; /* do nothing */
}
if (TCL_DTRACE_PROC_RESULT_ENABLED()) {
int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
Tcl_Obj *r = Tcl_GetObjResult(interp);
TCL_DTRACE_PROC_RESULT(l < iPtr->varFramePtr->objc ?
TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result,
TclGetString(r), r);
}
/*
* Free the stack-allocated compiled locals and CallFrame. It is important
* to pop the call frame without freeing it first: the compiledLocals
* cannot be freed before the frame is popped, as the local variables must
* be deleted. But the compiledLocals must be freed first, as they were
* allocated later on the stack.
*/
freePtr = iPtr->framePtr;
Tcl_PopCallFrame(interp); /* Pop but do not free. */
TclStackFree(interp, freePtr->compiledLocals);
/* Free compiledLocals. */
TclStackFree(interp, freePtr); /* Free CallFrame. */
return result;
goto done;
}
/*
Executable → Regular
View File
+79 -18
View File
@@ -1123,7 +1123,8 @@ Tcl_AppendLimitedToObj(
if (ellipsis == NULL) {
ellipsis = "...";
}
toCopy = Tcl_UtfPrev(bytes+limit+1-strlen(ellipsis), bytes) - bytes;
toCopy = (bytes == NULL) ? limit
: Tcl_UtfPrev(bytes+limit+1-strlen(ellipsis), bytes) - bytes;
}
/*
@@ -1281,23 +1282,43 @@ Tcl_AppendObjToObj(
if ((TclIsPureByteArray(objPtr) || objPtr->bytes == tclEmptyStringRep)
&& TclIsPureByteArray(appendObjPtr)) {
unsigned char *bytesSrc;
int lengthSrc, lengthTotal;
/*
* We do not assume that objPtr and appendObjPtr must be distinct!
* This makes this code a bit more complex than it otherwise would be,
* but in turn makes it much safer.
* You might expect the code here to be
*
* bytes = Tcl_GetByteArrayFromObj(appendObjPtr, &length);
* TclAppendBytesToByteArray(objPtr, bytes, length);
*
* and essentially all of the time that would be fine. However,
* it would run into trouble in the case where objPtr and
* appendObjPtr point to the same thing. That may never be a
* good idea. It seems to violate Copy On Write, and we don't
* have any tests for the situation, since making any Tcl commands
* that call Tcl_AppendObjToObj() do that appears impossible
* (They honor Copy On Write!). For the sake of extensions that
* go off into that realm, though, here's a more complex approach
* that can handle all the cases.
*/
/* Get lengths */
int lengthSrc;
(void) Tcl_GetByteArrayFromObj(objPtr, &length);
(void) Tcl_GetByteArrayFromObj(appendObjPtr, &lengthSrc);
lengthTotal = length + lengthSrc;
if (((length > lengthSrc) ? length : lengthSrc) > lengthTotal) {
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
}
bytesSrc = Tcl_GetByteArrayFromObj(appendObjPtr, NULL);
TclAppendBytesToByteArray(objPtr, bytesSrc, lengthSrc);
/* Grow buffer enough for the append */
TclAppendBytesToByteArray(objPtr, NULL, lengthSrc);
/* Reset objPtr back to the original value */
Tcl_SetByteArrayLength(objPtr, length);
/*
* Now do the append knowing that buffer growth cannot cause
* any trouble.
*/
TclAppendBytesToByteArray(objPtr,
Tcl_GetByteArrayFromObj(appendObjPtr, NULL), lengthSrc);
return;
}
@@ -1415,7 +1436,7 @@ AppendUnicodeToUnicodeRep(
* the reallocs below.
*/
if (unicode >= stringPtr->unicode
if (unicode && unicode >= stringPtr->unicode
&& unicode <= stringPtr->unicode + stringPtr->maxChars) {
offset = unicode - stringPtr->unicode;
}
@@ -1437,8 +1458,10 @@ AppendUnicodeToUnicodeRep(
* trailing null.
*/
memmove(stringPtr->unicode + stringPtr->numChars, unicode,
appendNumChars * sizeof(Tcl_UniChar));
if (unicode) {
memmove(stringPtr->unicode + stringPtr->numChars, unicode,
appendNumChars * sizeof(Tcl_UniChar));
}
stringPtr->unicode[numChars] = 0;
stringPtr->numChars = numChars;
stringPtr->allocated = 0;
@@ -1577,7 +1600,7 @@ AppendUtfToUtfRep(
* the reallocs below.
*/
if (bytes >= objPtr->bytes
if (bytes && bytes >= objPtr->bytes
&& bytes <= objPtr->bytes + objPtr->length) {
offset = bytes - objPtr->bytes;
}
@@ -1605,7 +1628,9 @@ AppendUtfToUtfRep(
stringPtr->numChars = -1;
stringPtr->hasUnicode = 0;
memmove(objPtr->bytes + oldLength, bytes, numBytes);
if (bytes) {
memmove(objPtr->bytes + oldLength, bytes, numBytes);
}
objPtr->bytes[newLength] = 0;
objPtr->length = newLength;
}
@@ -2635,6 +2660,38 @@ Tcl_ObjPrintf(
return objPtr;
}
/*
*---------------------------------------------------------------------------
*
* TclGetStringStorage --
*
* Returns the string storage space of a Tcl_Obj.
*
* Results:
* The pointer value objPtr->bytes is returned and the number of bytes
* allocated there is written to *sizePtr (if known).
*
* Side effects:
* May set objPtr->bytes.
*
*---------------------------------------------------------------------------
*/
char *
TclGetStringStorage(
Tcl_Obj *objPtr,
unsigned int *sizePtr)
{
String *stringPtr;
if (objPtr->typePtr != &tclStringType || objPtr->bytes == NULL) {
return TclGetStringFromObj(objPtr, (int *)sizePtr);
}
stringPtr = GET_STRING(objPtr);
*sizePtr = stringPtr->allocated;
return objPtr->bytes;
}
/*
*---------------------------------------------------------------------------
*
@@ -2828,7 +2885,11 @@ ExtendUnicodeRepWithString(
}
stringPtr->hasUnicode = 1;
stringPtr->numChars = needed;
if (bytes) {
stringPtr->numChars = needed;
} else {
numAppendChars = 0;
}
for (dst=stringPtr->unicode + numOrigChars; numAppendChars-- > 0; dst++) {
bytes += TclUtfToUniChar(bytes, dst);
}
+43
View File
@@ -0,0 +1,43 @@
/*
* tclStringTrim.h --
*
* This file contains the definition of what characters are to be trimmed
* from a string by [string trim] by default. It's only needed by Tcl's
* implementation; it does not form a public or private API at all.
*
* Copyright (c) 1987-1993 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 Scriptics Corporation.
* Copyright (c) 2002 ActiveState Corporation.
* Copyright (c) 2003-2013 Donal K. Fellows.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef TCL_STRING_TRIM_H
#define TCL_STRING_TRIM_H
/*
* Default set of characters to trim in [string trim] and friends. This is a
* UTF-8 literal string containing all Unicode space characters. [TIP #413]
*/
MODULE_SCOPE const char tclDefaultTrimSet[];
/*
* The whitespace trimming set used when [concat]enating. This is a subset of
* the above, and deliberately so.
*/
#define CONCAT_TRIM_SET " \f\v\r\t\n"
#endif /* TCL_STRING_TRIM_H */
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
+23 -15
View File
@@ -44,6 +44,9 @@
#define TclBackgroundException Tcl_BackgroundException
#undef Tcl_SetIntObj
#undef TclpInetNtoa
#undef TclWinGetServByName
#undef TclWinGetSockOpt
#undef TclWinSetSockOpt
/* See bug 510001: TclSockMinimumBuffers needs plat imp */
#ifdef _WIN64
@@ -90,7 +93,7 @@ static unsigned short TclWinNToHS(unsigned short ns) {
}
#endif
#ifdef __WIN32__
#ifdef _WIN32
# define TclUnixWaitForFile 0
# define TclUnixCopyFile 0
# define TclUnixOpenTemporaryFile 0
@@ -111,7 +114,8 @@ TclpIsAtty(int fd)
return isatty(fd);
}
int
#define TclWinGetPlatformId winGetPlatformId
static int
TclWinGetPlatformId()
{
/* Don't bother to determine the real platform on cygwin,
@@ -127,27 +131,31 @@ void *TclWinGetTclInstance()
return hInstance;
}
int
#define TclWinSetSockOpt winSetSockOpt
static int
TclWinSetSockOpt(SOCKET s, int level, int optname,
const char *optval, int optlen)
{
return setsockopt((int) s, level, optname, optval, optlen);
}
int
#define TclWinGetSockOpt winGetSockOpt
static int
TclWinGetSockOpt(SOCKET s, int level, int optname,
char *optval, int *optlen)
{
return getsockopt((int) s, level, optname, optval, optlen);
}
struct servent *
#define TclWinGetServByName winGetServByName
static struct servent *
TclWinGetServByName(const char *name, const char *proto)
{
return getservbyname(name, proto);
}
char *
#define TclWinNoBackslash winNoBackslash
static char *
TclWinNoBackslash(char *path)
{
char *p;
@@ -557,7 +565,7 @@ static const TclIntStubs tclIntStubs = {
static const TclIntPlatStubs tclIntPlatStubs = {
TCL_STUB_MAGIC,
0,
#if !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
TclGetAndDetachPids, /* 0 */
TclpCloseFile, /* 1 */
TclpCreateCommandChannel, /* 2 */
@@ -590,7 +598,7 @@ static const TclIntPlatStubs tclIntPlatStubs = {
TclWinCPUID, /* 29 */
TclUnixOpenTemporaryFile, /* 30 */
#endif /* UNIX */
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
TclWinConvertError, /* 0 */
TclWinConvertWSAError, /* 1 */
TclWinGetServByName, /* 2 */
@@ -661,7 +669,7 @@ static const TclIntPlatStubs tclIntPlatStubs = {
static const TclPlatStubs tclPlatStubs = {
TCL_STUB_MAGIC,
0,
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
Tcl_WinUtfToTChar, /* 0 */
Tcl_WinTCharToUtf, /* 1 */
#endif /* WIN */
@@ -758,19 +766,19 @@ const TclStubs tclStubs = {
Tcl_DbCkalloc, /* 6 */
Tcl_DbCkfree, /* 7 */
Tcl_DbCkrealloc, /* 8 */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
Tcl_CreateFileHandler, /* 9 */
#endif /* UNIX */
#if defined(__WIN32__) /* WIN */
#if defined(_WIN32) /* WIN */
0, /* 9 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
Tcl_CreateFileHandler, /* 9 */
#endif /* MACOSX */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
Tcl_DeleteFileHandler, /* 10 */
#endif /* UNIX */
#if defined(__WIN32__) /* WIN */
#if defined(_WIN32) /* WIN */
0, /* 10 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
@@ -932,10 +940,10 @@ const TclStubs tclStubs = {
Tcl_GetMaster, /* 164 */
Tcl_GetNameOfExecutable, /* 165 */
Tcl_GetObjResult, /* 166 */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
Tcl_GetOpenFile, /* 167 */
#endif /* UNIX */
#if defined(__WIN32__) /* WIN */
#if defined(_WIN32) /* WIN */
0, /* 167 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
+58
View File
@@ -0,0 +1,58 @@
/*
* tclStubLibTbl.c --
*
* Stub object that will be statically linked into extensions that want
* to access Tcl.
*
* Copyright (c) 1998-1999 by Scriptics Corporation.
* Copyright (c) 1998 Paul Duffin.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
/*
*----------------------------------------------------------------------
*
* TclInitStubTable --
*
* Initialize the stub table, using the structure pointed at
* by the "version" argument.
*
* Results:
* Outputs the value of the "version" argument.
*
* Side effects:
* Sets the stub table pointers.
*
*----------------------------------------------------------------------
*/
MODULE_SCOPE const char *
TclInitStubTable(
const char *version) /* points to the version field of a
TclStubInfoType structure variable. */
{
tclStubsPtr = ((const TclStubInfoType *) version)->stubs;
if (tclStubsPtr->hooks) {
tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs;
tclIntStubsPtr = tclStubsPtr->hooks->tclIntStubs;
tclIntPlatStubsPtr = tclStubsPtr->hooks->tclIntPlatStubs;
} else {
tclPlatStubsPtr = NULL;
tclIntStubsPtr = NULL;
tclIntPlatStubsPtr = NULL;
}
return version;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
+51 -10
View File
@@ -201,8 +201,9 @@ static int EncodingFromUtfProc(ClientData clientData,
int *dstCharsPtr);
static void ExitProcEven(ClientData clientData);
static void ExitProcOdd(ClientData clientData);
static int GetTimesCmd(ClientData clientData,
Tcl_Interp *interp, int argc, const char **argv);
static int GetTimesObjCmd(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
static void MainLoop(void);
static int NoopCmd(ClientData clientData,
Tcl_Interp *interp, int argc, const char **argv);
@@ -219,6 +220,9 @@ static void SpecialFree(char *blockPtr);
static int StaticInitProc(Tcl_Interp *interp);
static int TestasyncCmd(ClientData dummy,
Tcl_Interp *interp, int argc, const char **argv);
static int TestbytestringObjCmd(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
static int TestcmdinfoCmd(ClientData dummy,
Tcl_Interp *interp, int argc, const char **argv);
static int TestcmdtokenCmd(ClientData dummy,
@@ -414,7 +418,7 @@ static int TestNRELevels(ClientData clientData,
static int TestInterpResolverCmd(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
#if defined(HAVE_CPUID) || defined(__WIN32__)
#if defined(HAVE_CPUID) || defined(_WIN32)
static int TestcpuidCmd(ClientData dummy,
Tcl_Interp* interp, int objc,
Tcl_Obj *const objv[]);
@@ -556,9 +560,10 @@ Tcltest_Init(
* Create additional commands and math functions for testing Tcl.
*/
Tcl_CreateCommand(interp, "gettimes", GetTimesCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "gettimes", GetTimesObjCmd, NULL, NULL);
Tcl_CreateCommand(interp, "noop", NoopCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "noop", NoopObjCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "testbytestring", TestbytestringObjCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "testwrongnumargs", TestWrongNumArgsObjCmd,
NULL, NULL);
Tcl_CreateObjCommand(interp, "testfilesystem", TestFilesystemObjCmd,
@@ -681,7 +686,7 @@ Tcltest_Init(
NULL, NULL);
Tcl_CreateCommand(interp, "testexitmainloop", TestexitmainloopCmd,
NULL, NULL);
#if defined(HAVE_CPUID) || defined(__WIN32__)
#if defined(HAVE_CPUID) || defined(_WIN32)
Tcl_CreateObjCommand(interp, "testcpuid", TestcpuidCmd,
(ClientData) 0, NULL);
#endif
@@ -4717,7 +4722,7 @@ TestgetvarfullnameCmd(
/*
*----------------------------------------------------------------------
*
* GetTimesCmd --
* GetTimesObjCmd --
*
* This procedure implements the "gettimes" command. It is used for
* computing the time needed for various basic operations such as reading
@@ -4733,11 +4738,11 @@ TestgetvarfullnameCmd(
*/
static int
GetTimesCmd(
GetTimesObjCmd(
ClientData unused, /* Unused. */
Tcl_Interp *interp, /* The current interpreter. */
int argc, /* The number of arguments. */
const char **argv) /* The argument strings. */
int notused1, /* Number of arguments. */
Tcl_Obj *const notused2[]) /* The argument objects. */
{
Interp *iPtr = (Interp *) interp;
int i, n;
@@ -4948,6 +4953,42 @@ NoopObjCmd(
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TestbytestringObjCmd --
*
* This object-based procedure constructs a string which can
* possibly contain invalid UTF-8 bytes.
*
* Results:
* Returns the TCL_OK result code.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
TestbytestringObjCmd(
ClientData unused, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* The argument objects. */
{
int n;
const char *p;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "bytearray");
return TCL_ERROR;
}
p = (const char *)Tcl_GetByteArrayFromObj(objv[1], &n);
Tcl_SetObjResult(interp, Tcl_NewStringObj(p, n));
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
@@ -6648,7 +6689,7 @@ TestNumUtfCharsCmd(
return TCL_OK;
}
#if defined(HAVE_CPUID) || defined(__WIN32__)
#if defined(HAVE_CPUID) || defined(_WIN32)
/*
*----------------------------------------------------------------------
*
+6 -2
View File
@@ -339,8 +339,9 @@ Tcl_ConditionFinalize(
*
* TclFinalizeThreadData --
*
* This function cleans up the thread-local storage. This is called once
* for each thread.
* This function cleans up the thread-local storage. Secondary, it cleans
* thread alloc cache.
* This is called once for each thread before thread exits.
*
* Results:
* None.
@@ -355,6 +356,9 @@ void
TclFinalizeThreadData(void)
{
TclFinalizeThreadDataThread();
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
TclFinalizeThreadAllocThread();
#endif
}
/*
+102 -9
View File
@@ -217,10 +217,11 @@ GetCache(void)
cachePtr = TclpGetAllocCache();
if (cachePtr == NULL) {
cachePtr = calloc(1, sizeof(Cache));
cachePtr = TclpSysAlloc(sizeof(Cache), 0);
if (cachePtr == NULL) {
Tcl_Panic("alloc: could not allocate new cache");
}
memset(cachePtr, 0, sizeof(Cache));
Tcl_MutexLock(listLockPtr);
cachePtr->nextPtr = firstCachePtr;
firstCachePtr = cachePtr;
@@ -287,7 +288,7 @@ TclFreeAllocCache(
*nextPtrPtr = cachePtr->nextPtr;
cachePtr->nextPtr = NULL;
Tcl_MutexUnlock(listLockPtr);
free(cachePtr);
TclpSysFree(cachePtr);
}
/*
@@ -332,7 +333,7 @@ TclpAlloc(
/*
* Increment the requested size to include room for the Block structure.
* Call malloc() directly if the required amount is greater than the
* Call TclpSysAlloc() directly if the required amount is greater than the
* largest block, otherwise pop the smallest block large enough,
* allocating more blocks if necessary.
*/
@@ -344,7 +345,7 @@ TclpAlloc(
#endif
if (size > MAXALLOC) {
bucket = NBUCKETS;
blockPtr = malloc(size);
blockPtr = TclpSysAlloc(size, 0);
if (blockPtr != NULL) {
cachePtr->totalAssigned += reqSize;
}
@@ -407,7 +408,7 @@ TclpFree(
bucket = blockPtr->sourceBucket;
if (bucket == NBUCKETS) {
cachePtr->totalAssigned -= blockPtr->blockReqSize;
free(blockPtr);
TclpSysFree(blockPtr);
return;
}
@@ -472,7 +473,7 @@ TclpRealloc(
/*
* If the block is not a system block and fits in place, simply return the
* existing pointer. Otherwise, if the block is a system block and the new
* size would also require a system block, call realloc() directly.
* size would also require a system block, call TclpSysRealloc() directly.
*/
blockPtr = Ptr2Block(ptr);
@@ -495,7 +496,7 @@ TclpRealloc(
} else if (size > MAXALLOC) {
cachePtr->totalAssigned -= blockPtr->blockReqSize;
cachePtr->totalAssigned += reqSize;
blockPtr = realloc(blockPtr, size);
blockPtr = TclpSysRealloc(blockPtr, size);
if (blockPtr == NULL) {
return NULL;
}
@@ -567,7 +568,7 @@ TclThreadAllocObj(void)
Tcl_Obj *newObjsPtr;
cachePtr->numObjects = numMove = NOBJALLOC;
newObjsPtr = malloc(sizeof(Tcl_Obj) * numMove);
newObjsPtr = (Tcl_Obj *)(((ObjChunkHeader *)TclpSysAlloc(sizeof(ObjChunkHeader) + sizeof(Tcl_Obj) * numMove, 0)) + 1);
if (newObjsPtr == NULL) {
Tcl_Panic("alloc: could not allocate %d new objects", numMove);
}
@@ -576,6 +577,16 @@ TclThreadAllocObj(void)
objPtr->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr;
cachePtr->firstObjPtr = objPtr;
}
{
ObjChunkHeader *chunk = ((ObjChunkHeader *)newObjsPtr) - 1;
chunk->end = newObjsPtr + NOBJALLOC;
Tcl_MutexLock(objLockPtr);
chunk->next = tclObjChunkList;
tclObjChunkList = chunk;
Tcl_MutexUnlock(objLockPtr);
}
}
}
@@ -964,7 +975,7 @@ GetBlocks(
if (blockPtr == NULL) {
size = MAXALLOC;
blockPtr = malloc(size);
blockPtr = TclpSysAlloc(size, 0);
if (blockPtr == NULL) {
return 0;
}
@@ -1023,6 +1034,88 @@ TclFinalizeThreadAlloc(void)
TclpFreeAllocCache(NULL);
}
/*
*----------------------------------------------------------------------
*
* TclFinalizeThreadAllocThread --
*
* This procedure is used to destroy single thread private resources used
* in this file.
* Called in TclpFinalizeThreadData when a thread exits (Tcl_FinalizeThread).
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
TclFinalizeThreadAllocThread(void)
{
Cache *cachePtr = TclpGetAllocCache();
if (cachePtr != NULL) {
TclpFreeAllocCache(cachePtr);
}
}
/*
*----------------------------------------------------------------------
*
* TclpLockAlloc, TclpUnlockAlloc, TclpGetGlobalFreeObj, TclpGetLocalFreeObj --
* These functions allow outside callers to reach safely into our internal
* state for inspection or gc.
*----------------------------------------------------------------------
*/
void
TclpLockAlloc(void)
{
Tcl_MutexLock(objLockPtr);
}
void
TclpUnlockAlloc(void)
{
Tcl_MutexUnlock(objLockPtr);
}
Tcl_Obj **
TclpGetGlobalFreeObj(void)
{
return &sharedPtr->firstObjPtr;
}
Tcl_Obj **
TclpGetLocalFreeObj(void)
{
Cache *cachePtr;
GETCACHE(cachePtr);
return &cachePtr->firstObjPtr;
}
void TclpRecomputeGlobalNumObj(void)
{
int n;
Tcl_Obj *obj;
for(n=0,obj=sharedPtr->firstObjPtr;obj;obj=(Tcl_Obj *)obj->internalRep.twoPtrValue.ptr1,n++);
sharedPtr->numObjects = n;
}
void TclpRecomputeLocalNumObj(void)
{
int n;
Tcl_Obj *obj;
Cache *cachePtr;
GETCACHE(cachePtr);
for(n=0,obj=cachePtr->firstObjPtr;obj;obj=(Tcl_Obj *)obj->internalRep.twoPtrValue.ptr1,n++);
cachePtr->numObjects = n;
}
#else /* !(TCL_THREADS && USE_THREAD_ALLOC) */
/*
*----------------------------------------------------------------------
+2 -2
View File
@@ -14,7 +14,7 @@
#include "tclInt.h"
#ifdef WIN32
#ifdef _WIN32
/*
* The information about each joinable thread is remembered in a structure as
@@ -305,7 +305,7 @@ TclSignalExitThread(
Tcl_MutexUnlock(&threadPtr->threadMutex);
}
#endif /* WIN32 */
#endif /* _WIN32 */
/*
* Local Variables:
+1154 -1066
View File
File diff suppressed because it is too large Load Diff
+95 -26
View File
@@ -14,6 +14,7 @@
#include "tclInt.h"
#include "tclParse.h"
#include "tclStringTrim.h"
#include <math.h>
/*
@@ -110,7 +111,11 @@ static Tcl_HashTable * GetThreadHash(Tcl_ThreadDataKey *keyPtr);
static int SetEndOffsetFromAny(Tcl_Interp *interp,
Tcl_Obj *objPtr);
static void UpdateStringOfEndOffset(Tcl_Obj *objPtr);
static int FindElement(Tcl_Interp *interp, const char *string,
int stringLength, const char *typeStr,
const char *typeCode, const char **elementPtr,
const char **nextPtr, int *sizePtr,
int *literalPtr);
/*
* The following is the Tcl object type definition for an object that
* represents a list index in the form, "end-offset". It is used as a
@@ -236,7 +241,7 @@ const Tcl_ObjType tclEndOffsetType = {
* of either braces or quotes to delimit it.
*
* This collection of parsing rules is implemented in the routine
* TclFindElement().
* FindElement().
*
* In order to produce lists that can be parsed by these rules, we need the
* ability to distinguish between characters that are part of a list element
@@ -504,9 +509,70 @@ TclFindElement(
* does not/does require a call to
* TclCopyAndCollapse() by the caller. */
{
const char *p = list;
return FindElement(interp, list, listLength, "list", "LIST", elementPtr,
nextPtr, sizePtr, literalPtr);
}
int
TclFindDictElement(
Tcl_Interp *interp, /* Interpreter to use for error reporting. If
* NULL, then no error message is left after
* errors. */
const char *dict, /* Points to the first byte of a string
* containing a Tcl dictionary with zero or
* more keys and values (possibly in
* braces). */
int dictLength, /* Number of bytes in the dict's string. */
const char **elementPtr, /* Where to put address of first significant
* character in the first element (i.e., key
* or value) of dict. */
const char **nextPtr, /* Fill in with location of character just
* after all white space following end of
* element (next arg or end of list). */
int *sizePtr, /* If non-zero, fill in with size of
* element. */
int *literalPtr) /* If non-zero, fill in with non-zero/zero to
* indicate that the substring of *sizePtr
* bytes starting at **elementPtr is/is not
* the literal key or value and therefore
* does not/does require a call to
* TclCopyAndCollapse() by the caller. */
{
return FindElement(interp, dict, dictLength, "dict", "DICTIONARY",
elementPtr, nextPtr, sizePtr, literalPtr);
}
static int
FindElement(
Tcl_Interp *interp, /* Interpreter to use for error reporting. If
* NULL, then no error message is left after
* errors. */
const char *string, /* Points to the first byte of a string
* containing a Tcl list or dictionary with
* zero or more elements (possibly in
* braces). */
int stringLength, /* Number of bytes in the string. */
const char *typeStr, /* The name of the type of thing we are
* parsing, for error messages. */
const char *typeCode, /* The type code for thing we are parsing, for
* error messages. */
const char **elementPtr, /* Where to put address of first significant
* character in first element. */
const char **nextPtr, /* Fill in with location of character just
* after all white space following end of
* argument (next arg or end of list/dict). */
int *sizePtr, /* If non-zero, fill in with size of
* element. */
int *literalPtr) /* If non-zero, fill in with non-zero/zero to
* indicate that the substring of *sizePtr
* bytes starting at **elementPtr is/is not
* the literal list/dict element and therefore
* does not/does require a call to
* TclCopyAndCollapse() by the caller. */
{
const char *p = string;
const char *elemStart; /* Points to first byte of first element. */
const char *limit; /* Points just after list's last byte. */
const char *limit; /* Points just after list/dict's last byte. */
int openBraces = 0; /* Brace nesting level during parse. */
int inQuotes = 0;
int size = 0; /* lint. */
@@ -516,11 +582,11 @@ TclFindElement(
/*
* 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.
* We treat embedded NULLs in the list/dict as bytes belonging to a list
* element (or dictionary key or value).
*/
limit = (list + listLength);
limit = (string + stringLength);
while ((p < limit) && (TclIsSpaceProc(*p))) {
p++;
}
@@ -581,9 +647,9 @@ TclFindElement(
p2++;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"list element in braces followed by \"%.*s\" "
"instead of space", (int) (p2-p), p));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "LIST", "JUNK",
"%s element in braces followed by \"%.*s\" "
"instead of space", typeStr, (int) (p2-p), p));
Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "JUNK",
NULL);
}
return TCL_ERROR;
@@ -650,9 +716,9 @@ TclFindElement(
p2++;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"list element in quotes followed by \"%.*s\" "
"instead of space", (int) (p2-p), p));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "LIST", "JUNK",
"%s element in quotes followed by \"%.*s\" "
"instead of space", typeStr, (int) (p2-p), p));
Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "JUNK",
NULL);
}
return TCL_ERROR;
@@ -663,23 +729,23 @@ TclFindElement(
}
/*
* End of list: terminate element.
* End of list/dict: terminate element.
*/
if (p == limit) {
if (openBraces != 0) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"unmatched open brace in list", -1));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "LIST", "BRACE",
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"unmatched open brace in %s", typeStr));
Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "BRACE",
NULL);
}
return TCL_ERROR;
} else if (inQuotes) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"unmatched open quote in list", -1));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "LIST", "QUOTE",
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"unmatched open quote in %s", typeStr));
Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "QUOTE",
NULL);
}
return TCL_ERROR;
@@ -1768,8 +1834,7 @@ TclTrimLeft(
*/
/* The whitespace characters trimmed during [concat] operations */
#define CONCAT_WS " \f\v\r\t\n"
#define CONCAT_WS_SIZE (int) (sizeof(CONCAT_WS "") - 1)
#define CONCAT_WS_SIZE (int) (sizeof(CONCAT_TRIM_SET "") - 1)
char *
Tcl_Concat(
@@ -1825,7 +1890,8 @@ Tcl_Concat(
* Trim away the leading whitespace.
*/
trim = TclTrimLeft(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
element += trim;
elemLength -= trim;
@@ -1834,7 +1900,8 @@ Tcl_Concat(
* a final backslash character.
*/
trim = TclTrimRight(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
trim -= trim && (element[elemLength - trim - 1] == '\\');
elemLength -= trim;
@@ -1959,7 +2026,8 @@ Tcl_ConcatObj(
* Trim away the leading whitespace.
*/
trim = TclTrimLeft(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
element += trim;
elemLength -= trim;
@@ -1968,7 +2036,8 @@ Tcl_ConcatObj(
* a final backslash character.
*/
trim = TclTrimRight(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
trim -= trim && (element[elemLength - trim - 1] == '\\');
elemLength -= trim;
+3
View File
@@ -1958,6 +1958,9 @@ TclPtrSetVar(
Tcl_IncrRefCount(oldValuePtr); /* Since var is ref */
}
Tcl_AppendObjToObj(oldValuePtr, newValuePtr);
if (newValuePtr->refCount == 0) {
Tcl_DecrRefCount(newValuePtr);
}
}
}
} else if (newValuePtr != oldValuePtr) {
+12 -44
View File
@@ -26,7 +26,7 @@
* interface, even if that is mostly true).
*/
#define TCL_ZLIB_VERSION "2.0"
#define TCL_ZLIB_VERSION "2.0.1"
/*
* Magic flags used with wbits fields to indicate that we're handling the gzip
@@ -643,7 +643,6 @@ Tcl_ZlibStreamInit(
int e;
ZlibStreamHandle *zshPtr = NULL;
Tcl_DString cmdname;
Tcl_CmdInfo cmdinfo;
GzipHeader *gzHeaderPtr = NULL;
switch (mode) {
@@ -769,8 +768,8 @@ Tcl_ZlibStreamInit(
Tcl_DStringInit(&cmdname);
TclDStringAppendLiteral(&cmdname, "::tcl::zlib::streamcmd_");
TclDStringAppendObj(&cmdname, Tcl_GetObjResult(interp));
if (Tcl_GetCommandInfo(interp, Tcl_DStringValue(&cmdname),
&cmdinfo) == 1) {
if (Tcl_FindCommand(interp, Tcl_DStringValue(&cmdname),
NULL, 0) != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"BUG: Stream command name already exists", -1));
Tcl_SetErrorCode(interp, "TCL", "BUG", "EXISTING_CMD", NULL);
@@ -2911,6 +2910,10 @@ ZlibTransformClose(
* Release all memory.
*/
if (cd->compDictObj) {
Tcl_DecrRefCount(cd->compDictObj);
cd->compDictObj = NULL;
}
Tcl_DStringFree(&cd->decompressed);
if (cd->inBuffer) {
@@ -2994,47 +2997,18 @@ ZlibTransformInput(
*/
if (readBytes < 0) {
/*
* Report errors to caller. The state of the seek system is
* unchanged!
*/
if ((Tcl_GetErrno() == EAGAIN) && (gotBytes > 0)) {
/*
* EAGAIN is a special situation. If we had some data before
* we report that instead of the request to re-try.
*/
/* See ReflectInput() in tclIORTrans.c */
if (Tcl_InputBlocked(cd->parent) && (gotBytes > 0)) {
return gotBytes;
}
*errorCodePtr = Tcl_GetErrno();
return -1;
} else if (readBytes == 0) {
}
if (readBytes == 0) {
/*
* Check wether we hit on EOF in 'parent' or not. If not,
* differentiate between blocking and non-blocking modes. In
* non-blocking mode we ran temporarily out of data. Signal this
* to the caller via EWOULDBLOCK and error return (-1). In the
* other cases we simply return what we got and let the caller
* wait for more. On the other hand, if we got an EOF we have to
* convert and flush all waiting partial data.
*/
if (!Tcl_Eof(cd->parent)) {
/*
* The state of the seek system is unchanged!
*/
if ((gotBytes == 0) && (cd->flags & ASYNC)) {
*errorCodePtr = EWOULDBLOCK;
return -1;
}
return gotBytes;
}
/*
* (Semi-)Eof in parent.
* Eof in parent.
*
* Now this is a bit different. The partial data waiting is
* converted and returned.
@@ -3052,12 +3026,6 @@ ZlibTransformInput(
return gotBytes;
}
/*
* Reset eof, force caller to drain result buffer.
*/
((Channel *) cd->parent)->state->flags &= ~CHANNEL_EOF;
} else /* readBytes > 0 */ {
/*
* Transform the read chunk, which was not empty. Anything we get
+4 -4
View File
@@ -1227,8 +1227,8 @@ proc ::tcl::clock::scan { args } {
}
default {
return -code error \
-errorcode [list CLOCK badSwitch $flag] \
"bad switch \"$flag\",\
-errorcode [list CLOCK badOption $flag] \
"bad option \"$flag\",\
must be -base, -format, -gmt, -locale or -timezone"
}
}
@@ -4295,8 +4295,8 @@ proc ::tcl::clock::add { clockval args } {
set timezone $b
}
default {
throw [list CLOCK badSwitch $a] \
"bad switch \"$a\",\
throw [list CLOCK badOption $a] \
"bad option \"$a\",\
must be -gmt, -locale or -timezone"
}
}
Executable → Regular
View File
+3 -2
View File
@@ -16,7 +16,7 @@
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.6.1
package require -exact Tcl 8.6.2
# Compute the auto path to use in this interpreter.
# The values on the path come from several locations:
@@ -398,7 +398,8 @@ proc unknown args {
return -code error "ambiguous command name \"$name\": [lsort $cmds]"
}
}
return -code error "invalid command name \"$name\""
return -code error -errorcode [list TCL LOOKUP COMMAND $name] \
"invalid command name \"$name\""
}
# auto_load --
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File

Some files were not shown because too many files have changed in this diff Show More