Compare commits

...
Author SHA1 Message Date
dgp 1ddabb17f9 Support TCL_ENCODING_CHAR_LIMIT in TableToUtfProc and EscapeToUtfProc drivers. 2014-12-23 17:53:21 +00:00
dgp a3babfe12a Support TCL_ENCODING_CHAR_LIMIT in the Iso88591ToUtfProc driver. 2014-12-23 17:48:36 +00:00
dgp b6fecacc22 Support TCL_ENCODING_CHAR_LIMIT in the UnicodeToUtfProc driver. 2014-12-23 17:46:05 +00:00
dgp 360b5c41ee Support TCL_ENCODING_CHAR_LIMIT in the UtfToUtfProc driver. 2014-12-23 17:26:07 +00:00
dgp 5a6443d00e Support TCL_ENCODING_CHAR_LIMIT in the BinaryProc driver. 2014-12-23 17:13:13 +00:00
dgp 7134cd9399 Use the new TCL_ENCODING_CHAR_LIMIT flag to have the encoding system manage
the max chars to read constraint.
2014-12-23 16:57:02 +00:00
dgp 1a92fb378c merge trunk 2014-12-23 03:11:01 +00:00
dgp ef6f1ba2c3 Use more suitable variable name pushers. 2014-12-23 02:41:54 +00:00
dgp b0078c8129 Eliminate TclIsLocalScalar(). No callers left. 2014-12-23 02:12:59 +00:00
dgp 49e7d0262b Revise CompileEachloopCmd() to use LocalScalar() in place of TclIsLocalScalar(). 2014-12-23 01:28:30 +00:00
dgp 2cbec4bf44 Convert the LocalScalar*() macros to rest on TclPushVarName rather than on
TclIsLocalScalar().
2014-12-22 20:27:14 +00:00
dgp 7ac39417f1 Use (interp == NULL) argument to TclPushVarName() to signal that no compiling
is desired.  Only a lookup of an index into the compiled variable table.
2014-12-22 20:13:29 +00:00
dgp 3faf4cc3b8 More complete use of the TCL_NO_ELEMENT flag to suppress useless actions. 2014-12-22 19:57:36 +00:00
dgp 9f699d22a2 merge mark 2014-12-22 17:12:50 +00:00
dgp 13667e8096 One more (interp==NULL) shortcut. 2014-12-22 15:35:47 +00:00
dgp 51f7688e96 merge-mark. The compiler machinery has changed too much for any hope for
a successful merge.  TclIsLocalScalar() elimination will need to be done
on trunk as an independent effort.
2014-12-19 17:57:04 +00:00
dgp f6d6b394eb Revise name and interface of new utility routines to match work already
in place on the trunk.
2014-12-19 17:09:32 +00:00
dgp 7e44dabec3 [e711ffb458] Eliminate TclIsLocalScalar() and revise all callers to use
more appropriate facilities.
2014-12-19 16:09:20 +00:00
dgp cfefe7127b New utility routine GetLocalScalarIndex() reduces common caller boilerplate
(and fixes a bug!)
2014-12-19 15:55:21 +00:00
dgp 2613112a13 Use interp==NULL argument to PushVarName to signal that only an index into
the CLT is sought, and no time should be wasted compiling other cases which
the caller is just going to discard.
2014-12-19 15:13:11 +00:00
dgp 18131f9c09 With no callers left, TclIsLocalScalar() is removed. 2014-12-19 14:21:42 +00:00
dgp baf649278a Replace TclIsLocalScalar() with PushVarNameWord() in [dict for] compiler. 2014-12-19 14:17:03 +00:00
dgp 88ec3c9772 Narrow scope of numVars. 2014-12-19 03:31:09 +00:00
dgp ad19550909 A bit more tidying... 2014-12-18 22:25:27 +00:00
dgp aed72bee30 No need for a loopIndex. 2014-12-18 22:13:11 +00:00
dgp f65cb994d8 No need for varvList any more. 2014-12-18 22:00:08 +00:00
dgp 893c9c7302 Fix up the token array passed to PushVarNameWord. Remove string list parse. 2014-12-18 21:29:07 +00:00
dgp 24817641b1 Replace use of TclIsLocalScalar() and late setting of varIndexes with an
earlier setting of varIndexes using PushVarNameWord().
2014-12-18 21:08:53 +00:00
dgp 89e6a65411 Simplify creation and storage of temporaries 2014-12-18 20:38:53 +00:00
dgp f664d633e6 With that shift, varcList is no longer needed. 2014-12-18 20:34:12 +00:00
dgp d56e61b246 Shift the allocation of AuxData earlier in the [foreach] compiler. 2014-12-18 19:21:31 +00:00
dgp 8dd58baa04 merge 8.5 2014-12-18 18:16:10 +00:00
dgp 559113cc4c [7c187a3773] Fix error in managing inStatePtr->inQueueTail value in the
byte-moving optimized path of [chan copy].  Thanks to Benno.
2014-12-18 18:06:51 +00:00
dgp 5dafefe112 [af08e89777] Rework finalization to stop encoding-24.2 segfault. 2014-12-18 14:38:26 +00:00
dgp 955507f635 Rework the *FinalizeThread*() routines so that the quick exit preference
is respected without need to run afoul of encoding finalizations.
tests pass now.  All changes are fully internal.
2014-12-17 20:47:58 +00:00
dgp e942227f6e Revise encoding finalization so that it does a more complete job of restoring
the pre-initialized state.  This makes finalization errors more repeatable
and cross-platform.
2014-12-17 19:57:40 +00:00
oehhar 68b5780dde changes for TIP427 2014-12-17 11:21:16 +00:00
oehhar 3b7664e77f Include option -connecting in test iocmd-8.15.1 2014-12-17 08:42:24 +00:00
oehhar b47b88af9b TIP-427: make "fconfigure $h -connecting" official (client sockets only) 2014-12-17 08:24:33 +00:00
oehhar d7a9d63520 Documented "fconfigure $h -connecting" on socket man page 2014-12-17 08:22:23 +00:00
oehhar f716d8815b Merge trunk 2014-12-17 07:53:41 +00:00
jan.nijtmans 4e0313afe2 85 -> 86 2014-12-15 10:20:39 +00:00
jan.nijtmans d9b30b94b8 merge-mark 2014-12-14 12:13:30 +00:00
Kevin Walzer 2f8ea1be7c Add header install flag to OS X GNUMakefile; thanks to Stephan Houben for patch 2014-12-13 02:50:07 +00:00
Kevin Walzer 59cb45cc16 Add header install flag to OS X GNUMakefile; thanks to Stephan Houben for patch 2014-12-13 02:47:25 +00:00
dgp ee5c231ff5 Similar conversion of the [dict append] compiler. 2014-12-11 16:00:19 +00:00
dgp 604faa265f Similar conversion for [dict update] compiler. 2014-12-11 15:45:16 +00:00
dgp 8e80c62f6f Similar revisions to [dict incr] compiler. 2014-12-11 15:19:38 +00:00
dgp a417c667a5 Get the word number right, even though it has no effect. 2014-12-11 14:41:09 +00:00
dgp 26326004c6 [e711ffb458] Same conversion for [catch] compiler. 2014-12-11 14:40:02 +00:00
venkat 0318c256ed merge tzdata2014j from ietf.org 2014-12-10 00:37:24 +00:00
venkat 704532c57a tzdata2014j from ietf.org 2014-12-10 00:35:37 +00:00
dgp 2d415cbf59 [e711ffb458] Replace TclIsLocalScalar() with PushVarNameWord() in the
compiler for [dict set].
2014-12-09 20:45:30 +00:00
dgp 916f1716f3 [e711ffb458] Replace TclIsLocalScalar() (which does the wrong thing).... with
PushVarNameWord() (which doesn't) in the compiler for [dict lappend].
2014-12-09 20:29:09 +00:00
jan.nijtmans d297273a13 Fix some gcc compiler warnings (probably cygwin-only) 2014-12-08 16:10:00 +00:00
jan.nijtmans b27238fbbb Fix some gcc compiler warnings (probably cygwin-only) 2014-12-08 16:05:19 +00:00
oehhar 7466351c90 test for bug [c6ed4acfd8]: running async socket connect with other connect established will block tcl as it goes in an infinite loop in vwait 2014-12-07 12:17:24 +00:00
ashok 58bde2cb77 Potential fix for [c6ed4acfd8].
Simple typo in original fix for [336441ed59]. Was looping on
statePtr->next instead of statePtr2->next. Would result in
an infinite loop. Definitely a bug but whether it completely
fixes the above in all cases needs to be tested.
2014-12-06 11:19:32 +00:00
dgp 40420634aa Ever since (Tcl)PushVarName() stopped making a recursive call to Tcl_ParseCommand() (in the pre-8.4.0 timeframe), there's been no need for special protections for brace-quoted varname words. A simple word is a simple word is a simple word. 2014-12-05 21:28:00 +00:00
dgp b52476a5cd Ever since (Tcl)PushVarName() stopped making a recursive call to
Tcl_ParseCommand() (in the pre-8.4.0 timeframe), there's been no need
for special protections for brace-quoted varname words.  A simple word
is a simple word is a simple word.
2014-12-05 21:05:17 +00:00
dgp bc8ffb3922 [d2ffcca163] Limit parsing results that are documented to accept only ASCII chars to actually follow that constraint. This requires not trusting isalnum(.) and isalpha(.) to deliver portable identical results. 2014-12-05 12:28:01 +00:00
dgp bfb321eb38 [d2ffcca163] Limit parsing results that are documented to accept only
ASCII chars to actually follow that constraint.  This requires not trusting
isalnum(.) and isalpha(.) to deliver portable identical results.
2014-12-04 22:10:57 +00:00
dgp 5c1b9fefdf Limit isalpha(.) calls in the expr parser to only apply to known ASCII
arguments to make the results portable.
2014-12-04 21:29:18 +00:00
dgp 6d936db4a3 The isalpha(.) calls remaining in the expr parser still bring nonportability.
Commit a test that demonstrates that.
2014-12-04 20:45:11 +00:00
dgp dd4c175c81 Stop using isalnum(.). Its results are not portable. Replace with our
own private routine TclIsBareword() that does exactly what we want.
2014-12-04 18:26:31 +00:00
dgp 29b10229de merge 8.5 2014-12-04 13:02:43 +00:00
dgp bff00baca2 And then another merge mark to finish. 2014-12-03 23:55:39 +00:00
dgp 7dfd9c5a96 Now make the patch by hand that fossil could not merge. 2014-12-03 23:54:16 +00:00
dgp 05971adca4 Just a merge mark since fossil cannot do it right. 2014-12-03 23:51:36 +00:00
dgp 2f3edeea43 [0c043a175] backport fix from trunk. 2014-12-03 23:46:51 +00:00
Miguel Sofer 0c0be35710 missing unset in new test 2014-12-03 23:34:36 +00:00
Miguel Sofer 137e142be2 fix var($) problem, bug [0c043a175] (thx dgp) 2014-12-03 23:27:45 +00:00
Miguel Sofer 8694763c10 test and fix (thx dgp) 2014-12-03 23:17:16 +00:00
dkf 58cd08bb7d [0dca3bfa8f] Strengthen validity checks on fast-path string comparison. 2014-12-03 23:05:15 +00:00
Miguel Sofer 730a9a132c adding a test for the bug 2014-12-03 13:22:53 +00:00
andreask d7cf041bab Fix missing export of the "NewForeachInfoType" AuxData structure for tbcload/tclcompiler packages. 2014-12-01 20:17:04 +00:00
dgp 03f0d60f88 Same issue in expr parser also tested and fixed. 2014-11-26 17:00:55 +00:00
dgp 92402afe21 I like this patch better. Retain the byte orientation of the parser. 2014-11-26 16:22:40 +00:00
dgp d9465a5be2 One way to fix the parser of $-substitution accepting non-ASCII varnames. 2014-11-25 21:24:06 +00:00
dgp 52bcb866e5 merge trunk 2014-11-24 03:11:23 +00:00
dgp 7f5ddf43ee [e087812465] Trim back operatorStrings array to just the entries that are needed. Trims away the part of the array that was out of sync with the opcodes. 2014-11-24 03:08:50 +00:00
dgp 484de8b987 [e087812465] Trim back operatorStrings array to just the entries that are
needed.  Trims away the part of the array that was out of sync with the opcodes.
2014-11-24 03:00:03 +00:00
jan.nijtmans 2b3e403550 Fix [743338466549f09e3956d8a86e6f9a8030f227cb|7433384665]: socket error encoding bug. 2014-11-21 13:05:31 +00:00
dgp fa8d5668aa merge trunk 2014-11-17 13:00:42 +00:00
dgp 24d57ad4ff Add to Tcl_ExternalToUtf() a capability to impose a limit on the number
of chars produce in the encoding result.  When the flag
TCL_ENCODING_CHAR_LIMIT is set and dstCharsPtr is not NULL, then the
initial value of *dstCharsPtr is taken as the max number of chars to produce.
The limit is imposed in a way that does not require the assistance of the
encoding's driver procs, but the flag is passed on to them in case they
can do better when they know they should.  No callers updated yet.
No drivers updated yet.

One difficulty is that this necessarily imposes a pre-translation limit,
and the I/O system has a history of wanting to impose only a post-translation
limit.
2014-11-15 21:46:19 +00:00
dgp 3185389da2 With no padding needed for a terminating NUL, there no need for a distinction
between the dstNeeded and dstLimit values.
2014-11-15 21:13:52 +00:00
dgp 164250cf86 Tcl_ExternalToUtf appends a terminating NUL to its encoded results.
Perhaps this is a welcome convenience for some callers, but not for Tcl's
I/O system, which has no need for that.  Added a new flag value
TCL_ENCODING_NO_TERMINATE that callers can use to suppress this behavior.
This means buffers don't require so much padding, and a tiny bit of processing
is saved.  Update I/O callers to use the feature.
2014-11-15 21:08:57 +00:00
jan.nijtmans 9c2149012b Remove a number of eol-spaces. No change in functionality. 2014-11-14 09:44:34 +00:00
jan.nijtmans 6e056b1e14 Simplify NativeIsComPort() implementation: native paths never end in ':', and never use forward slashes (any more), so no need to check for that. 2014-11-13 16:08:47 +00:00
jan.nijtmans 99ee3e86d7 Improve documentation on the use of com ports (remove references to Windows 95, deprecate the use of postfix ':').
Allow lpt[5-9] just as com[5-9], and make sure that path normalization works as expected for ports > 4.
2014-11-13 12:52:29 +00:00
jan.nijtmans 3bbc2317b3 Improve documentation on the use of com ports (remove references to Windows 95, deprecate the use of postfix ':').
Allow lpt[5-9] just as com[5-9], and make sure that path normalization works as expected for ports > 4.
2014-11-13 12:29:04 +00:00
dgp 7d10d699c7 merge release 2014-11-12 04:35:37 +00:00
dgp 620cf6fa02 Likely fix for channel mem leaks. 2014-11-11 22:23:57 +00:00
dkf 98e4ac55d2 [214cc0eb22] Add tests to make sure that this bug stays fixed. 2014-11-08 07:06:52 +00:00
dgp eb64ed3cf0 Correct -singleproc 1 testing flaws. 2014-11-07 17:48:31 +00:00
dgp 5e0d1d6bc5 update changes; more test suite polishing. 2014-11-07 14:10:23 +00:00
dgp 7565b9ff1e Make sure all uses of the [testbytestring] command are constrained. 2014-11-07 13:59:27 +00:00
andreask 10dc783c93 Merged latest trunk work (especially changes to eof handling) into the RC. 2014-11-06 18:38:36 +00:00
dgp 0c027bb706 cleanup global namespace litter 2014-11-06 17:34:40 +00:00
dgp c658976cc3 [5adc350683] Stop Tcl forcing EOF condition on channels to be permanent. It may be fleeting, and all parts of Tcl channel ecosystem have to deal with that. New assertions and tests to keep us on track. 2014-11-06 16:34:03 +00:00
dgp 1db5ff8c2c [5adc350683] Stop Tcl forcing EOF condition on channels to be permanent.
It may be fleeting, and all parts of Tcl channel ecosystem have to deal
with that.  New assertions and tests to keep us on track.
2014-11-06 16:24:02 +00:00
dgp fbba7d0b1e merge iogt fixes. 2014-11-06 16:20:44 +00:00
dgp 559b8ab9de Also test transfroms that delay. 2014-11-06 16:12:26 +00:00
dgp 60ef43cb8c fix failing test 2014-11-06 15:49:30 +00:00
dgp 5c6717b7d5 New test iogt-7.0 demos bug in [testchannel transform]. 2014-11-06 15:06:52 +00:00
dgp 2f8dae1cec Another test checking that handling when transform returns nothing is right. 2014-11-06 14:52:36 +00:00
dgp dac552ac0b New tests iortrans-4.11* demonstrate what was wrong with the "leaky EOF flag"
approach in 8.6.1 and earlier.  If each level of the channel stack is to have
control over its EOF independently, we have to provide for that, even though
the Filesystem read APIs make it a big pain.  Also test robustness against
varing buffer sizes.
2014-11-06 13:38:01 +00:00
dgp 53ae611583 Reflected Transform channel fix. Be sure each EOF on the base channel gets
passed up to become an eof of the transform before continuing on to additional
ReadRaw() from the base channel.  This way we don't miss fleeting EOFs.
2014-11-05 20:34:03 +00:00
dgp 57de194b09 New test iortrans-4.10 to demo failure of channel transformation to handle
fleeting EOF in the base channel.  Falls into infinite block.  Regression
compared with Tcl 8.6.1.
2014-11-05 16:47:00 +00:00
dgp 5204910c12 merge trunk 2014-11-05 16:39:16 +00:00
dgp 71d27bd9c6 [214cc0eb22] Restore [lappend $var] return value to the 8.6.1- behavior.
If this is going to change, lets not do it by accident.
2014-11-05 06:36:07 +00:00
dgp 3fa4ffc77a Make sure reflected channels do not make a double call to Tcl_ReadRaw(),
with the unwarranted assumption that EOF is a permanent condition.
2014-11-03 21:37:37 +00:00
dgp d2b69b306e Same patch re-enabling read after EOF, but here applied to 8.6.
Likely additional changes needed in the other channel transforms new in 8.6.
2014-11-03 21:04:24 +00:00
dgp db9946ccc3 merge 8.5 2014-11-03 20:54:12 +00:00
dgp cb0895755d [5adc350683] Reworked the management of the EOF states to re-enable the
ability to read beyond EOF.  Plenty of assert()s to keep thing from going
off track again.
2014-11-03 20:39:25 +00:00
jan.nijtmans b14c2f49d2 Add test-case for previous commit, which shows that when trying to open a filename with invalid characters gives the right error-message. (same bug existed on UNIX too, which is now fixed) 2014-11-03 12:54:25 +00:00
jan.nijtmans 48ab03f3cd Add test-case for previous commit, which shows that when trying to open a filename with invalid characters gives the right error-message. (same bug existed on UNIX too, which is now fixed) 2014-11-03 12:44:55 +00:00
jan.nijtmans de82a1a99e Better errormessage when file path contains invalid characters. 2014-11-03 10:23:06 +00:00
jan.nijtmans 7ec17e20d3 Better errormessage when file path contains invalid characters. See: [03414f517b7a74]. 2014-11-03 10:14:48 +00:00
dgp d95273cf0e Disable assertion until tls bug it detects is fixed. 2014-11-01 14:52:55 +00:00
jan.nijtmans f87735c127 Extend WinIsReserved() to recognize COM[5-9]: as valid com ports as well. Prevent possible buffer-overflow if COM name ends with ':'. 2014-10-31 11:14:24 +00:00
jan.nijtmans 1e769e4b57 Extend WinIsReserved() to recognize COM[5-9]: as valid com ports as well. 2014-10-31 10:57:25 +00:00
jan.nijtmans a8dc863399 When translating a reserved devicename to native pathname, strip ':' postfix. Possible fix for [dcc03414f5], but anyway a good idea. 2014-10-31 10:20:03 +00:00
jan.nijtmans 476a68cbe5 When translating a reserved devicename to native pathname, strip ':' postfix. Possible fix for [dcc03414f5], but anyway a good idea. 2014-10-31 09:59:36 +00:00
dgp 54d2883694 Base test for [5adc350683]. 2014-10-29 14:54:11 +00:00
dgp 5a9b116846 merge 8.5 2014-10-29 13:49:46 +00:00
dgp df4391e23f Work in progress restoring ability to [read] after [eof] and get non-empty
strings back in those cases where the channel has them to offer.  Also
working through all the implications of this possibility on Tcl's more
exotic channel features, like stacking.
2014-10-28 20:10:32 +00:00
dgp 717a98747d merge trunk 2014-10-28 13:06:56 +00:00
jan.nijtmans 915359ddce Support for Windows 10 2014-10-26 07:53:23 +00:00
jan.nijtmans 999c88ea06 Support for Windows 10 2014-10-26 07:51:22 +00:00
dgp 790fed46bb merge mark 2014-10-24 20:10:39 +00:00
dgp da01ebeabe merge release 2014-10-24 20:07:52 +00:00
dgp 91d5ac9d0b by request 2014-10-22 14:46:33 +00:00
dgp adff5bc1c6 merge trunk 2014-10-18 22:43:06 +00:00
dgp eee56ee95a update changes 2014-10-18 20:11:36 +00:00
dgp 9cf7e2a336 merge 8.5 2014-10-18 20:06:02 +00:00
dgp 93082a74a2 [10dc6daa37] New fix for [gets] on non-blocking channel. This time properly accounts for the effects of ENCODING_LINESIZE. 2014-10-18 20:03:08 +00:00
dgp 9f2c3815f7 [10dc6daa37] New fix for [gets] on non-blocking channel. This time
properly accounts for the effects of ENCODING_LINESIZE.
2014-10-18 19:50:19 +00:00
dgp 592ab670f3 [10dc6daa37] [gets] on a non-blocking channel must take care so that
1) At least one call to the channel driver input proc gets made.
       Failure to do this locks up the channel - catastrophic FAIL. 
    2) After any driver call reports BLOCKED, don't call again.
       This is less serious, but FAILs to respect the non-blocking setting.
Code corrections and tests included, to restore 8.5.15 compat.
2014-10-17 15:20:34 +00:00
oehhar c0e8db49d5 fconfigure -peername and -sockname return empty string while async connect running. 2014-10-17 12:52:15 +00:00
oehhar d7604e5728 New tests: 14.16: -peername empty while async connect running, 14.17: -sockname 2014-10-17 12:28:55 +00:00
oehhar 8e5b3b87a5 Merge trunk 2014-10-17 10:00:39 +00:00
dgp d31d858702 Bump to Tcl 8.6.3, TclOO 1.0.3, and update changes file. 2014-10-14 18:12:36 +00:00
dgp 1234267c92 missed a bump 2014-10-13 17:34:12 +00:00
dgp 59491ce8ca update changes file 2014-10-13 17:15:55 +00:00
dgp ef89704696 Resolve test conflicts over global vars 2014-10-10 20:37:58 +00:00
dgp 1ce240e90f Bump to 8.5.17 2014-10-10 20:17:12 +00:00
dgp c132978e4b merge mark 2014-10-10 20:02:40 +00:00
dgp 59f2031ac5 backport those tests that can be 2014-10-10 20:02:00 +00:00
dgp f85490f4e1 [bf7135428c] Restore the Tcl_Write() return value logic. 2014-10-10 19:56:06 +00:00
dgp c2be2a28e0 [bf7135428c] Restore the Tcl_Write() return value logic. 2014-10-10 19:54:19 +00:00
dgp 4977df535f [ed29c4da21] Completed fix for [chan copy] handling [chan blocked]. 2014-10-10 19:44:54 +00:00
ferrieux 182bace1e3 Add Colin's test for coro floor above street level [Bug #3008307] 2014-10-10 19:36:17 +00:00
dgp 1f33c7ae12 Another test so both DoRead and MBRead are covered. 2014-10-10 19:02:37 +00:00
dgp 78c2c1cedf [ed29c4da21] Merge patch from 8.5, still not a complete fix. 2014-10-10 18:28:31 +00:00
dgp 186ecf8003 [ed29c4da21] Don't let BLOCKED state get converted into a channel error. 2014-10-10 18:24:32 +00:00
dgp 56c0b11912 New test io-53.15 for [ed29c4da21]. 2014-10-10 16:13:53 +00:00
dgp 1df1505d69 New test io-53.15 for [ed29c4da21]. 2014-10-10 15:38:15 +00:00
dgp 1a08ae6fb4 [2039178] Remove false claims about TCL_INTERP_DESTROYED flag bit in command traces. 2014-10-09 14:56:27 +00:00
dgp 891a0ade43 [2039178] Remove false claims about TCL_INTERP_DESTROYED flag bit in command traces. 2014-10-09 14:52:48 +00:00
jan.nijtmans 29d06499aa Fix [59a2e78e54d3361c33b8cd6eef55d384d8abecd7|59a2e78e54] : tclWinTime.c does not compile with MSVC14.
Eliminate use of __MINGW32__ macro everywhere, as it is deprecated.
2014-10-08 07:11:53 +00:00
jan.nijtmans ea97de415f Fix [59a2e78e54d3361c33b8cd6eef55d384d8abecd7|59a2e78e54] : tclWinTime.c does not compile with MSVC14.
Eliminate use of __MINGW32__ macro everywhare, as it is deprecated.
2014-10-08 07:02:34 +00:00
dgp b327c90dcc fix [bc1a96407a] 2014-10-03 20:20:12 +00:00
dgp cd1372b52d test cases 2014-10-03 15:47:38 +00:00
dgp 3b4cf982e3 Possible fix for testing. 2014-10-02 21:40:13 +00:00
dgp 7c4da917a7 [bc1a96407a] Partial solution should avoid crash, but may lead to wrong behavior. 2014-10-02 17:43:16 +00:00
dgp e36d384130 [bc5b790099] Improper calculation of new dstLimit value. New test io-12.7. 2014-10-02 14:46:54 +00:00
dgp 5e53c4c296 [bc5b790099] Improper calculation of new dstLimit value. New test io-12.7. 2014-10-02 14:43:10 +00:00
Miguel Sofer 78fcaa3580 Backing out commit [cddbfc3081], fix for bug [82521bfb6734f891dd]
The "optimisation" in that commit assumes that the last byte in the
generated bytecodes is an INST_TRY_CONVERT if it equals 64. This is an
invalid assumption, it could be 64 and not be an instruction.
2014-09-27 21:36:06 +00:00
ferrieux 11db57d058 Applied patch by Andreas Leitgeb so that [string cat]'s compiled bytecode optimally groups args by 255 for INSTR_STR_CONCAT1. 2014-09-27 20:28:47 +00:00
oehhar 822a2b50f7 Implemented tip-427: socket fconfigure option -connecting plus no -peername,-sockname when still connecting. 2014-09-26 12:05:30 +00:00
dgp fc21aee814 comment fix 2014-09-25 18:47:32 +00:00
dkf d06897f3ea Added a script-readable bytecode disassembler in tcl::unsupported. 2014-09-20 12:37:19 +00:00
dkf 1598658a83 Tidy things up a bit more. 2014-09-20 11:40:35 +00:00
jan.nijtmans 192fa71096 merge-mark 2014-09-17 10:47:21 +00:00
stwo 76db7c5c04 Better pic flag for OpenBSD. 2014-09-16 15:52:44 +00:00
stwo 85f3786d9c Better pic flag for OpenBSD. 2014-09-16 15:48:48 +00:00
dkf 5e0835667d whitespace tweak 2014-09-14 17:11:33 +00:00
dkf 26fe5fff38 merge trunk 2014-09-14 16:51:49 +00:00
dgp d75135cca1 [cee90e4e88] Correct error in stack depth checking. 2014-09-10 22:17:21 +00:00
dkf a5dd225e78 [2486824] Improve error message; not all that upvars is an upvar. 2014-09-10 08:24:59 +00:00
dkf 5f9519213f [2486824] Improve error message; not all that upvars is an upvar. 2014-09-10 08:20:46 +00:00
dkf 7bce68fe3b [84af1192f5]: [regsub] compiler no longer confused by quantification handling. 2014-09-09 19:49:08 +00:00
ferrieux 600ace1c4b Refine TclFinalizeThreadData so that the quick-exit optimization really only affects exit. 2014-09-08 22:50:11 +00:00
dgp 62004c9fb4 Exceptional handling of oo::class has to be consistent throughout. 2014-09-08 21:22:05 +00:00
stwo 976c48a7f1 Change one '#ifdef' to '#if defined()' for improved consistency within the file,
as in checkin [211aa43013].
2014-09-08 00:37:22 +00:00
dgp a3b501f125 Remove unused macros. 2014-09-05 19:04:43 +00:00
dgp 13d8cae724 Make corrections to long-false comments. 2014-09-05 18:30:57 +00:00
dkf 303cced03d [ccc2c2cc98]: lreplace edge case 2014-09-05 10:05:05 +00:00
dgp 3f8809d6ec Remove ChannelHandlerEvent struct, which has never been used in all of
recorded Tcl history.
Still need to purge comments of mentions of ChannelHandlerEventProc()
which is similarly pre-historic.
2014-09-04 22:05:21 +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
dkf 2e512ffbe8 merge trunk 2014-08-30 08:30:00 +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
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
Kevin B Kenny aa2667b729 merge trunk 2014-08-02 19:20:06 +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
Kevin B Kenny 0bab3624a9 merge trunk 2014-06-29 02:20:31 +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
dkf c0726f8f4f merge trunk 2014-02-08 07:54:21 +00:00
dkf 39ddd8c91b improve the testing of the disassembly commands 2014-02-08 07:54:04 +00:00
dkf d69c1d382b merge trunk 2014-02-08 07:41:17 +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 14b32b82e1 merge trunk 2014-02-04 09:09:06 +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
dkf 3f60452ac2 merge trunk 2014-02-03 22:29:31 +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 75b361386e merge trunk 2014-01-09 21:20:23 +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 f3dba34e63 merge trunk 2013-09-26 16:32:21 +00:00
dkf 36a7db47de merge trunk 2013-09-20 13:02:29 +00:00
dkf 97323cd8a0 merge trunk 2013-08-22 07:09:21 +00:00
dkf 8fa124afba merge trunk 2013-07-07 11:57:55 +00:00
dkf df623b6abe Properly encode more operand types to reduce the number of special cases in the disassembler. 2013-06-20 11:05:20 +00:00
dkf 3ef97fba38 merge trunk 2013-06-19 22:46:10 +00:00
dkf a261f7d413 Remove extra scribblings not normally needed. Thanks to jdc for suggestion. 2013-06-17 14:04:28 +00:00
dkf 50cc521ee3 Improved rendering of some opcode arguments and auxdata. 2013-06-13 21:21:22 +00:00
dkf 48205fa50d merge trunk 2013-06-13 08:31:24 +00:00
dkf 9fb06ec1c9 Extract more of the info from the bytecode. 2013-06-12 08:55:15 +00:00
dkf f9e188bad3 merge trunk 2013-06-11 21:40:51 +00:00
dkf 6b65756937 Code-readable disassembler: tcl::unsupported::getbytecode 2013-06-11 21:33:33 +00:00
dkf a74538b064 merge trunk 2013-06-11 08:34:09 +00:00
dkf 55787f4f08 Move the disassembler to its own file. 2013-06-11 08:19:56 +00:00
dkf 0d59c187fe merge trunk 2013-06-09 17:38:20 +00:00
dkf 4d2add8f0f merge trunk 2013-06-08 13:42:46 +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
455 changed files with 18575 additions and 12415 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.3 source distribution.
http://sourceforge.net/projects/tcl/files/Tcl/
You can get any source release of Tcl from the URL above.
+191 -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,193 @@ 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
2014-08-28 (bug)[b9e1a3] Correct Method Search Order (nadkarni,fellows)
=> TclOO 1.0.3
2014-09-05 (bug)[ccc2c2] Regression [lreplace {} 1 1] (bron,fellows)
2014-09-08 (bug)<oo-1.18.2> Crash regression in [oo::class destroy] (porter)
2014-09-09 (bug)[84af11] Regress [regsub -all {\(.*} a(b) {}] (fellows)
2014-09-10 (bug)[cee90e] [try {} on ok {} - on return {} {}] panic (porter)
2014-09-20 (feature) [tcl::unsupported::getbytecode] disassember (fellows)
2014-09-27 (enhancement) [string cat] bytecode optimization (leitgeb,ferrieux)
2014-09-27 (bug)[82521b] segfault in mangled bytecode (ogilvie,sofer)
2014-10-02 (bug)[bc5b79] Hang in some [read]s of limited size (rogers,porter)
2014-10-03 (bug)[bc1a96] segfault in [array set] of traced array (tab,porter)
2014-10-08 (bug)[59a2e7] MSVC14 compile support (dower,nijtmans)
2014-10-10 (bug)[ed29c4] [fcopy] treats [blocked] as error (rowen,porter)
2014-10-10 (bug)[bf7135] regression in Tcl_Write() interface (porter)
2014-10-18 (bug)[10dc6d] fix [gets] on non-blocking channels (fassel,porter)
2014-10-26 Support for Windows 10 (nijtmans)
2014-10-31 (bug)[dcc034] restore [open comX: r+] (lll,nijtmans)
2014-11-05 (bug)[214cc0] Restore [lappend v] return value (sayers,porter)
2014-11-06 (bug)[5adc35] Stop forcing EOF to be permanent (porter)
--- Released 8.6.3, November 12, 2014 --- http://core.tcl.tk/tcl/ for details
2014-12-17 (TIP 427) [fconfigure $h -connecting, -peername, -sockname] (oehlmann,rmax)
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
+10 -23
View File
@@ -86,11 +86,14 @@ operation is being performed on the command. The bit
\fBTCL_TRACE_DESTROYED\fR will be set in \fIflags\fR if the trace is about
to be destroyed; this information may be useful to \fIproc\fR so that
it can clean up its own internal data structures (see the section
\fBTCL_TRACE_DESTROYED\fR below for more details). Lastly, the bit
\fBTCL_INTERP_DESTROYED\fR will be set if the entire interpreter is being
destroyed. When this bit is set, \fIproc\fR must be especially
careful in the things it does (see the section \fBTCL_INTERP_DESTROYED\fR
below).
\fBTCL_TRACE_DESTROYED\fR below for more details). Because the
deletion of commands can take place as part of the deletion of the interp
that contains them, \fIproc\fR must be careful about checking what
the passed in \fIinterp\fR value can be called upon to do.
The routine \fBTcl_InterpDeleted\fR is an important tool for this.
When \fBTcl_InterpDeleted\fR returns 1, \fIproc\fR will not be able
to invoke any scripts in \fIinterp\fR. The function of \fIproc\fR
in that circumstance is limited to the cleanup of its own data structures.
.PP
\fBTcl_UntraceCommand\fR may be used to remove a trace. If the
command specified by \fIinterp\fR, \fIcmdName\fR, and \fIflags\fR has
@@ -123,7 +126,8 @@ traces for a given command that have the same \fIproc\fR.
.PP
During rename traces, the command being renamed is visible with both
names simultaneously, and the command still exists during delete
traces (if \fBTCL_INTERP_DESTROYED\fR is not set). However, there is no
traces, unless the interp that contains it is being deleted.
However, there is no
mechanism for signaling that an error occurred in a trace procedure,
so great care should be taken that errors do not get silently lost.
.SH "MULTIPLE TRACES"
@@ -142,22 +146,5 @@ rename the command, the last renaming takes precedence.
In a delete callback to \fIproc\fR, the \fBTCL_TRACE_DESTROYED\fR bit
is set in \fIflags\fR.
.\" Perhaps need some more comments here? - DKF
.SH "TCL_INTERP_DESTROYED"
.PP
When an interpreter is destroyed, unset traces are called for
all of its commands.
The \fBTCL_INTERP_DESTROYED\fR bit will be set in the \fIflags\fR
argument passed to the trace procedures.
Trace procedures must be extremely careful in what they do if
the \fBTCL_INTERP_DESTROYED\fR bit is set.
It is not safe for the procedures to invoke any Tcl procedures
on the interpreter, since its state is partially deleted.
All that trace procedures should do under these circumstances is
to clean up and free their own internal data structures.
.SH BUGS
.PP
Tcl does not do any error checking to prevent trace procedures
from misusing the interpreter during traces with \fBTCL_INTERP_DESTROYED\fR
set.
.SH KEYWORDS
clientData, trace, command
+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
+13 -48
View File
@@ -361,18 +361,17 @@ may cause this error.
A BREAK condition has been detected by your UART (see above).
.SH "PORTABILITY ISSUES"
.TP
\fBWindows \fR(all versions)
\fBWindows \fR
.
Valid values for \fIfileName\fR to open a serial port are of the form
\fBcom\fIX\fB:\fR, where \fIX\fR is a number, generally from 1 to 4.
This notation only works for serial ports from 1 to 9, if the system
happens to have more than four. An attempt to open a serial port that
\fBcom\fIX\fB\fR, where \fIX\fR is a number, generally from 1 to 9.
A legacy form accepted as well is \fBcom\fIX\fB:\fR. This notation only
works for serial ports from 1 to 9. An attempt to open a serial port that
does not exist or has a number greater than 9 will fail. An alternate
form of opening serial ports is to use the filename \fB\e\e.\ecomX\fR,
where X is any number that corresponds to a serial port; please note
that this method is considerably slower on Windows 95 and Windows 98.
.TP
\fBWindows NT\fR
form of opening serial ports is to use the filename \fB//./comX\fR,
where X is any number that corresponds to a serial port.
.RS
.PP
.
When running Tcl interactively, there may be some strange interactions
between the real console, if one is present, and a command pipeline that uses
@@ -380,45 +379,11 @@ standard input or output. If a command pipeline is opened for reading, some
of the lines entered at the console will be sent to the command pipeline and
some will be sent to the Tcl evaluator. If a command pipeline is opened for
writing, keystrokes entered into the console are not visible until the
pipe is closed. This behavior occurs whether the command pipeline is
executing 16-bit or 32-bit applications. These problems only occur because
both Tcl and the child application are competing for the console at
the same time. If the command pipeline is started from a script, so that Tcl
is not accessing the console, or if the command pipeline does not use
standard input or output, but is redirected from or to a file, then the
above problems do not occur.
.TP
\fBWindows 95\fR
.
A command pipeline that executes a 16-bit DOS application cannot be opened
for both reading and writing, since 16-bit DOS applications that receive
standard input from a pipe and send standard output to a pipe run
synchronously. Command pipelines that do not execute 16-bit DOS
applications run asynchronously and can be opened for both reading and
writing.
.RS
.PP
When running Tcl interactively, there may be some strange interactions
between the real console, if one is present, and a command pipeline that uses
standard input or output. If a command pipeline is opened for reading from
a 32-bit application, some of the keystrokes entered at the console will be
sent to the command pipeline and some will be sent to the Tcl evaluator. If
a command pipeline is opened for writing to a 32-bit application, no output
is visible on the console until the pipe is closed. These problems only
occur because both Tcl and the child application are competing for the
console at the same time. If the command pipeline is started from a script,
so that Tcl is not accessing the console, or if the command pipeline does
not use standard input or output, but is redirected from or to a file, then
the above problems do not occur.
.PP
Whether or not Tcl is running interactively, if a command pipeline is opened
for reading from a 16-bit DOS application, the call to \fBopen\fR will not
return until end-of-file has been received from the command pipeline's
standard output. If a command pipeline is opened for writing to a 16-bit DOS
application, no data will be sent to the command pipeline's standard output
until the pipe is actually closed. This problem occurs because 16-bit DOS
applications are run synchronously, as described above.
.RE
pipe is closed. These problems only occur because both Tcl and the child
application are competing for the console at the same time. If the command
pipeline is started from a script, so that Tcl is not accessing the console,
or if the command pipeline does not use standard input or output, but is
redirected from or to a file, then the above problems do not occur.
.TP
\fBUnix\fR\0\0\0\0\0\0\0
.
+9
View File
@@ -97,6 +97,10 @@ writable channel event on the socket to get notified when the
asynchronous connection has succeeded or failed. See the \fBvwait\fR
and the \fBchan\fR commands for more details on the event loop and
channel events.
.PP
The \fBchan configure\fR option \fB-connecting\fR may be used to check if the connect is still running. To verify a successful connect, the option \fB-error\fR may be checked when \fB-connecting\fR returned 0.
.PP
Operation without the event queue requires at the moment calls to \fBchan configure\fR to advance the internal state machine.
.RE
.SH "SERVER SOCKETS"
.PP
@@ -186,6 +190,11 @@ sockets, this option returns a list of three elements; these are the
address, the host name and the port to which the peer socket is connected
or bound. If the host name cannot be computed, the second element of the
list is identical to the address, its first element.
.RE
.TP
\fB\-connecting\fR
.
This option is not supported by server sockets. For client sockets, this option returns 1 if an asyncroneous connect is still in progress, 0 otherwise.
.PP
.SH "EXAMPLES"
.PP
+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;
}
+42 -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 3
#define TCL_VERSION "8.6"
#define TCL_PATCH_LEVEL "8.6.1"
#define TCL_PATCH_LEVEL "8.6.3"
/*
*----------------------------------------------------------------------------
@@ -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
@@ -2147,11 +2144,28 @@ typedef struct Tcl_EncodingType {
* substituting one or more "close" characters in
* the destination buffer and then continue to
* convert the source.
* TCL_ENCODING_NO_TERMINATE - If set, Tcl_ExternalToUtf will not append a
* terminating NUL byte. Knowing that it will
* not need space to do so, it will fill all
* dstLen bytes with encoded UTF-8 content, as
* other circumstances permit. If clear, the
* default behavior is to reserve a byte in
* the dst space for NUL termination, and to
* append the NUL byte.
* TCL_ENCODING_CHAR_LIMIT - If set and dstCharsPtr is not NULL, then
* Tcl_ExternalToUtf takes the initial value
* of *dstCharsPtr is taken as a limit of the
* maximum number of chars to produce in the
* encoded UTF-8 content. Otherwise, the
* number of chars produced is controlled only
* by other limiting factors.
*/
#define TCL_ENCODING_START 0x01
#define TCL_ENCODING_END 0x02
#define TCL_ENCODING_STOPONERROR 0x04
#define TCL_ENCODING_NO_TERMINATE 0x08
#define TCL_ENCODING_CHAR_LIMIT 0x10
/*
* The following definitions are the error codes returned by the conversion
@@ -2436,9 +2450,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"
/*
+1 -1
View File
@@ -31,7 +31,7 @@
* until Tcl uses config.h properly.
*/
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__)
#if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__)
typedef unsigned long caddr_t;
#endif
+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 */
};
/*
+41 -25
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.
@@ -840,7 +840,9 @@ Tcl_CreateInterp(void)
*/
Tcl_CreateObjCommand(interp, "::tcl::unsupported::disassemble",
Tcl_DisassembleObjCmd, NULL, NULL);
Tcl_DisassembleObjCmd, INT2PTR(0), NULL);
Tcl_CreateObjCommand(interp, "::tcl::unsupported::getbytecode",
Tcl_DisassembleObjCmd, INT2PTR(1), NULL);
Tcl_CreateObjCommand(interp, "::tcl::unsupported::representation",
Tcl_RepresentationCmd, NULL, NULL);
@@ -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;
+230 -118
View File
@@ -26,14 +26,23 @@ static void FreeDictUpdateInfo(ClientData clientData);
static void PrintDictUpdateInfo(ClientData clientData,
Tcl_Obj *appendObj, ByteCode *codePtr,
unsigned int pcOffset);
static void DisassembleDictUpdateInfo(ClientData clientData,
Tcl_Obj *dictObj, ByteCode *codePtr,
unsigned int pcOffset);
static ClientData DupForeachInfo(ClientData clientData);
static void FreeForeachInfo(ClientData clientData);
static void PrintForeachInfo(ClientData clientData,
Tcl_Obj *appendObj, ByteCode *codePtr,
unsigned int pcOffset);
static void DisassembleForeachInfo(ClientData clientData,
Tcl_Obj *dictObj, ByteCode *codePtr,
unsigned int pcOffset);
static void PrintNewForeachInfo(ClientData clientData,
Tcl_Obj *appendObj, ByteCode *codePtr,
unsigned int pcOffset);
static void DisassembleNewForeachInfo(ClientData clientData,
Tcl_Obj *dictObj, ByteCode *codePtr,
unsigned int pcOffset);
static int CompileEachloopCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
CompileEnv *envPtr, int collect);
@@ -49,29 +58,25 @@ const AuxDataType tclForeachInfoType = {
"ForeachInfo", /* name */
DupForeachInfo, /* dupProc */
FreeForeachInfo, /* freeProc */
PrintForeachInfo /* printProc */
PrintForeachInfo, /* printProc */
DisassembleForeachInfo /* disassembleProc */
};
const AuxDataType tclNewForeachInfoType = {
"NewForeachInfo", /* name */
DupForeachInfo, /* dupProc */
FreeForeachInfo, /* freeProc */
PrintNewForeachInfo /* printProc */
PrintNewForeachInfo, /* printProc */
DisassembleNewForeachInfo /* disassembleProc */
};
const AuxDataType tclDictUpdateInfoType = {
"DictUpdateInfo", /* name */
DupDictUpdateInfo, /* dupProc */
FreeDictUpdateInfo, /* freeProc */
PrintDictUpdateInfo /* printProc */
PrintDictUpdateInfo, /* printProc */
DisassembleDictUpdateInfo /* disassembleProc */
};
/*
* 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"
/*
*----------------------------------------------------------------------
@@ -172,9 +177,9 @@ TclCompileAppendCmd(
*/
varTokenPtr = TokenAfter(parsePtr->tokenPtr);
PushVarNameWord(interp, varTokenPtr, envPtr, TCL_NO_ELEMENT,
&localIndex, &isScalar, 1);
if (!isScalar || localIndex < 0) {
localIndex = LocalScalarFromToken(varTokenPtr, envPtr);
if (localIndex < 0) {
return TCL_ERROR;
}
@@ -285,7 +290,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;
@@ -296,7 +301,8 @@ TclCompileArraySetCmd(
* a proc, we cannot do a better compile than generic.
*/
if (envPtr->procPtr == NULL && !(isDataEven && len == 0)) {
if ((varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) ||
(envPtr->procPtr == NULL && !(isDataEven && len == 0))) {
code = TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
goto done;
}
@@ -337,8 +343,9 @@ TclCompileArraySetCmd(
* a non-local variable: upvar from a local one! This consumes the
* variable name that was left at stacktop.
*/
localIndex = AnonymousLocal(envPtr);
localIndex = TclFindCompiledLocal(varTokenPtr->start,
varTokenPtr->size, 1, envPtr);
PushStringLiteral(envPtr, "0");
TclEmitInstInt4(INST_REVERSE, 2, envPtr);
TclEmitInstInt4(INST_UPVAR, localIndex, envPtr);
@@ -380,7 +387,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);
@@ -2091,11 +2098,13 @@ TclCompileDictWithCmd(
* DupDictUpdateInfo: a copy of the auxiliary data
* FreeDictUpdateInfo: none
* PrintDictUpdateInfo: none
* DisassembleDictUpdateInfo: none
*
* Side effects:
* DupDictUpdateInfo: allocates memory
* FreeDictUpdateInfo: releases memory
* PrintDictUpdateInfo: none
* DisassembleDictUpdateInfo: none
*
*----------------------------------------------------------------------
*/
@@ -2138,6 +2147,25 @@ PrintDictUpdateInfo(
Tcl_AppendPrintfToObj(appendObj, "%%v%u", duiPtr->varIndices[i]);
}
}
static void
DisassembleDictUpdateInfo(
ClientData clientData,
Tcl_Obj *dictObj,
ByteCode *codePtr,
unsigned int pcOffset)
{
DictUpdateInfo *duiPtr = clientData;
int i;
Tcl_Obj *variables = Tcl_NewObj();
for (i=0 ; i<duiPtr->length ; i++) {
Tcl_ListObjAppendElement(NULL, variables,
Tcl_NewIntObj(duiPtr->varIndices[i]));
}
Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("variables", -1),
variables);
}
/*
*----------------------------------------------------------------------
@@ -2375,7 +2403,6 @@ TclCompileForCmd(
SetLineInformation(2);
TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
TclClearNumConversion(envPtr);
jumpDist = CurrentOffset(envPtr) - bodyCodeOffset;
if (jumpDist > 127) {
@@ -2500,24 +2527,16 @@ CompileEachloopCmd(
* (TCL_EACH_*) */
{
Proc *procPtr = envPtr->procPtr;
ForeachInfo *infoPtr; /* Points to the structure describing this
ForeachInfo *infoPtr=NULL; /* Points to the structure describing this
* foreach command. Stored in a AuxData
* record in the ByteCode. */
Tcl_Token *tokenPtr, *bodyTokenPtr;
int jumpBackOffset, infoIndex, range;
int numWords, numLists, numVars, loopIndex, i, j, code;
int numWords, numLists, i, j, code = TCL_OK;
Tcl_Obj *varListObj = NULL;
DefineLineInformation; /* TIP #280 */
/*
* We parse the variable list argument words and create two arrays:
* varcList[i] is number of variables in i-th var list.
* varvList[i] points to array of var names in i-th var list.
*/
int *varcList;
const char ***varvList;
/*
* If the foreach command isn't in a procedure, don't compile it inline:
* the payoff is too small.
@@ -2546,105 +2565,73 @@ CompileEachloopCmd(
}
/*
* Allocate storage for the varcList and varvList arrays if necessary.
* Create and initialize the ForeachInfo and ForeachVarList data
* structures describing this command. Then create a AuxData record
* pointing to the ForeachInfo structure.
*/
numLists = (numWords - 2)/2;
varcList = TclStackAlloc(interp, numLists * sizeof(int));
memset(varcList, 0, numLists * sizeof(int));
varvList = (const char ***) TclStackAlloc(interp,
numLists * sizeof(const char **));
memset((char*) varvList, 0, numLists * sizeof(const char **));
infoPtr = ckalloc(sizeof(ForeachInfo)
+ (numLists - 1) * sizeof(ForeachVarList *));
infoPtr->numLists = 0; /* Count this up as we go */
/*
* Break up each var list and set the varcList and varvList arrays. Don't
* Parse each var list into sequence of var names. Don't
* compile the foreach inline if any var name needs substitutions or isn't
* a scalar, or if any var list needs substitutions.
*/
loopIndex = 0;
varListObj = Tcl_NewObj();
for (i = 0, tokenPtr = parsePtr->tokenPtr;
i < numWords-1;
i++, tokenPtr = TokenAfter(tokenPtr)) {
Tcl_DString varList;
ForeachVarList *varListPtr;
int numVars;
if (i%2 != 1) {
continue;
}
if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
code = TCL_ERROR;
goto done;
}
/*
* Lots of copying going on here. Need a ListObj wizard to show a
* better way.
*/
Tcl_DStringInit(&varList);
TclDStringAppendToken(&varList, &tokenPtr[1]);
code = Tcl_SplitList(NULL, Tcl_DStringValue(&varList),
&varcList[loopIndex], &varvList[loopIndex]);
Tcl_DStringFree(&varList);
if (code != TCL_OK) {
code = TCL_ERROR;
goto done;
}
numVars = varcList[loopIndex];
/*
* If the variable list is empty, we can enter an infinite loop when
* the interpreted version would not. Take care to ensure this does
* not happen. [Bug 1671138]
* the interpreted version would not. Take care to ensure this does
* not happen. [Bug 1671138]
*/
if (numVars == 0) {
if (!TclWordKnownAtCompileTime(tokenPtr, varListObj) ||
TCL_OK != Tcl_ListObjLength(NULL, varListObj, &numVars) ||
numVars == 0) {
code = TCL_ERROR;
goto done;
}
for (j = 0; j < numVars; j++) {
const char *varName = varvList[loopIndex][j];
varListPtr = ckalloc(sizeof(ForeachVarList)
+ (numVars - 1) * sizeof(int));
varListPtr->numVars = numVars;
infoPtr->varLists[i/2] = varListPtr;
infoPtr->numLists++;
if (!TclIsLocalScalar(varName, (int) strlen(varName))) {
for (j = 0; j < numVars; j++) {
Tcl_Obj *varNameObj;
const char *bytes;
int numBytes, varIndex;
Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj);
bytes = Tcl_GetStringFromObj(varNameObj, &numBytes);
varIndex = LocalScalar(bytes, numBytes, envPtr);
if (varIndex < 0) {
code = TCL_ERROR;
goto done;
}
varListPtr->varIndexes[j] = varIndex;
}
loopIndex++;
Tcl_SetObjLength(varListObj, 0);
}
/*
* We will compile the foreach command.
*/
code = TCL_OK;
/*
* Create and initialize the ForeachInfo and ForeachVarList data
* structures describing this command. Then create a AuxData record
* pointing to the ForeachInfo structure.
*/
infoPtr = ckalloc(sizeof(ForeachInfo)
+ (numLists - 1) * sizeof(ForeachVarList *));
infoPtr->numLists = numLists;
for (loopIndex = 0; loopIndex < numLists; loopIndex++) {
ForeachVarList *varListPtr;
numVars = varcList[loopIndex];
varListPtr = ckalloc(sizeof(ForeachVarList)
+ (numVars - 1) * sizeof(int));
varListPtr->numVars = numVars;
for (j = 0; j < numVars; j++) {
const char *varName = varvList[loopIndex][j];
int nameChars = strlen(varName);
varListPtr->varIndexes[j] = TclFindCompiledLocal(varName,
nameChars, /*create*/ 1, envPtr);
}
infoPtr->varLists[loopIndex] = varListPtr;
}
infoIndex = TclCreateAuxData(infoPtr, &tclNewForeachInfoType, envPtr);
/*
@@ -2716,13 +2703,14 @@ CompileEachloopCmd(
}
done:
for (loopIndex = 0; loopIndex < numLists; loopIndex++) {
if (varvList[loopIndex] != NULL) {
ckfree(varvList[loopIndex]);
if (code == TCL_ERROR) {
if (infoPtr) {
FreeForeachInfo(infoPtr);
}
}
TclStackFree(interp, (void *)varvList);
TclStackFree(interp, varcList);
if (varListObj) {
Tcl_DecrRefCount(varListObj);
}
return code;
}
@@ -2816,10 +2804,10 @@ FreeForeachInfo(
/*
*----------------------------------------------------------------------
*
* PrintForeachInfo --
* PrintForeachInfo, DisassembleForeachInfo --
*
* Function to write a human-readable representation of a ForeachInfo
* structure to stdout for debugging.
* Functions to write a human-readable or script-readablerepresentation
* of a ForeachInfo structure to a Tcl_Obj for debugging.
*
* Results:
* None.
@@ -2899,6 +2887,89 @@ PrintNewForeachInfo(
Tcl_AppendToObj(appendObj, "]", -1);
}
}
static void
DisassembleForeachInfo(
ClientData clientData,
Tcl_Obj *dictObj,
ByteCode *codePtr,
unsigned int pcOffset)
{
register ForeachInfo *infoPtr = clientData;
register ForeachVarList *varsPtr;
int i, j;
Tcl_Obj *objPtr, *innerPtr;
/*
* Data stores.
*/
objPtr = Tcl_NewObj();
for (i=0 ; i<infoPtr->numLists ; i++) {
Tcl_ListObjAppendElement(NULL, objPtr,
Tcl_NewIntObj(infoPtr->firstValueTemp + i));
}
Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("data", -1), objPtr);
/*
* Loop counter.
*/
Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("loop", -1),
Tcl_NewIntObj(infoPtr->loopCtTemp));
/*
* Assignment targets.
*/
objPtr = Tcl_NewObj();
for (i=0 ; i<infoPtr->numLists ; i++) {
innerPtr = Tcl_NewObj();
varsPtr = infoPtr->varLists[i];
for (j=0 ; j<varsPtr->numVars ; j++) {
Tcl_ListObjAppendElement(NULL, innerPtr,
Tcl_NewIntObj(varsPtr->varIndexes[j]));
}
Tcl_ListObjAppendElement(NULL, objPtr, innerPtr);
}
Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("assign", -1), objPtr);
}
static void
DisassembleNewForeachInfo(
ClientData clientData,
Tcl_Obj *dictObj,
ByteCode *codePtr,
unsigned int pcOffset)
{
register ForeachInfo *infoPtr = clientData;
register ForeachVarList *varsPtr;
int i, j;
Tcl_Obj *objPtr, *innerPtr;
/*
* Jump offset.
*/
Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("jumpOffset", -1),
Tcl_NewIntObj(infoPtr->loopCtTemp));
/*
* Assignment targets.
*/
objPtr = Tcl_NewObj();
for (i=0 ; i<infoPtr->numLists ; i++) {
innerPtr = Tcl_NewObj();
varsPtr = infoPtr->varLists[i];
for (j=0 ; j<varsPtr->numVars ; j++) {
Tcl_ListObjAppendElement(NULL, innerPtr,
Tcl_NewIntObj(varsPtr->varIndexes[j]));
}
Tcl_ListObjAppendElement(NULL, objPtr, innerPtr);
}
Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("assign", -1), objPtr);
}
/*
*----------------------------------------------------------------------
@@ -3121,6 +3192,54 @@ TclCompileFormatCmd(
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclLocalScalarFromToken --
*
* Get the index into the table of compiled locals that corresponds
* to a local scalar variable name.
*
* Results:
* Returns the non-negative integer index value into the table of
* compiled locals corresponding to a local scalar variable name.
* If the arguments passed in do not identify a local scalar variable
* then return -1.
*
* Side effects:
* May add an entery into the table of compiled locals.
*
*----------------------------------------------------------------------
*/
int
TclLocalScalarFromToken(
Tcl_Token *tokenPtr,
CompileEnv *envPtr)
{
int isScalar, index;
TclPushVarName(NULL, tokenPtr, envPtr, TCL_NO_ELEMENT, &index, &isScalar);
if (!isScalar) {
index = -1;
}
return index;
}
int
TclLocalScalar(
const char *bytes,
int numBytes,
CompileEnv *envPtr)
{
Tcl_Token token[2] = {{TCL_TOKEN_SIMPLE_WORD, NULL, 0, 1},
{TCL_TOKEN_TEXT, NULL, 0, 0}};
token[1].start = bytes;
token[1].size = numBytes;
return TclLocalScalarFromToken(token, envPtr);
}
/*
*----------------------------------------------------------------------
*
@@ -3179,16 +3298,7 @@ TclPushVarName(
nameChars = elNameChars = 0;
localIndex = -1;
/*
* Check not only that the type is TCL_TOKEN_SIMPLE_WORD, but whether
* curly braces surround the variable name. This really matters for array
* elements to handle things like
* set {x($foo)} 5
* which raises an undefined var error if we are not careful here.
*/
if ((varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) &&
(varTokenPtr->start[0] != '{')) {
if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
/*
* A simple variable name. Divide it up into "name" and "elName"
* strings. If it is not a local variable, look it up at runtime.
@@ -3212,7 +3322,7 @@ TclPushVarName(
}
}
if ((elName != NULL) && elNameChars) {
if (!(flags & TCL_NO_ELEMENT) && (elName != NULL) && elNameChars) {
/*
* An array element, the element name is a simple string:
* assemble the corresponding token.
@@ -3227,7 +3337,7 @@ TclPushVarName(
elemTokenCount = 1;
}
}
} else if (((n = varTokenPtr->numComponents) > 1)
} else if (interp && ((n = varTokenPtr->numComponents) > 1)
&& (varTokenPtr[1].type == TCL_TOKEN_TEXT)
&& (varTokenPtr[n].type == TCL_TOKEN_TEXT)
&& (varTokenPtr[n].start[varTokenPtr[n].size - 1] == ')')) {
@@ -3263,9 +3373,10 @@ TclPushVarName(
nameChars = p - varTokenPtr[1].start;
elName = p + 1;
remainingChars = (varTokenPtr[2].start - p) - 1;
elNameChars = (varTokenPtr[n].start-p) + varTokenPtr[n].size - 2;
elNameChars = (varTokenPtr[n].start-p) + varTokenPtr[n].size - 1;
if (remainingChars) {
if (!(flags & TCL_NO_ELEMENT)) {
if (remainingChars) {
/*
* Make a first token with the extra characters in the first
* token.
@@ -3285,13 +3396,14 @@ TclPushVarName(
memcpy(elemTokenPtr+1, varTokenPtr+2,
(n-1) * sizeof(Tcl_Token));
} else {
} else {
/*
* Use the already available tokens.
*/
elemTokenPtr = &varTokenPtr[2];
elemTokenCount = n - 1;
}
}
}
}
@@ -3326,7 +3438,7 @@ TclPushVarName(
localIndex = -1;
}
}
if (localIndex < 0) {
if (interp && localIndex < 0) {
PushLiteral(envPtr, name, nameChars);
}
@@ -3343,7 +3455,7 @@ TclPushVarName(
PushStringLiteral(envPtr, "");
}
}
} else {
} else if (interp) {
/*
* The var name isn't simple: compile and push it.
*/
+123 -60
View File
@@ -281,7 +281,6 @@ TclCompileIfCmd(
SetLineInformation(wordIdx);
Tcl_ResetResult(interp);
TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
TclClearNumConversion(envPtr);
if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) {
TclExpandJumpFixupArray(&jumpFalseFixupArray);
}
@@ -531,7 +530,6 @@ TclCompileIncrCmd(
} else {
SetLineInformation(2);
CompileTokens(envPtr, incrTokenPtr, interp);
TclClearNumConversion(envPtr);
}
} else { /* No incr amount given so use 1. */
haveImmValue = 1;
@@ -868,28 +866,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) {
if (numWords < 3) {
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 +929,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;
}
@@ -1506,7 +1478,7 @@ TclCompileLreplaceCmd(
Tcl_Token *tokenPtr, *listTokenPtr;
DefineLineInformation; /* TIP #280 */
Tcl_Obj *tmpObj;
int idx1, idx2, i, offset;
int idx1, idx2, i, offset, offset2;
if (parsePtr->numWords < 4) {
return TCL_ERROR;
@@ -1612,12 +1584,18 @@ TclCompileLreplaceCmd(
TclEmitOpcode( INST_GT, envPtr);
offset = CurrentOffset(envPtr);
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
TclEmitOpcode( INST_DUP, envPtr);
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
offset2 = CurrentOffset(envPtr);
TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr);
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf(
"list doesn't contain element %d", idx1), NULL), envPtr);
CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0,
Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}"));
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset,
envPtr->codeStart + offset + 1);
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2,
envPtr->codeStart + offset2 + 1);
TclAdjustStackDepth(-1, envPtr);
}
TclEmitOpcode( INST_DUP, envPtr);
@@ -1662,12 +1640,18 @@ TclCompileLreplaceCmd(
TclEmitOpcode( INST_GT, envPtr);
offset = CurrentOffset(envPtr);
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
TclEmitOpcode( INST_DUP, envPtr);
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
offset2 = CurrentOffset(envPtr);
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf(
"list doesn't contain element %d", idx1), NULL), envPtr);
CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0,
Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}"));
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset,
envPtr->codeStart + offset + 1);
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2,
envPtr->codeStart + offset2 + 1);
TclAdjustStackDepth(-1, envPtr);
}
TclEmitOpcode( INST_DUP, envPtr);
@@ -1955,6 +1939,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. */
@@ -2038,7 +2044,7 @@ TclCompileNamespaceUpvarCmd(
CompileEnv *envPtr) /* Holds resulting instructions. */
{
Tcl_Token *tokenPtr, *otherTokenPtr, *localTokenPtr;
int isScalar, localIndex, numWords, i;
int localIndex, numWords, i;
DefineLineInformation; /* TIP #280 */
if (envPtr->procPtr == NULL) {
@@ -2073,10 +2079,8 @@ TclCompileNamespaceUpvarCmd(
localTokenPtr = TokenAfter(otherTokenPtr);
CompileWord(envPtr, otherTokenPtr, interp, i);
PushVarNameWord(interp, localTokenPtr, envPtr, 0,
&localIndex, &isScalar, i+1);
if ((localIndex < 0) || !isScalar) {
localIndex = LocalScalarFromToken(localTokenPtr, envPtr);
if (localIndex < 0) {
return TCL_ERROR;
}
TclEmitInstInt4( INST_NSUPVAR, localIndex, envPtr);
@@ -2262,7 +2266,7 @@ TclCompileRegexpCmd(
* converted pattern as a literal.
*/
if (TclReToGlob(NULL, varTokenPtr[1].start, len, &ds, &exact)
if (TclReToGlob(NULL, varTokenPtr[1].start, len, &ds, &exact, NULL)
== TCL_OK) {
simple = 1;
PushLiteral(envPtr, Tcl_DStringValue(&ds),Tcl_DStringLength(&ds));
@@ -2354,7 +2358,7 @@ TclCompileRegsubCmd(
Tcl_Obj *patternObj = NULL, *replacementObj = NULL;
Tcl_DString pattern;
const char *bytes;
int len, exact, result = TCL_ERROR;
int len, exact, quantified, result = TCL_ERROR;
if (parsePtr->numWords < 5 || parsePtr->numWords > 6) {
return TCL_ERROR;
@@ -2414,7 +2418,8 @@ TclCompileRegsubCmd(
*/
bytes = Tcl_GetStringFromObj(patternObj, &len);
if (TclReToGlob(NULL, bytes, len, &pattern, &exact) != TCL_OK || exact) {
if (TclReToGlob(NULL, bytes, len, &pattern, &exact, &quantified)
!= TCL_OK || exact || quantified) {
goto done;
}
bytes = Tcl_DStringValue(&pattern);
@@ -2756,7 +2761,7 @@ TclCompileUpvarCmd(
CompileEnv *envPtr) /* Holds resulting instructions. */
{
Tcl_Token *tokenPtr, *otherTokenPtr, *localTokenPtr;
int isScalar, localIndex, numWords, i;
int localIndex, numWords, i;
DefineLineInformation; /* TIP #280 */
Tcl_Obj *objPtr;
@@ -2819,10 +2824,8 @@ TclCompileUpvarCmd(
localTokenPtr = TokenAfter(otherTokenPtr);
CompileWord(envPtr, otherTokenPtr, interp, i);
PushVarNameWord(interp, localTokenPtr, envPtr, 0,
&localIndex, &isScalar, i+1);
if ((localIndex < 0) || !isScalar) {
localIndex = LocalScalarFromToken(localTokenPtr, envPtr);
if (localIndex < 0) {
return TCL_ERROR;
}
TclEmitInstInt4( INST_UPVAR, localIndex, envPtr);
@@ -3017,6 +3020,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. */
+469 -39
View File
@@ -17,6 +17,7 @@
#include "tclInt.h"
#include "tclCompile.h"
#include "tclStringTrim.h"
/*
* Prototypes for procedures defined later in this file:
@@ -27,6 +28,9 @@ static void FreeJumptableInfo(ClientData clientData);
static void PrintJumptableInfo(ClientData clientData,
Tcl_Obj *appendObj, ByteCode *codePtr,
unsigned int pcOffset);
static void DisassembleJumptableInfo(ClientData clientData,
Tcl_Obj *dictObj, ByteCode *codePtr,
unsigned int pcOffset);
static int CompileAssociativeBinaryOpCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, const char *identity,
int instruction, CompileEnv *envPtr);
@@ -71,7 +75,8 @@ const AuxDataType tclJumptableInfoType = {
"JumptableInfo", /* name */
DupJumptableInfo, /* dupProc */
FreeJumptableInfo, /* freeProc */
PrintJumptableInfo /* printProc */
PrintJumptableInfo, /* printProc */
DisassembleJumptableInfo /* disassembleProc */
};
/*
@@ -267,6 +272,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, numArgs, envPtr);
numArgs = 1; /* concat pushes 1 obj, the result */
}
}
wordTokenPtr = TokenAfter(wordTokenPtr);
}
if (folded) {
int len;
const char *bytes = Tcl_GetStringFromObj(folded, &len);
PushLiteral(envPtr, bytes, len);
Tcl_DecrRefCount(folded);
folded = NULL;
numArgs ++;
}
if (numArgs > 1) {
TclEmitInstInt1(INST_STR_CONCAT1, numArgs, envPtr);
}
return TCL_OK;
}
int
TclCompileStringCmpCmd(
Tcl_Interp *interp, /* Used for error reporting. */
@@ -423,6 +500,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 +1055,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 +1142,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 +1164,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 +1192,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 +1220,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 +1292,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}
};
/*
*----------------------------------------------------------------------
*
@@ -1736,7 +2095,7 @@ IssueSwitchChainedTests(
*/
if (TclReToGlob(NULL, bodyToken[i]->start,
bodyToken[i]->size, &ds, &exact) == TCL_OK) {
bodyToken[i]->size, &ds, &exact, NULL) == TCL_OK){
simple = 1;
PushLiteral(envPtr, Tcl_DStringValue(&ds),
Tcl_DStringLength(&ds));
@@ -2086,11 +2445,13 @@ IssueSwitchJumpTable(
* DupJumptableInfo: a copy of the jump-table
* FreeJumptableInfo: none
* PrintJumptableInfo: none
* DisassembleJumptableInfo: none
*
* Side effects:
* DupJumptableInfo: allocates memory
* FreeJumptableInfo: releases memory
* PrintJumptableInfo: none
* DisassembleJumptableInfo: none
*
*----------------------------------------------------------------------
*/
@@ -2153,6 +2514,30 @@ PrintJumptableInfo(
keyPtr, pcOffset + offset);
}
}
static void
DisassembleJumptableInfo(
ClientData clientData,
Tcl_Obj *dictObj,
ByteCode *codePtr,
unsigned int pcOffset)
{
register JumptableInfo *jtPtr = clientData;
Tcl_Obj *mapping = Tcl_NewObj();
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
const char *keyPtr;
int offset;
hPtr = Tcl_FirstHashEntry(&jtPtr->hashTable, &search);
for (; hPtr ; hPtr = Tcl_NextHashEntry(&search)) {
keyPtr = Tcl_GetHashKey(&jtPtr->hashTable, hPtr);
offset = PTR2INT(Tcl_GetHashValue(hPtr));
Tcl_DictObjPut(NULL, mapping, Tcl_NewStringObj(keyPtr, -1),
Tcl_NewIntObj(offset));
}
Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("mapping", -1), mapping);
}
/*
*----------------------------------------------------------------------
@@ -2683,6 +3068,7 @@ IssueTryClausesInstructions(
if (!handlerTokens[i]) {
forwardsNeedFixing = 1;
JUMP4( JUMP, forwardsToFix[i]);
TclAdjustStackDepth(1, envPtr);
} else {
int dontChangeOptions;
@@ -3396,7 +3782,6 @@ TclCompileWhileCmd(
}
SetLineInformation(1);
TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
TclClearNumConversion(envPtr);
jumpDist = CurrentOffset(envPtr) - bodyCodeOffset;
if (jumpDist > 127) {
@@ -3474,6 +3859,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;
}
/*
*----------------------------------------------------------------------
*
+40 -43
View File
@@ -365,7 +365,7 @@ static const unsigned char prec[] = {
0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0,
/* Unary operator lexemes */
PREC_UNARY, /* UNARY_PLUS */
PREC_UNARY, /* UNARY_MINUS */
@@ -420,7 +420,7 @@ static const unsigned char instruction[] = {
0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0,
/* Unary operator lexemes */
INST_UPLUS, /* UNARY_PLUS */
INST_UMINUS, /* UNARY_MINUS */
@@ -488,7 +488,7 @@ static const unsigned char Lexeme[] = {
typedef struct JumpList {
JumpFixup jump; /* Pass this argument to matching calls of
* TclEmitForwardJump() and
* TclEmitForwardJump() and
* TclFixupForwardJump(). */
struct JumpList *next; /* Point to next item on the stack */
} JumpList;
@@ -838,7 +838,7 @@ ParseExpr(
switch (lexeme) {
case NUMBER:
case BOOLEAN:
case BOOLEAN:
/*
* TODO: Consider using a dict or hash to collapse all
* duplicate literals into a single representative value.
@@ -861,7 +861,7 @@ ParseExpr(
start += scanned;
numBytes -= scanned;
continue;
default:
break;
}
@@ -1324,7 +1324,7 @@ ParseExpr(
nodePtr->mark = MARK_LEFT;
nodePtr->left = complete;
/*
/*
* The COMMA operator cannot be optimized, since the function
* needs all of its arguments, and optimization would reduce the
* number. Other binary operators root constant expressions when
@@ -1546,7 +1546,7 @@ ConvertTreeToTokens(
* Tcl_ParseExpr() we do not change them now. Internally, we can
* do better.
*/
int toCopy = tokenPtr->numComponents + 1;
if (tokenPtr->numComponents == tokenPtr[1].numComponents + 1) {
@@ -1562,7 +1562,7 @@ ConvertTreeToTokens(
subExprTokenPtr->type = TCL_TOKEN_SUB_EXPR;
parsePtr->numTokens += toCopy;
} else {
/*
/*
* Multiple element word. Create a TCL_TOKEN_SUB_EXPR token to
* lead, with fields initialized from the leading token, then
* copy entire set of word tokens.
@@ -1611,7 +1611,7 @@ ConvertTreeToTokens(
case COMMA:
case COLON:
/*
/*
* Historical practice has been to have no Tcl_Tokens for
* these operators.
*/
@@ -1747,7 +1747,7 @@ ConvertTreeToTokens(
/*
* Before we leave this node/operator/subexpression for the
* last time, finish up its tokens....
*
*
* Our current position scanning the string is where the
* substring for the subexpression ends.
*/
@@ -1967,7 +1967,7 @@ ParseLexeme(
case 'i':
if ((numBytes > 1) && (start[1] == 'n')
&& ((numBytes == 2) || !isalpha(UCHAR(start[2])))) {
&& ((numBytes == 2) || start[2] & 0x80 || !isalpha(UCHAR(start[2])))) {
/*
* Must make this check so we can tell the difference between the
* "in" operator and the "int" function name and the "infinity"
@@ -1981,14 +1981,15 @@ ParseLexeme(
case 'e':
if ((numBytes > 1) && (start[1] == 'q')
&& ((numBytes == 2) || !isalpha(UCHAR(start[2])))) {
&& ((numBytes == 2) || start[2] & 0x80 || !isalpha(UCHAR(start[2])))) {
*lexemePtr = STREQ;
return 2;
}
break;
case 'n':
if ((numBytes > 1) && ((numBytes == 2) || !isalpha(UCHAR(start[2])))) {
if ((numBytes > 1)
&& ((numBytes == 2) || start[2] & 0x80 || !isalpha(UCHAR(start[2])))) {
switch (start[1]) {
case 'e':
*lexemePtr = STRNEQ;
@@ -2003,9 +2004,8 @@ ParseLexeme(
literal = Tcl_NewObj();
if (TclParseNumber(NULL, literal, NULL, start, numBytes, &end,
TCL_PARSE_NO_WHITESPACE) == TCL_OK) {
if (end < start + numBytes && !isalnum(UCHAR(*end))
&& UCHAR(*end) != '_') {
if (end < start + numBytes && !TclIsBareword(*end)) {
number:
TclInitStringRep(literal, start, end-start);
*lexemePtr = NUMBER;
@@ -2029,9 +2029,9 @@ ParseLexeme(
const char *p = start;
while (p < end) {
if (!isalnum(UCHAR(*p++))) {
if (!TclIsBareword(*p++)) {
/*
* The number has non-bareword characters, so we
* The number has non-bareword characters, so we
* must treat it as a number.
*/
goto number;
@@ -2054,33 +2054,30 @@ ParseLexeme(
}
}
if (Tcl_UtfCharComplete(start, numBytes)) {
scanned = Tcl_UtfToUniChar(start, &ch);
} else {
char utfBytes[TCL_UTF_MAX];
/*
* We reject leading underscores in bareword. No sensible reason why.
* Might be inspired by reserved identifier rules in C, which of course
* have no direct relevance here.
*/
memcpy(utfBytes, start, (size_t) numBytes);
utfBytes[numBytes] = '\0';
scanned = Tcl_UtfToUniChar(utfBytes, &ch);
}
if (!isalnum(UCHAR(ch))) {
if (!TclIsBareword(*start) || *start == '_') {
if (Tcl_UtfCharComplete(start, numBytes)) {
scanned = Tcl_UtfToUniChar(start, &ch);
} else {
char utfBytes[TCL_UTF_MAX];
memcpy(utfBytes, start, (size_t) numBytes);
utfBytes[numBytes] = '\0';
scanned = Tcl_UtfToUniChar(utfBytes, &ch);
}
*lexemePtr = INVALID;
Tcl_DecrRefCount(literal);
return scanned;
}
end = start;
while (isalnum(UCHAR(ch)) || (UCHAR(ch) == '_')) {
end += scanned;
numBytes -= scanned;
if (Tcl_UtfCharComplete(end, numBytes)) {
scanned = Tcl_UtfToUniChar(end, &ch);
} else {
char utfBytes[TCL_UTF_MAX];
memcpy(utfBytes, end, (size_t) numBytes);
utfBytes[numBytes] = '\0';
scanned = Tcl_UtfToUniChar(utfBytes, &ch);
}
while (numBytes && TclIsBareword(*end)) {
end += 1;
numBytes -= 1;
}
*lexemePtr = BAREWORD;
if (literalPtr) {
@@ -2098,7 +2095,7 @@ ParseLexeme(
* TclCompileExpr --
*
* This procedure compiles a string containing a Tcl expression into Tcl
* bytecodes.
* bytecodes.
*
* Results:
* None.
@@ -2333,7 +2330,7 @@ CompileExprTree(
* Use the numWords count we've kept to invoke the function
* command with the correct number of arguments.
*/
if (numWords < 255) {
TclEmitInvoke(envPtr, INST_INVOKE_STK1, numWords);
} else {
@@ -2427,7 +2424,7 @@ CompileExprTree(
const char *bytes = TclGetStringFromObj(literal, &length);
int index = TclRegisterNewLiteral(envPtr, bytes, length);
Tcl_Obj *objPtr = TclFetchLiteral(envPtr, index);
if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) {
/*
* Would like to do this:
@@ -2570,7 +2567,7 @@ TclSingleOpCmd(
*
* TclSortingOpCmd --
* Implements the commands:
* <, <=, >, >=, ==, eq
* <, <=, >, >=, ==, eq
* in the ::tcl::mathop namespace. These commands are defined for
* arbitrary number of arguments by computing the AND of the base
* operator applied to all neighbor argument pairs.
+67 -799
View File
@@ -55,9 +55,9 @@ InstructionDesc const tclInstructionTable[] = {
/* Name Bytes stackEffect #Opnds Operand types */
{"done", 1, -1, 0, {OPERAND_NONE}},
/* Finish ByteCode execution and return stktop (top stack item) */
{"push1", 2, +1, 1, {OPERAND_UINT1}},
{"push1", 2, +1, 1, {OPERAND_LIT1}},
/* Push object at ByteCode objArray[op1] */
{"push4", 5, +1, 1, {OPERAND_UINT4}},
{"push4", 5, +1, 1, {OPERAND_LIT4}},
/* Push object at ByteCode objArray[op4] */
{"pop", 1, -1, 0, {OPERAND_NONE}},
/* Pop the topmost stack object */
@@ -125,17 +125,17 @@ InstructionDesc const tclInstructionTable[] = {
{"incrStkImm", 2, 0, 1, {OPERAND_INT1}},
/* Incr general variable; unparsed name is top, amount is op1 */
{"jump1", 2, 0, 1, {OPERAND_INT1}},
{"jump1", 2, 0, 1, {OPERAND_OFFSET1}},
/* Jump relative to (pc + op1) */
{"jump4", 5, 0, 1, {OPERAND_INT4}},
{"jump4", 5, 0, 1, {OPERAND_OFFSET4}},
/* Jump relative to (pc + op4) */
{"jumpTrue1", 2, -1, 1, {OPERAND_INT1}},
{"jumpTrue1", 2, -1, 1, {OPERAND_OFFSET1}},
/* Jump relative to (pc + op1) if stktop expr object is true */
{"jumpTrue4", 5, -1, 1, {OPERAND_INT4}},
{"jumpTrue4", 5, -1, 1, {OPERAND_OFFSET4}},
/* Jump relative to (pc + op4) if stktop expr object is true */
{"jumpFalse1", 2, -1, 1, {OPERAND_INT1}},
{"jumpFalse1", 2, -1, 1, {OPERAND_OFFSET1}},
/* Jump relative to (pc + op1) if stktop expr object is false */
{"jumpFalse4", 5, -1, 1, {OPERAND_INT4}},
{"jumpFalse4", 5, -1, 1, {OPERAND_OFFSET4}},
/* Jump relative to (pc + op4) if stktop expr object is false */
{"lor", 1, -1, 0, {OPERAND_NONE}},
@@ -298,7 +298,7 @@ InstructionDesc const tclInstructionTable[] = {
/* List Index: push (lindex stktop op4) */
{"listRangeImm", 9, 0, 2, {OPERAND_IDX4, OPERAND_IDX4}},
/* List Range: push (lrange stktop op4 op4) */
{"startCommand", 9, 0, 2, {OPERAND_INT4,OPERAND_UINT4}},
{"startCommand", 9, 0, 2, {OPERAND_OFFSET4, OPERAND_UINT4}},
/* Start of bytecoded command: op is the length of the cmd's code, op2
* is number of commands here */
@@ -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}}
};
@@ -640,11 +692,6 @@ static void RegisterAuxDataType(const AuxDataType *typePtr);
static int SetByteCodeFromAny(Tcl_Interp *interp,
Tcl_Obj *objPtr);
static void StartExpanding(CompileEnv *envPtr);
static int FormatInstruction(ByteCode *codePtr,
const unsigned char *pc, Tcl_Obj *bufferObj);
static void PrintSourceToObj(Tcl_Obj *appendObj,
const char *stringPtr, int maxChars);
static void UpdateStringOfInstName(Tcl_Obj *objPtr);
/*
* TIP #280: Helper for building the per-word line information of all compiled
@@ -682,19 +729,6 @@ static const Tcl_ObjType substCodeType = {
NULL, /* setFromAnyProc */
};
/*
* The structure below defines an instruction name Tcl object to allow
* reporting of inner contexts in errorstack without string allocation.
*/
static const Tcl_ObjType tclInstNameType = {
"instname", /* name */
NULL, /* freeIntRepProc */
NULL, /* dupIntRepProc */
UpdateStringOfInstName, /* updateStringProc */
NULL, /* setFromAnyProc */
};
/*
* Helper macros.
*/
@@ -4308,10 +4342,11 @@ TclInitAuxDataTypeTable(void)
Tcl_InitHashTable(&auxDataTypeTable, TCL_STRING_KEYS);
/*
* There are only three AuxData types at this time, so register them here.
* There are only four AuxData types at this time, so register them here.
*/
RegisterAuxDataType(&tclForeachInfoType);
RegisterAuxDataType(&tclNewForeachInfoType);
RegisterAuxDataType(&tclJumptableInfoType);
RegisterAuxDataType(&tclDictUpdateInfoType);
}
@@ -4544,773 +4579,6 @@ EncodeCmdLocMap(
return p;
}
#ifdef TCL_COMPILE_DEBUG
/*
*----------------------------------------------------------------------
*
* TclPrintByteCodeObj --
*
* This procedure prints ("disassembles") the instructions of a bytecode
* object to stdout.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
TclPrintByteCodeObj(
Tcl_Interp *interp, /* Used only for Tcl_GetStringFromObj. */
Tcl_Obj *objPtr) /* The bytecode object to disassemble. */
{
Tcl_Obj *bufPtr = TclDisassembleByteCodeObj(objPtr);
fprintf(stdout, "\n%s", TclGetString(bufPtr));
Tcl_DecrRefCount(bufPtr);
}
/*
*----------------------------------------------------------------------
*
* TclPrintInstruction --
*
* This procedure prints ("disassembles") one instruction from a bytecode
* object to stdout.
*
* Results:
* Returns the length in bytes of the current instruiction.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TclPrintInstruction(
ByteCode *codePtr, /* Bytecode containing the instruction. */
const unsigned char *pc) /* Points to first byte of instruction. */
{
Tcl_Obj *bufferObj;
int numBytes;
TclNewObj(bufferObj);
numBytes = FormatInstruction(codePtr, pc, bufferObj);
fprintf(stdout, "%s", TclGetString(bufferObj));
Tcl_DecrRefCount(bufferObj);
return numBytes;
}
/*
*----------------------------------------------------------------------
*
* TclPrintObject --
*
* This procedure prints up to a specified number of characters from the
* argument Tcl object's string representation to a specified file.
*
* Results:
* None.
*
* Side effects:
* Outputs characters to the specified file.
*
*----------------------------------------------------------------------
*/
void
TclPrintObject(
FILE *outFile, /* The file to print the source to. */
Tcl_Obj *objPtr, /* Points to the Tcl object whose string
* representation should be printed. */
int maxChars) /* Maximum number of chars to print. */
{
char *bytes;
int length;
bytes = Tcl_GetStringFromObj(objPtr, &length);
TclPrintSource(outFile, bytes, TclMin(length, maxChars));
}
/*
*----------------------------------------------------------------------
*
* TclPrintSource --
*
* This procedure prints up to a specified number of characters from the
* argument string to a specified file. It tries to produce legible
* output by adding backslashes as necessary.
*
* Results:
* None.
*
* Side effects:
* Outputs characters to the specified file.
*
*----------------------------------------------------------------------
*/
void
TclPrintSource(
FILE *outFile, /* The file to print the source to. */
const char *stringPtr, /* The string to print. */
int maxChars) /* Maximum number of chars to print. */
{
Tcl_Obj *bufferObj;
TclNewObj(bufferObj);
PrintSourceToObj(bufferObj, stringPtr, maxChars);
fprintf(outFile, "%s", TclGetString(bufferObj));
Tcl_DecrRefCount(bufferObj);
}
#endif /* TCL_COMPILE_DEBUG */
/*
*----------------------------------------------------------------------
*
* TclDisassembleByteCodeObj --
*
* Given an object which is of bytecode type, return a disassembled
* version of the bytecode (in a new refcount 0 object). No guarantees
* are made about the details of the contents of the result.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
TclDisassembleByteCodeObj(
Tcl_Obj *objPtr) /* The bytecode object to disassemble. */
{
ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1;
unsigned char *codeStart, *codeLimit, *pc;
unsigned char *codeDeltaNext, *codeLengthNext;
unsigned char *srcDeltaNext, *srcLengthNext;
int codeOffset, codeLen, srcOffset, srcLen, numCmds, delta, i;
Interp *iPtr = (Interp *) *codePtr->interpHandle;
Tcl_Obj *bufferObj;
char ptrBuf1[20], ptrBuf2[20];
TclNewObj(bufferObj);
if (codePtr->refCount <= 0) {
return bufferObj; /* Already freed. */
}
codeStart = codePtr->codeStart;
codeLimit = codeStart + codePtr->numCodeBytes;
numCmds = codePtr->numCommands;
/*
* Print header lines describing the ByteCode.
*/
sprintf(ptrBuf1, "%p", codePtr);
sprintf(ptrBuf2, "%p", iPtr);
Tcl_AppendPrintfToObj(bufferObj,
"ByteCode 0x%s, refCt %u, epoch %u, interp 0x%s (epoch %u)\n",
ptrBuf1, codePtr->refCount, codePtr->compileEpoch, ptrBuf2,
iPtr->compileEpoch);
Tcl_AppendToObj(bufferObj, " Source ", -1);
PrintSourceToObj(bufferObj, codePtr->source,
TclMin(codePtr->numSrcBytes, 55));
Tcl_AppendPrintfToObj(bufferObj,
"\n Cmds %d, src %d, inst %d, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n",
numCmds, codePtr->numSrcBytes, codePtr->numCodeBytes,
codePtr->numLitObjects, codePtr->numAuxDataItems,
codePtr->maxStackDepth,
#ifdef TCL_COMPILE_STATS
codePtr->numSrcBytes?
codePtr->structureSize/(float)codePtr->numSrcBytes :
#endif
0.0);
#ifdef TCL_COMPILE_STATS
Tcl_AppendPrintfToObj(bufferObj,
" Code %lu = header %lu+inst %d+litObj %lu+exc %lu+aux %lu+cmdMap %d\n",
(unsigned long) codePtr->structureSize,
(unsigned long) (sizeof(ByteCode) - sizeof(size_t) - sizeof(Tcl_Time)),
codePtr->numCodeBytes,
(unsigned long) (codePtr->numLitObjects * sizeof(Tcl_Obj *)),
(unsigned long) (codePtr->numExceptRanges*sizeof(ExceptionRange)),
(unsigned long) (codePtr->numAuxDataItems * sizeof(AuxData)),
codePtr->numCmdLocBytes);
#endif /* TCL_COMPILE_STATS */
/*
* If the ByteCode is the compiled body of a Tcl procedure, print
* information about that procedure. Note that we don't know the
* procedure's name since ByteCode's can be shared among procedures.
*/
if (codePtr->procPtr != NULL) {
Proc *procPtr = codePtr->procPtr;
int numCompiledLocals = procPtr->numCompiledLocals;
sprintf(ptrBuf1, "%p", procPtr);
Tcl_AppendPrintfToObj(bufferObj,
" Proc 0x%s, refCt %d, args %d, compiled locals %d\n",
ptrBuf1, procPtr->refCount, procPtr->numArgs,
numCompiledLocals);
if (numCompiledLocals > 0) {
CompiledLocal *localPtr = procPtr->firstLocalPtr;
for (i = 0; i < numCompiledLocals; i++) {
Tcl_AppendPrintfToObj(bufferObj,
" slot %d%s%s%s%s%s%s", i,
(localPtr->flags & (VAR_ARRAY|VAR_LINK)) ? "" : ", scalar",
(localPtr->flags & VAR_ARRAY) ? ", array" : "",
(localPtr->flags & VAR_LINK) ? ", link" : "",
(localPtr->flags & VAR_ARGUMENT) ? ", arg" : "",
(localPtr->flags & VAR_TEMPORARY) ? ", temp" : "",
(localPtr->flags & VAR_RESOLVED) ? ", resolved" : "");
if (TclIsVarTemporary(localPtr)) {
Tcl_AppendToObj(bufferObj, "\n", -1);
} else {
Tcl_AppendPrintfToObj(bufferObj, ", \"%s\"\n",
localPtr->name);
}
localPtr = localPtr->nextPtr;
}
}
}
/*
* Print the ExceptionRange array.
*/
if (codePtr->numExceptRanges > 0) {
Tcl_AppendPrintfToObj(bufferObj, " Exception ranges %d, depth %d:\n",
codePtr->numExceptRanges, codePtr->maxExceptDepth);
for (i = 0; i < codePtr->numExceptRanges; i++) {
ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i];
Tcl_AppendPrintfToObj(bufferObj,
" %d: level %d, %s, pc %d-%d, ",
i, rangePtr->nestingLevel,
(rangePtr->type==LOOP_EXCEPTION_RANGE ? "loop" : "catch"),
rangePtr->codeOffset,
(rangePtr->codeOffset + rangePtr->numCodeBytes - 1));
switch (rangePtr->type) {
case LOOP_EXCEPTION_RANGE:
Tcl_AppendPrintfToObj(bufferObj, "continue %d, break %d\n",
rangePtr->continueOffset, rangePtr->breakOffset);
break;
case CATCH_EXCEPTION_RANGE:
Tcl_AppendPrintfToObj(bufferObj, "catch %d\n",
rangePtr->catchOffset);
break;
default:
Tcl_Panic("TclDisassembleByteCodeObj: bad ExceptionRange type %d",
rangePtr->type);
}
}
}
/*
* If there were no commands (e.g., an expression or an empty string was
* compiled), just print all instructions and return.
*/
if (numCmds == 0) {
pc = codeStart;
while (pc < codeLimit) {
Tcl_AppendToObj(bufferObj, " ", -1);
pc += FormatInstruction(codePtr, pc, bufferObj);
}
return bufferObj;
}
/*
* Print table showing the code offset, source offset, and source length
* for each command. These are encoded as a sequence of bytes.
*/
Tcl_AppendPrintfToObj(bufferObj, " Commands %d:", numCmds);
codeDeltaNext = codePtr->codeDeltaStart;
codeLengthNext = codePtr->codeLengthStart;
srcDeltaNext = codePtr->srcDeltaStart;
srcLengthNext = codePtr->srcLengthStart;
codeOffset = srcOffset = 0;
for (i = 0; i < numCmds; i++) {
if ((unsigned) *codeDeltaNext == (unsigned) 0xFF) {
codeDeltaNext++;
delta = TclGetInt4AtPtr(codeDeltaNext);
codeDeltaNext += 4;
} else {
delta = TclGetInt1AtPtr(codeDeltaNext);
codeDeltaNext++;
}
codeOffset += delta;
if ((unsigned) *codeLengthNext == (unsigned) 0xFF) {
codeLengthNext++;
codeLen = TclGetInt4AtPtr(codeLengthNext);
codeLengthNext += 4;
} else {
codeLen = TclGetInt1AtPtr(codeLengthNext);
codeLengthNext++;
}
if ((unsigned) *srcDeltaNext == (unsigned) 0xFF) {
srcDeltaNext++;
delta = TclGetInt4AtPtr(srcDeltaNext);
srcDeltaNext += 4;
} else {
delta = TclGetInt1AtPtr(srcDeltaNext);
srcDeltaNext++;
}
srcOffset += delta;
if ((unsigned) *srcLengthNext == (unsigned) 0xFF) {
srcLengthNext++;
srcLen = TclGetInt4AtPtr(srcLengthNext);
srcLengthNext += 4;
} else {
srcLen = TclGetInt1AtPtr(srcLengthNext);
srcLengthNext++;
}
Tcl_AppendPrintfToObj(bufferObj, "%s%4d: pc %d-%d, src %d-%d",
((i % 2)? " " : "\n "),
(i+1), codeOffset, (codeOffset + codeLen - 1),
srcOffset, (srcOffset + srcLen - 1));
}
if (numCmds > 0) {
Tcl_AppendToObj(bufferObj, "\n", -1);
}
/*
* Print each instruction. If the instruction corresponds to the start of
* a command, print the command's source. Note that we don't need the code
* length here.
*/
codeDeltaNext = codePtr->codeDeltaStart;
srcDeltaNext = codePtr->srcDeltaStart;
srcLengthNext = codePtr->srcLengthStart;
codeOffset = srcOffset = 0;
pc = codeStart;
for (i = 0; i < numCmds; i++) {
if ((unsigned) *codeDeltaNext == (unsigned) 0xFF) {
codeDeltaNext++;
delta = TclGetInt4AtPtr(codeDeltaNext);
codeDeltaNext += 4;
} else {
delta = TclGetInt1AtPtr(codeDeltaNext);
codeDeltaNext++;
}
codeOffset += delta;
if ((unsigned) *srcDeltaNext == (unsigned) 0xFF) {
srcDeltaNext++;
delta = TclGetInt4AtPtr(srcDeltaNext);
srcDeltaNext += 4;
} else {
delta = TclGetInt1AtPtr(srcDeltaNext);
srcDeltaNext++;
}
srcOffset += delta;
if ((unsigned) *srcLengthNext == (unsigned) 0xFF) {
srcLengthNext++;
srcLen = TclGetInt4AtPtr(srcLengthNext);
srcLengthNext += 4;
} else {
srcLen = TclGetInt1AtPtr(srcLengthNext);
srcLengthNext++;
}
/*
* Print instructions before command i.
*/
while ((pc-codeStart) < codeOffset) {
Tcl_AppendToObj(bufferObj, " ", -1);
pc += FormatInstruction(codePtr, pc, bufferObj);
}
Tcl_AppendPrintfToObj(bufferObj, " Command %d: ", i+1);
PrintSourceToObj(bufferObj, (codePtr->source + srcOffset),
TclMin(srcLen, 55));
Tcl_AppendToObj(bufferObj, "\n", -1);
}
if (pc < codeLimit) {
/*
* Print instructions after the last command.
*/
while (pc < codeLimit) {
Tcl_AppendToObj(bufferObj, " ", -1);
pc += FormatInstruction(codePtr, pc, bufferObj);
}
}
return bufferObj;
}
/*
*----------------------------------------------------------------------
*
* FormatInstruction --
*
* Appends a representation of a bytecode instruction to a Tcl_Obj.
*
*----------------------------------------------------------------------
*/
static int
FormatInstruction(
ByteCode *codePtr, /* Bytecode containing the instruction. */
const unsigned char *pc, /* Points to first byte of instruction. */
Tcl_Obj *bufferObj) /* Object to append instruction info to. */
{
Proc *procPtr = codePtr->procPtr;
unsigned char opCode = *pc;
register const InstructionDesc *instDesc = &tclInstructionTable[opCode];
unsigned char *codeStart = codePtr->codeStart;
unsigned pcOffset = pc - codeStart;
int opnd = 0, i, j, numBytes = 1;
int localCt = procPtr ? procPtr->numCompiledLocals : 0;
CompiledLocal *localPtr = procPtr ? procPtr->firstLocalPtr : NULL;
char suffixBuffer[128]; /* Additional info to print after main opcode
* and immediates. */
char *suffixSrc = NULL;
Tcl_Obj *suffixObj = NULL;
AuxData *auxPtr = NULL;
suffixBuffer[0] = '\0';
Tcl_AppendPrintfToObj(bufferObj, "(%u) %s ", pcOffset, instDesc->name);
for (i = 0; i < instDesc->numOperands; i++) {
switch (instDesc->opTypes[i]) {
case OPERAND_INT1:
opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++;
if (opCode == INST_JUMP1 || opCode == INST_JUMP_TRUE1
|| opCode == INST_JUMP_FALSE1) {
sprintf(suffixBuffer, "pc %u", pcOffset+opnd);
}
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
break;
case OPERAND_INT4:
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
if (opCode == INST_JUMP4 || opCode == INST_JUMP_TRUE4
|| opCode == INST_JUMP_FALSE4) {
sprintf(suffixBuffer, "pc %u", pcOffset+opnd);
} else if (opCode == INST_START_CMD) {
sprintf(suffixBuffer, "next cmd at pc %u", pcOffset+opnd);
}
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
break;
case OPERAND_UINT1:
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
if (opCode == INST_PUSH1) {
suffixObj = codePtr->objArrayPtr[opnd];
}
Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd);
break;
case OPERAND_AUX4:
case OPERAND_UINT4:
opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
if (opCode == INST_PUSH4) {
suffixObj = codePtr->objArrayPtr[opnd];
} else if (opCode == INST_START_CMD && opnd != 1) {
sprintf(suffixBuffer+strlen(suffixBuffer),
", %u cmds start here", opnd);
}
Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd);
if (instDesc->opTypes[i] == OPERAND_AUX4) {
auxPtr = &codePtr->auxDataArrayPtr[opnd];
}
break;
case OPERAND_IDX4:
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
if (opnd >= -1) {
Tcl_AppendPrintfToObj(bufferObj, "%d ", opnd);
} else if (opnd == -2) {
Tcl_AppendPrintfToObj(bufferObj, "end ");
} else {
Tcl_AppendPrintfToObj(bufferObj, "end-%d ", -2-opnd);
}
break;
case OPERAND_LVT1:
opnd = TclGetUInt1AtPtr(pc+numBytes);
numBytes++;
goto printLVTindex;
case OPERAND_LVT4:
opnd = TclGetUInt4AtPtr(pc+numBytes);
numBytes += 4;
printLVTindex:
if (localPtr != NULL) {
if (opnd >= localCt) {
Tcl_Panic("FormatInstruction: bad local var index %u (%u locals)",
(unsigned) opnd, localCt);
}
for (j = 0; j < opnd; j++) {
localPtr = localPtr->nextPtr;
}
if (TclIsVarTemporary(localPtr)) {
sprintf(suffixBuffer, "temp var %u", (unsigned) opnd);
} else {
sprintf(suffixBuffer, "var ");
suffixSrc = localPtr->name;
}
}
Tcl_AppendPrintfToObj(bufferObj, "%%v%u ", (unsigned) opnd);
break;
case OPERAND_NONE:
default:
break;
}
}
if (suffixObj) {
const char *bytes;
int length;
Tcl_AppendToObj(bufferObj, "\t# ", -1);
bytes = Tcl_GetStringFromObj(codePtr->objArrayPtr[opnd], &length);
PrintSourceToObj(bufferObj, bytes, TclMin(length, 40));
} else if (suffixBuffer[0]) {
Tcl_AppendPrintfToObj(bufferObj, "\t# %s", suffixBuffer);
if (suffixSrc) {
PrintSourceToObj(bufferObj, suffixSrc, 40);
}
}
Tcl_AppendToObj(bufferObj, "\n", -1);
if (auxPtr && auxPtr->type->printProc) {
Tcl_AppendToObj(bufferObj, "\t\t[", -1);
auxPtr->type->printProc(auxPtr->clientData, bufferObj, codePtr,
pcOffset);
Tcl_AppendToObj(bufferObj, "]\n", -1);
}
return numBytes;
}
/*
*----------------------------------------------------------------------
*
* TclGetInnerContext --
*
* If possible, returns a list capturing the inner context. Otherwise
* return NULL.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
TclGetInnerContext(
Tcl_Interp *interp,
const unsigned char *pc,
Tcl_Obj **tosPtr)
{
int objc = 0, off = 0;
Tcl_Obj *result;
Interp *iPtr = (Interp *) interp;
switch (*pc) {
case INST_STR_LEN:
case INST_LNOT:
case INST_BITNOT:
case INST_UMINUS:
case INST_UPLUS:
case INST_TRY_CVT_TO_NUMERIC:
case INST_EXPAND_STKTOP:
case INST_EXPR_STK:
objc = 1;
break;
case INST_LIST_IN:
case INST_LIST_NOT_IN: /* Basic list containment operators. */
case INST_STR_EQ:
case INST_STR_NEQ: /* String (in)equality check */
case INST_STR_CMP: /* String compare. */
case INST_STR_INDEX:
case INST_STR_MATCH:
case INST_REGEXP:
case INST_EQ:
case INST_NEQ:
case INST_LT:
case INST_GT:
case INST_LE:
case INST_GE:
case INST_MOD:
case INST_LSHIFT:
case INST_RSHIFT:
case INST_BITOR:
case INST_BITXOR:
case INST_BITAND:
case INST_EXPON:
case INST_ADD:
case INST_SUB:
case INST_DIV:
case INST_MULT:
objc = 2;
break;
case INST_RETURN_STK:
/* early pop. TODO: dig out opt dict too :/ */
objc = 1;
break;
case INST_SYNTAX:
case INST_RETURN_IMM:
objc = 2;
break;
case INST_INVOKE_STK4:
objc = TclGetUInt4AtPtr(pc+1);
break;
case INST_INVOKE_STK1:
objc = TclGetUInt1AtPtr(pc+1);
break;
}
result = iPtr->innerContext;
if (Tcl_IsShared(result)) {
Tcl_DecrRefCount(result);
iPtr->innerContext = result = Tcl_NewListObj(objc + 1, NULL);
Tcl_IncrRefCount(result);
} else {
int len;
/*
* Reset while keeping the list intrep as much as possible.
*/
Tcl_ListObjLength(interp, result, &len);
Tcl_ListObjReplace(interp, result, 0, len, 0, NULL);
}
Tcl_ListObjAppendElement(NULL, result, TclNewInstNameObj(*pc));
for (; objc>0 ; objc--) {
Tcl_Obj *objPtr;
objPtr = tosPtr[1 - objc + off];
if (!objPtr) {
Tcl_Panic("InnerContext: bad tos -- appending null object");
}
if ((objPtr->refCount<=0)
#ifdef TCL_MEM_DEBUG
|| (objPtr->refCount==0x61616161)
#endif
) {
Tcl_Panic("InnerContext: bad tos -- appending freed object %p",
objPtr);
}
Tcl_ListObjAppendElement(NULL, result, objPtr);
}
return result;
}
/*
*----------------------------------------------------------------------
*
* TclNewInstNameObj --
*
* Creates a new InstName Tcl_Obj based on the given instruction
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
TclNewInstNameObj(
unsigned char inst)
{
Tcl_Obj *objPtr = Tcl_NewObj();
objPtr->typePtr = &tclInstNameType;
objPtr->internalRep.longValue = (long) inst;
objPtr->bytes = NULL;
return objPtr;
}
/*
*----------------------------------------------------------------------
*
* UpdateStringOfInstName --
*
* Update the string representation for an instruction name object.
*
*----------------------------------------------------------------------
*/
static void
UpdateStringOfInstName(
Tcl_Obj *objPtr)
{
int inst = objPtr->internalRep.longValue;
char *s, buf[20];
int len;
if ((inst < 0) || (inst > LAST_INST_OPCODE)) {
sprintf(buf, "inst_%d", inst);
s = buf;
} else {
s = (char *) tclInstructionTable[objPtr->internalRep.longValue].name;
}
len = strlen(s);
objPtr->bytes = ckalloc(len + 1);
memcpy(objPtr->bytes, s, len + 1);
objPtr->length = len;
}
/*
*----------------------------------------------------------------------
*
* PrintSourceToObj --
*
* Appends a quoted representation of a string to a Tcl_Obj.
*
*----------------------------------------------------------------------
*/
static void
PrintSourceToObj(
Tcl_Obj *appendObj, /* The object to print the source to. */
const char *stringPtr, /* The string to print. */
int maxChars) /* Maximum number of chars to print. */
{
register const char *p;
register int i = 0;
if (stringPtr == NULL) {
Tcl_AppendToObj(appendObj, "\"\"", -1);
return;
}
Tcl_AppendToObj(appendObj, "\"", -1);
p = stringPtr;
for (; (*p != '\0') && (i < maxChars); p++, i++) {
switch (*p) {
case '"':
Tcl_AppendToObj(appendObj, "\\\"", -1);
continue;
case '\f':
Tcl_AppendToObj(appendObj, "\\f", -1);
continue;
case '\n':
Tcl_AppendToObj(appendObj, "\\n", -1);
continue;
case '\r':
Tcl_AppendToObj(appendObj, "\\r", -1);
continue;
case '\t':
Tcl_AppendToObj(appendObj, "\\t", -1);
continue;
case '\v':
Tcl_AppendToObj(appendObj, "\\v", -1);
continue;
default:
Tcl_AppendPrintfToObj(appendObj, "%c", *p);
continue;
}
}
Tcl_AppendToObj(appendObj, "\"", -1);
}
#ifdef TCL_COMPILE_STATS
/*
*----------------------------------------------------------------------
+91 -22
View File
@@ -48,6 +48,13 @@ MODULE_SCOPE int tclTraceCompile;
MODULE_SCOPE int tclTraceExec;
#endif
/*
* The type of lambda expressions. Note that every lambda will *always* have a
* string representation.
*/
MODULE_SCOPE const Tcl_ObjType tclLambdaType;
/*
*------------------------------------------------------------------------
@@ -238,6 +245,16 @@ typedef struct AuxDataType {
AuxDataPrintProc *printProc;/* Callback function to invoke when printing
* the aux data as part of debugging. NULL
* means that the data can't be printed. */
AuxDataPrintProc *disassembleProc;
/* Callback function to invoke when doing a
* disassembly of the aux data (like the
* printProc, except that the output is
* intended to be script-readable). The
* appendObj argument should be filled in with
* a descriptive dictionary; it will start out
* with "name" mapped to the content of the
* name field. NULL means that the printProc
* should be used instead. */
} AuxDataType;
/*
@@ -751,6 +768,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 +805,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 +847,15 @@ 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_OFFSET1, /* One byte signed jump offset. */
OPERAND_OFFSET4, /* Four byte signed jump offset. */
OPERAND_LIT1, /* One byte unsigned index into table of
* literals. */
OPERAND_LIT4, /* Four byte unsigned index into table of
* literals. */
OPERAND_SCLS1 /* Index into tclStringClassTable. */
} InstOperandType;
typedef struct InstructionDesc {
@@ -831,6 +873,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
@@ -1075,6 +1151,10 @@ MODULE_SCOPE void TclFinalizeLoopExceptionRange(CompileEnv *envPtr,
MODULE_SCOPE char * TclLiteralStats(LiteralTable *tablePtr);
MODULE_SCOPE int TclLog2(int value);
#endif
MODULE_SCOPE int TclLocalScalar(const char *bytes, int numBytes,
CompileEnv *envPtr);
MODULE_SCOPE int TclLocalScalarFromToken(Tcl_Token *tokenPtr,
CompileEnv *envPtr);
MODULE_SCOPE void TclOptimizeBytecode(void *envPtr);
#ifdef TCL_COMPILE_DEBUG
MODULE_SCOPE void TclPrintByteCodeObj(Tcl_Interp *interp,
@@ -1112,12 +1192,15 @@ MODULE_SCOPE void TclVerifyLocalLiteralTable(CompileEnv *envPtr);
MODULE_SCOPE int TclWordKnownAtCompileTime(Tcl_Token *tokenPtr,
Tcl_Obj *valuePtr);
MODULE_SCOPE void TclLogCommandInfo(Tcl_Interp *interp,
const char *script,
const char *command, int length,
const unsigned char *pc, Tcl_Obj **tosPtr);
const char *script, const char *command,
int length, const unsigned char *pc,
Tcl_Obj **tosPtr);
MODULE_SCOPE Tcl_Obj *TclGetInnerContext(Tcl_Interp *interp,
const unsigned char *pc, Tcl_Obj **tosPtr);
const unsigned char *pc, Tcl_Obj **tosPtr);
MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst);
MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData,
register Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[], int isLambda);
/*
@@ -1334,18 +1417,6 @@ MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst);
} \
} while (0)
/*
* If the expr compiler finished with TRY_CONVERT, macro to remove it when the
* job is done by the following instruction.
*/
#define TclClearNumConversion(envPtr) \
do { \
if (*(envPtr->codeNext - 1) == INST_TRY_CVT_TO_NUMERIC) { \
envPtr->codeNext--; \
} \
} while (0)
/*
* Macros to update a (signed or unsigned) integer starting at a pointer. The
* two variants depend on the number of bytes. The ANSI C "prototypes" for
@@ -1611,11 +1682,9 @@ MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst);
#define AnonymousLocal(envPtr) \
(TclFindCompiledLocal(NULL, /*nameChars*/ 0, /*create*/ 1, (envPtr)))
#define LocalScalar(chars,len,envPtr) \
(!TclIsLocalScalar((chars), (len)) ? -1 : \
TclFindCompiledLocal((chars), (len), /*create*/ 1, (envPtr)))
TclLocalScalar(chars, len, envPtr)
#define LocalScalarFromToken(tokenPtr,envPtr) \
((tokenPtr)->type != TCL_TOKEN_SIMPLE_WORD ? -1 : \
LocalScalar((tokenPtr)[1].start, (tokenPtr)[1].size, (envPtr)))
TclLocalScalarFromToken(tokenPtr, envPtr)
/*
* Flags bits used by TclPushVarName.
+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;
}
File diff suppressed because it is too large Load Diff
+74 -24
View File
@@ -180,8 +180,9 @@ TCL_DECLARE_MUTEX(encodingMutex)
* the system encoding will be used to perform the conversion.
*/
static Tcl_Encoding defaultEncoding;
static Tcl_Encoding systemEncoding;
static Tcl_Encoding defaultEncoding = NULL;
static Tcl_Encoding systemEncoding = NULL;
Tcl_Encoding tclIdentityEncoding = NULL;
/*
* The following variable is used in the sparse matrix code for a
@@ -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,10 @@ TclFinalizeEncodingSubsystem(void)
Tcl_MutexLock(&encodingMutex);
encodingsInitialized = 0;
FreeEncoding(systemEncoding);
systemEncoding = NULL;
defaultEncoding = NULL;
FreeEncoding(tclIdentityEncoding);
tclIdentityEncoding = NULL;
hPtr = Tcl_FirstHashEntry(&encodingTable, &search);
while (hPtr != NULL) {
@@ -1201,7 +1206,10 @@ Tcl_ExternalToUtf(
* output buffer. */
{
const Encoding *encodingPtr;
int result, srcRead, dstWrote, dstChars;
int result, srcRead, dstWrote, dstChars = 0;
int noTerminate = flags & TCL_ENCODING_NO_TERMINATE;
int charLimited = (flags & TCL_ENCODING_CHAR_LIMIT) && dstCharsPtr;
int maxChars = INT_MAX;
Tcl_EncodingState state;
if (encoding == NULL) {
@@ -1226,19 +1234,40 @@ Tcl_ExternalToUtf(
}
if (dstCharsPtr == NULL) {
dstCharsPtr = &dstChars;
flags &= ~TCL_ENCODING_CHAR_LIMIT;
} else if (charLimited) {
maxChars = *dstCharsPtr;
}
/*
* If there are any null characters in the middle of the buffer, they will
* converted to the UTF-8 null character (\xC080). To get the actual \0 at
* the end of the destination buffer, we need to append it manually.
*/
if (!noTerminate) {
/*
* If there are any null characters in the middle of the buffer,
* they will converted to the UTF-8 null character (\xC080). To get
* the actual \0 at the end of the destination buffer, we need to
* append it manually. First make room for it...
*/
dstLen--;
result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen,
flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr,
dstCharsPtr);
dst[*dstWrotePtr] = '\0';
dstLen--;
}
do {
int savedFlags = flags;
Tcl_EncodingState savedState = *statePtr;
result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen,
flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr,
dstCharsPtr);
if (*dstCharsPtr <= maxChars) {
break;
}
dstLen = Tcl_UtfAtIndex(dst, maxChars) - 1 - dst + TCL_UTF_MAX;
flags = savedFlags;
*statePtr = savedState;
} while (1);
if (!noTerminate) {
/* ...and then append it */
dst[*dstWrotePtr] = '\0';
}
return result;
}
@@ -2102,6 +2131,9 @@ BinaryProc(
if (dstLen < 0) {
dstLen = 0;
}
if ((flags & TCL_ENCODING_CHAR_LIMIT) && srcLen > *dstCharsPtr) {
srcLen = *dstCharsPtr;
}
if (srcLen > dstLen) {
srcLen = dstLen;
result = TCL_CONVERT_NOSPACE;
@@ -2262,7 +2294,7 @@ UtfToUtfProc(
{
const char *srcStart, *srcEnd, *srcClose;
const char *dstStart, *dstEnd;
int result, numChars;
int result, numChars, charLimit = INT_MAX;
Tcl_UniChar ch;
result = TCL_OK;
@@ -2273,11 +2305,14 @@ UtfToUtfProc(
if ((flags & TCL_ENCODING_END) == 0) {
srcClose -= TCL_UTF_MAX;
}
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
}
dstStart = dst;
dstEnd = dst + dstLen - TCL_UTF_MAX;
for (numChars = 0; src < srcEnd; numChars++) {
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
/*
* If there is more string to follow, this will ensure that the
@@ -2373,9 +2408,12 @@ UnicodeToUtfProc(
{
const char *srcStart, *srcEnd;
const char *dstEnd, *dstStart;
int result, numChars;
int result, numChars, charLimit = INT_MAX;
Tcl_UniChar ch;
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
}
result = TCL_OK;
if ((srcLen % sizeof(Tcl_UniChar)) != 0) {
result = TCL_CONVERT_MULTIBYTE;
@@ -2389,7 +2427,7 @@ UnicodeToUtfProc(
dstStart = dst;
dstEnd = dst + dstLen - TCL_UTF_MAX;
for (numChars = 0; src < srcEnd; numChars++) {
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
if (dst > dstEnd) {
result = TCL_CONVERT_NOSPACE;
break;
@@ -2557,12 +2595,15 @@ TableToUtfProc(
{
const char *srcStart, *srcEnd;
const char *dstEnd, *dstStart, *prefixBytes;
int result, byte, numChars;
int result, byte, numChars, charLimit = INT_MAX;
Tcl_UniChar ch;
const unsigned short *const *toUnicode;
const unsigned short *pageZero;
TableEncodingData *dataPtr = clientData;
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
}
srcStart = src;
srcEnd = src + srcLen;
@@ -2574,7 +2615,7 @@ TableToUtfProc(
pageZero = toUnicode[0];
result = TCL_OK;
for (numChars = 0; src < srcEnd; numChars++) {
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
if (dst > dstEnd) {
result = TCL_CONVERT_NOSPACE;
break;
@@ -2788,8 +2829,11 @@ Iso88591ToUtfProc(
{
const char *srcStart, *srcEnd;
const char *dstEnd, *dstStart;
int result, numChars;
int result, numChars, charLimit = INT_MAX;
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
}
srcStart = src;
srcEnd = src + srcLen;
@@ -2797,7 +2841,7 @@ Iso88591ToUtfProc(
dstEnd = dst + dstLen - TCL_UTF_MAX;
result = TCL_OK;
for (numChars = 0; src < srcEnd; numChars++) {
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
Tcl_UniChar ch;
if (dst > dstEnd) {
@@ -2958,7 +3002,9 @@ TableFreeProc(
*/
ckfree(dataPtr->toUnicode);
dataPtr->toUnicode = NULL;
ckfree(dataPtr->fromUnicode);
dataPtr->fromUnicode = NULL;
ckfree(dataPtr);
}
@@ -3011,9 +3057,12 @@ EscapeToUtfProc(
const char *prefixBytes, *tablePrefixBytes, *srcStart, *srcEnd;
const unsigned short *const *tableToUnicode;
const Encoding *encodingPtr;
int state, result, numChars;
int state, result, numChars, charLimit = INT_MAX;
const char *dstStart, *dstEnd;
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
}
result = TCL_OK;
tablePrefixBytes = NULL; /* lint. */
tableToUnicode = NULL; /* lint. */
@@ -3031,7 +3080,7 @@ EscapeToUtfProc(
state = 0;
}
for (numChars = 0; src < srcEnd; ) {
for (numChars = 0; src < srcEnd && numChars <= charLimit; ) {
int byte, hi, lo, ch;
if (dst > dstEnd) {
@@ -3431,6 +3480,7 @@ EscapeFreeProc(
subTablePtr = dataPtr->subTables;
for (i = 0; i < dataPtr->numSubTables; i++) {
FreeEncoding((Tcl_Encoding) subTablePtr->encodingPtr);
subTablePtr->encodingPtr = NULL;
subTablePtr++;
}
}
+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);
+11 -4
View File
@@ -119,6 +119,7 @@ static char * VwaitVarProc(ClientData clientData,
Tcl_Interp *interp, const char *name1,
const char *name2, int flags);
static void InvokeExitHandlers(void);
static void FinalizeThread(int quick);
/*
*----------------------------------------------------------------------
@@ -983,7 +984,7 @@ Tcl_Exit(
* Tcl_Channels that may have data enqueued.
*/
Tcl_FinalizeThread();
FinalizeThread(/* quick */ 1);
}
TclpExit(status);
Tcl_Panic("OS exit failed!");
@@ -1183,7 +1184,7 @@ Tcl_Finalize(void)
* This fixes the Tcl Bug #990552.
*/
TclFinalizeThreadData();
TclFinalizeThreadData(/* quick */ 0);
/*
* Now we can free constants for conversions to/from double.
@@ -1268,6 +1269,13 @@ Tcl_Finalize(void)
void
Tcl_FinalizeThread(void)
{
FinalizeThread(/* quick */ 0);
}
void
FinalizeThread(
int quick)
{
ExitHandler *exitPtr;
ThreadSpecificData *tsdPtr;
@@ -1309,8 +1317,7 @@ Tcl_FinalizeThread(void)
*
* Fix [Bug #571002]
*/
TclFinalizeThreadData();
TclFinalizeThreadData(quick);
}
/*
+1141 -498
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;
}
+4 -4
View File
@@ -235,9 +235,9 @@ ExtractWinRoot(
if ((path[0] == 'c' || path[0] == 'C')
&& (path[1] == 'o' || path[1] == 'O')) {
if ((path[2] == 'm' || path[2] == 'M')
&& path[3] >= '1' && path[3] <= '4') {
&& path[3] >= '1' && path[3] <= '9') {
/*
* May have match for 'com[1-4]:?', which is a serial port.
* May have match for 'com[1-9]:?', which is a serial port.
*/
if (path[4] == '\0') {
@@ -257,9 +257,9 @@ ExtractWinRoot(
} else if ((path[0] == 'l' || path[0] == 'L')
&& (path[1] == 'p' || path[1] == 'P')
&& (path[2] == 't' || path[2] == 'T')) {
if (path[3] >= '1' && path[3] <= '3') {
if (path[3] >= '1' && path[3] <= '9') {
/*
* May have match for 'lpt[1-3]:?'
* May have match for 'lpt[1-9]:?'
*/
if (path[4] == '\0') {
+1702 -2052
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;
}
+125 -80
View File
@@ -187,6 +187,7 @@ struct TransformChannelData {
Tcl_Channel self; /* Our own Channel handle. */
int readIsFlushed; /* Flag to note whether in.flushProc was
* called or not. */
int eofPending; /* Flag: EOF seen down, not raised up */
int flags; /* Currently CHANNEL_ASYNC or zero. */
int watchMask; /* Current watch/event/interest mask. */
int mode; /* Mode of parent channel, OR'ed combination
@@ -210,7 +211,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 +261,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 +269,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,16 +289,17 @@ TclChannelTransform(
dataPtr = ckalloc(sizeof(TransformChannelData));
dataPtr->refCount = 1;
Tcl_DStringInit(&ds);
Tcl_GetChannelOption(interp, chan, "-blocking", &ds);
dataPtr->readIsFlushed = 0;
dataPtr->eofPending = 0;
dataPtr->flags = 0;
if (ds.string[0] == '0') {
dataPtr->flags |= CHANNEL_ASYNC;
}
Tcl_DStringFree(&ds);
dataPtr->self = chan;
dataPtr->watchMask = 0;
dataPtr->mode = mode;
dataPtr->timer = NULL;
@@ -286,19 +315,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 +337,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 +382,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 +396,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 +417,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 +439,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 +468,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 +561,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 +581,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,9 +624,9 @@ TransformInputProc(
* Should assert(dataPtr->mode & TCL_READABLE);
*/
if (toRead == 0) {
if (toRead == 0 || dataPtr->self == NULL) {
/*
* Catch a no-op.
* Catch a no-op. TODO: Is this a panic()?
*/
return 0;
}
@@ -606,6 +634,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 +652,7 @@ TransformInputProc(
* break out of the loop and return to the caller.
*/
return gotBytes;
break;
}
/*
@@ -647,7 +676,18 @@ TransformInputProc(
}
} /* else: 'maxRead < 0' == Accept the current value of toRead. */
if (toRead <= 0) {
return gotBytes;
break;
}
if (dataPtr->eofPending) {
/*
* Already saw EOF from downChan; don't ask again.
* NOTE: Could move this up to avoid the last maxRead
* execution. Believe this would still be correct behavior,
* but the test suite tests the whole command callback
* sequence, so leave it unchanged for now.
*/
break;
}
/*
@@ -656,46 +696,35 @@ 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 ((error == EAGAIN) && (gotBytes > 0)) {
return gotBytes;
}
*errorCodePtr = error;
return -1;
} 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;
}
if (dataPtr->readIsFlushed) {
if (Tcl_InputBlocked(downChan) && (gotBytes > 0)) {
/*
* Already flushed, nothing to do anymore.
* Zero bytes available from downChan because blocked.
* But nonzero bytes already copied, so total is a
* valid blocked short read. Return to caller.
*/
return gotBytes;
break;
}
/*
* Either downChan is not blocked (there's a real error).
* or it is and there are no bytes copied yet. In either
* case we want to pass the "error" along to the caller,
* either to report an error, or to signal to the caller
* that zero bytes are available because blocked.
*/
*errorCodePtr = Tcl_GetErrno();
gotBytes = -1;
break;
} else if (read == 0) {
/*
* Zero returned from Tcl_ReadRaw() always indicates EOF
* on the down channel.
*/
dataPtr->eofPending = 1;
dataPtr->readIsFlushed = 1;
ExecuteCallback(dataPtr, NULL, A_FLUSH_READ, NULL, 0,
TRANSMIT_IBUF, P_PRESERVE);
@@ -705,7 +734,7 @@ TransformInputProc(
* We had nothing to flush.
*/
return gotBytes;
break;
}
continue; /* at: while (toRead > 0) */
@@ -719,10 +748,15 @@ 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 */
if (gotBytes == 0) {
dataPtr->eofPending = 0;
}
ReleaseData(dataPtr);
return gotBytes;
}
@@ -763,11 +797,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 +856,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);
@@ -830,7 +867,9 @@ TransformSeekProc(
P_NO_PRESERVE);
ResultClear(&dataPtr->result);
dataPtr->readIsFlushed = 0;
dataPtr->eofPending = 0;
}
ReleaseData(dataPtr);
return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset, mode,
errorCodePtr);
@@ -891,6 +930,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);
@@ -901,7 +941,9 @@ TransformWideSeekProc(
P_NO_PRESERVE);
ResultClear(&dataPtr->result);
dataPtr->readIsFlushed = 0;
dataPtr->eofPending = 0;
}
ReleaseData(dataPtr);
/*
* If we have a wide seek capability, we should stick with that.
@@ -1056,6 +1098,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 {
/*
+63 -56
View File
@@ -161,6 +161,7 @@ typedef struct {
int mode; /* Mask of R/W mode */
int nonblocking; /* Flag: Channel is blocking or not. */
int readIsDrained; /* Flag: Read buffers are flushed. */
int eofPending; /* Flag: EOF seen down, but not raised up */
int dead; /* Boolean signal that some operations
* should no longer be attempted. */
ResultBuffer result;
@@ -457,8 +458,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 +1063,7 @@ ReflectInput(
{
ReflectedTransform *rtPtr = clientData;
int gotBytes, copied, readBytes;
Tcl_Obj *bufObj;
/*
* The following check can be done before thread redirection, because we
@@ -1078,7 +1079,14 @@ ReflectInput(
Tcl_Preserve(rtPtr);
/* TODO: Consider a more appropriate buffer size. */
bufObj = Tcl_NewByteArrayObj(NULL, toRead);
Tcl_IncrRefCount(bufObj);
gotBytes = 0;
if (rtPtr->eofPending) {
goto stop;
}
rtPtr->readIsDrained = 0;
while (toRead > 0) {
/*
* Loop until the request is satisfied (or no data available from
@@ -1094,6 +1102,11 @@ ReflectInput(
goto stop;
}
if (rtPtr->eofPending) {
goto stop;
}
/*
* The buffer is exhausted, but the caller wants even more. We now
* have to go to the underlying channel, get more bytes and then
@@ -1129,56 +1142,42 @@ 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;
}
rtPtr->eofPending = 1;
/*
* Now this is a bit different. The partial data waiting is
* converted and returned.
@@ -1198,13 +1197,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 +1206,23 @@ 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:
if (gotBytes == 0) {
rtPtr->eofPending = 0;
}
Tcl_DecrRefCount(bufObj);
Tcl_Release(rtPtr);
return gotBytes;
@@ -1773,6 +1777,7 @@ NewReflectedTransform(
rtPtr->timer = NULL;
rtPtr->mode = 0;
rtPtr->readIsDrained = 0;
rtPtr->eofPending = 0;
rtPtr->nonblocking =
(((Channel *) parentChan)->state->flags & CHANNEL_NONBLOCKING);
rtPtr->dead = 0;
@@ -2010,6 +2015,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 +2060,7 @@ InvokeTclMethod(
Tcl_IncrRefCount(resObj);
}
Tcl_RestoreInterpState(rtPtr->interp, sr);
Tcl_Release(rtPtr->interp);
Tcl_Release(rtPtr);
/*
@@ -2230,6 +2237,9 @@ DeleteReflectedTransformMap(
*/
evPtr = resultPtr->evPtr;
if (evPtr == NULL) {
continue;
}
paramPtr = evPtr->param;
evPtr->resultPtr = NULL;
@@ -2355,6 +2365,9 @@ DeleteThreadReflectedTransformMap(
*/
evPtr = resultPtr->evPtr;
if (evPtr == NULL) {
continue;
}
paramPtr = evPtr->param;
evPtr->resultPtr = NULL;
@@ -3065,10 +3078,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 +3092,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 +3113,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 +3123,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 +3190,7 @@ TransformWrite(
}
if (res < 0) {
*errorCodePtr = EINVAL;
*errorCodePtr = Tcl_GetErrno();
return 0;
}
@@ -3294,7 +3300,7 @@ TransformFlush(
}
if (res < 0) {
*errorCodePtr = EINVAL;
*errorCodePtr = Tcl_GetErrno();
return 0;
}
@@ -3324,6 +3330,7 @@ TransformClear(
(void) InvokeTclMethod(rtPtr, "clear", NULL, NULL, NULL);
rtPtr->readIsDrained = 0;
rtPtr->eofPending = 0;
ResultClear(&rtPtr->result);
}
+20 -3
View File
@@ -12,9 +12,26 @@
#include "tclInt.h"
#if defined(_WIN32) && defined(UNICODE)
/* On Windows, we always need the ASCII version. */
# undef gai_strerror
# define gai_strerror gai_strerrorA
/* On Windows, we need to do proper Unicode->UTF-8 conversion. */
typedef struct ThreadSpecificData {
int initialized;
Tcl_DString errorMsg; /* UTF-8 encoded error-message */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
#undef gai_strerror
static const char *gai_strerror(int code) {
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (tsdPtr->initialized) {
Tcl_DStringFree(&tsdPtr->errorMsg);
} else {
tsdPtr->initialized = 1;
}
Tcl_WinTCharToUtf(gai_strerrorW(code), -1, &tsdPtr->errorMsg);
return Tcl_DStringValue(&tsdPtr->errorMsg);
}
#endif
/*
+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);
/*
+59 -4
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
/*
*----------------------------------------------------------------
@@ -1740,7 +1741,7 @@ enum PkgPreferOptions {
* definition there.
* Some macros require knowledge of some fields in the struct in order to
* avoid hitting the TSD unnecessarily. In order to facilitate this, a pointer
* to the relevant fields is kept in the objCache field in struct Interp.
* to the relevant fields is kept in the allocCache field in struct Interp.
*----------------------------------------------------------------
*/
@@ -2451,6 +2452,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 +2664,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 +2864,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 +2883,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,7 +2926,8 @@ MODULE_SCOPE void TclFinalizeObjects(void);
MODULE_SCOPE void TclFinalizePreserve(void);
MODULE_SCOPE void TclFinalizeSynchronization(void);
MODULE_SCOPE void TclFinalizeThreadAlloc(void);
MODULE_SCOPE void TclFinalizeThreadData(void);
MODULE_SCOPE void TclFinalizeThreadAllocThread(void);
MODULE_SCOPE void TclFinalizeThreadData(int quick);
MODULE_SCOPE void TclFinalizeThreadObjects(void);
MODULE_SCOPE double TclFloor(const mp_int *a);
MODULE_SCOPE void TclFormatNaN(double value, char *buffer);
@@ -2918,6 +2952,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);
@@ -2949,8 +2985,8 @@ MODULE_SCOPE void TclInitNotifier(void);
MODULE_SCOPE void TclInitObjSubsystem(void);
MODULE_SCOPE void TclInitSubsystems(void);
MODULE_SCOPE int TclInterpReady(Tcl_Interp *interp);
MODULE_SCOPE int TclIsLocalScalar(const char *src, int len);
MODULE_SCOPE int TclIsSpaceProc(char byte);
MODULE_SCOPE int TclIsBareword(char byte);
MODULE_SCOPE Tcl_Obj * TclJoinPath(int elements, Tcl_Obj * const objv[]);
MODULE_SCOPE int TclJoinThread(Tcl_ThreadId id, int *result);
MODULE_SCOPE void TclLimitRemoveAllHandlers(Tcl_Interp *interp);
@@ -3059,7 +3095,8 @@ MODULE_SCOPE void TclRememberJoinableThread(Tcl_ThreadId id);
MODULE_SCOPE void TclRememberMutex(Tcl_Mutex *mutex);
MODULE_SCOPE void TclRemoveScriptLimitCallbacks(Tcl_Interp *interp);
MODULE_SCOPE int TclReToGlob(Tcl_Interp *interp, const char *reStr,
int reStrLen, Tcl_DString *dsPtr, int *flagsPtr);
int reStrLen, Tcl_DString *dsPtr, int *flagsPtr,
int *quantifiersFoundPtr);
MODULE_SCOPE int TclScanElement(const char *string, int length,
int *flagPtr);
MODULE_SCOPE void TclSetBgErrorHandler(Tcl_Interp *interp,
@@ -3571,6 +3608,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 +3626,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 +3647,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 +3662,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 +3731,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},
+16 -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,9 @@ TclOORemoveFromInstances(
removeInstance:
if (Deleted(clsPtr->thisPtr)) {
if (!IsRootClass(clsPtr)) {
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.3"
#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 */
+46 -67
View File
@@ -618,6 +618,47 @@ TclIsSpaceProc(
return CHAR_TYPE(byte) & (TYPE_SPACE) || byte == '\n';
}
/*
*----------------------------------------------------------------------
*
* TclIsBareword--
*
* Report whether byte is one that can be part of a "bareword".
* This concept is named in expression parsing, where it determines
* what can be a legal function name, but is the same definition used
* in determining what variable names can be parsed as variable
* substitutions without the benefit of enclosing braces. The set of
* ASCII chars that are accepted are the numeric chars ('0'-'9'),
* the alphabetic chars ('a'-'z', 'A'-'Z') and underscore ('_').
*
* Results:
* Returns 1, if byte is in the accepted set of chars, 0 otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TclIsBareword(
char byte)
{
if (byte < '0' || byte > 'z') {
return 0;
}
if (byte <= '9' || byte >= 'a') {
return 1;
}
if (byte == '_') {
return 1;
}
if (byte < 'A' || byte > 'Z') {
return 0;
}
return 1;
}
/*
*----------------------------------------------------------------------
*
@@ -1346,9 +1387,7 @@ Tcl_ParseVarName(
{
Tcl_Token *tokenPtr;
register const char *src;
unsigned char c;
int varIndex, offset;
Tcl_UniChar ch;
int varIndex;
unsigned array;
if ((numBytes == 0) || (start == NULL)) {
@@ -1431,22 +1470,12 @@ Tcl_ParseVarName(
tokenPtr->numComponents = 0;
while (numBytes) {
if (Tcl_UtfCharComplete(src, numBytes)) {
offset = Tcl_UtfToUniChar(src, &ch);
} else {
char utfBytes[TCL_UTF_MAX];
memcpy(utfBytes, src, (size_t) numBytes);
utfBytes[numBytes] = '\0';
offset = Tcl_UtfToUniChar(utfBytes, &ch);
}
c = UCHAR(ch);
if (isalnum(c) || (c == '_')) { /* INTL: ISO only, UCHAR. */
src += offset;
numBytes -= offset;
if (TclIsBareword(*src)) {
src += 1;
numBytes -= 1;
continue;
}
if ((c == ':') && (numBytes != 1) && (src[1] == ':')) {
if ((src[0] == ':') && (numBytes != 1) && (src[1] == ':')) {
src += 2;
numBytes -= 2;
while (numBytes && (*src == ':')) {
@@ -2496,56 +2525,6 @@ TclObjCommandComplete(
return CommandComplete(script, length);
}
/*
*----------------------------------------------------------------------
*
* TclIsLocalScalar --
*
* Check to see if a given string is a legal scalar variable name with no
* namespace qualifiers or substitutions.
*
* Results:
* Returns 1 if the variable is a local scalar.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TclIsLocalScalar(
const char *src,
int len)
{
const char *p;
const char *lastChar = src + (len - 1);
for (p=src ; p<=lastChar ; p++) {
if ((CHAR_TYPE(*p) != TYPE_NORMAL)
&& (CHAR_TYPE(*p) != TYPE_COMMAND_END)) {
/*
* TCL_COMMAND_END is returned for the last character of the
* string. By this point we know it isn't an array or namespace
* reference.
*/
return 0;
}
if (*p == '(') {
if (*lastChar == ')') { /* We have an array element */
return 0;
}
} else if (*p == ':') {
if ((p != lastChar) && *(p+1) == ':') { /* qualified name */
return 0;
}
}
}
return 1;
}
/*
* 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 \
+46 -286
View File
@@ -15,7 +15,6 @@
#include "tclInt.h"
#include "tclCompile.h"
#include "tclOOInt.h"
/*
* Variables that are part of the [apply] command implementation and which
@@ -41,9 +40,6 @@ static void InitResolvedLocals(Tcl_Interp *interp,
ByteCode *codePtr, Var *defPtr,
Namespace *nsPtr);
static void InitLocalCache(Proc *procPtr);
static int PushProcCallFrame(ClientData clientData,
register Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[], int isLambda);
static void ProcBodyDup(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr);
static void ProcBodyFree(Tcl_Obj *objPtr);
static int ProcWrongNumArgs(Tcl_Interp *interp, int skip);
@@ -92,10 +88,10 @@ static const Tcl_ObjType levelReferenceType = {
*
* Internally, ptr1 is a pointer to a Proc instance that is not bound to a
* command name, and ptr2 is a pointer to the namespace that the Proc instance
* will execute within.
* will execute within. IF YOU CHANGE THIS, CHECK IN tclDisassemble.c TOO.
*/
static const Tcl_ObjType lambdaType = {
const Tcl_ObjType tclLambdaType = {
"lambdaExpr", /* name */
FreeLambdaInternalRep, /* freeIntRepProc */
DupLambdaInternalRep, /* dupIntRepProc */
@@ -221,7 +217,7 @@ Tcl_ProcObjCmd(
*
* This code is nearly identical to the #280 code in SetLambdaFromAny, see
* this file. The differences are the different index of the body in the
* line array of the context, and the lamdba code requires some special
* line array of the context, and the lambda code requires some special
* processing. Find a way to factor the common elements into a single
* function.
*/
@@ -1571,7 +1567,7 @@ InitArgsAndLocals(
/*
*----------------------------------------------------------------------
*
* PushProcCallFrame --
* TclPushProcCallFrame --
*
* Compiles a proc body if necessary, then pushes a CallFrame suitable
* for executing it.
@@ -1586,8 +1582,8 @@ InitArgsAndLocals(
*----------------------------------------------------------------------
*/
static int
PushProcCallFrame(
int
TclPushProcCallFrame(
ClientData clientData, /* Record describing procedure to be
* interpreted. */
register Tcl_Interp *interp,/* Interpreter in which procedure was
@@ -1708,7 +1704,7 @@ TclNRInterpProc(
* procedure. */
Tcl_Obj *const objv[]) /* Argument value objects. */
{
int result = PushProcCallFrame(clientData, interp, objc, objv,
int result = TclPushProcCallFrame(clientData, interp, objc, objv,
/*isLambda*/ 0);
if (result != TCL_OK) {
@@ -1855,9 +1851,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 +1918,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;
}
/*
@@ -2451,7 +2439,7 @@ DupLambdaInternalRep(
procPtr->refCount++;
Tcl_IncrRefCount(nsObjPtr);
copyPtr->typePtr = &lambdaType;
copyPtr->typePtr = &tclLambdaType;
}
static void
@@ -2488,7 +2476,7 @@ SetLambdaFromAny(
/*
* Convert objPtr to list type first; if it cannot be converted, or if its
* length is not 2, then it cannot be converted to lambdaType.
* length is not 2, then it cannot be converted to tclLambdaType.
*/
result = TclListObjGetElements(NULL, objPtr, &objc, &objv);
@@ -2634,14 +2622,14 @@ SetLambdaFromAny(
/*
* Free the list internalrep of objPtr - this will free argsPtr, but
* bodyPtr retains a reference from the Proc structure. Then finish the
* conversion to lambdaType.
* conversion to tclLambdaType.
*/
TclFreeIntRep(objPtr);
objPtr->internalRep.twoPtrValue.ptr1 = procPtr;
objPtr->internalRep.twoPtrValue.ptr2 = nsObjPtr;
objPtr->typePtr = &lambdaType;
objPtr->typePtr = &tclLambdaType;
return TCL_OK;
}
@@ -2692,12 +2680,12 @@ TclNRApplyObjCmd(
}
/*
* Set lambdaPtr, convert it to lambdaType in the current interp if
* Set lambdaPtr, convert it to tclLambdaType in the current interp if
* necessary.
*/
lambdaPtr = objv[1];
if (lambdaPtr->typePtr == &lambdaType) {
if (lambdaPtr->typePtr == &tclLambdaType) {
procPtr = lambdaPtr->internalRep.twoPtrValue.ptr1;
}
@@ -2775,7 +2763,7 @@ TclNRApplyObjCmd(
}
extraPtr->isRootEnsemble = isRootEnsemble;
result = PushProcCallFrame(procPtr, interp, objc, objv, 1);
result = TclPushProcCallFrame(procPtr, interp, objc, objv, 1);
if (result == TCL_OK) {
TclNRAddCallback(interp, ApplyNR2, extraPtr, NULL, NULL, NULL);
result = TclNRInterpProcCore(interp, objv[1], 2, &MakeLambdaError);
@@ -2834,234 +2822,6 @@ MakeLambdaError(
(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
}
/*
*----------------------------------------------------------------------
*
* Tcl_DisassembleObjCmd --
*
* Implementation of the "::tcl::unsupported::disassemble" command. This
* command is not documented, but will disassemble procedures, lambda
* terms and general scripts. Note that will compile terms if necessary
* in order to disassemble them.
*
*----------------------------------------------------------------------
*/
int
Tcl_DisassembleObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
static const char *const types[] = {
"lambda", "method", "objmethod", "proc", "script", NULL
};
enum Types {
DISAS_LAMBDA, DISAS_CLASS_METHOD, DISAS_OBJECT_METHOD, DISAS_PROC,
DISAS_SCRIPT
};
int idx, result;
Tcl_Obj *codeObjPtr = NULL;
Proc *procPtr = NULL;
Tcl_HashEntry *hPtr;
Object *oPtr;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "type ...");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], types, "type", 0, &idx)!=TCL_OK){
return TCL_ERROR;
}
switch ((enum Types) idx) {
case DISAS_LAMBDA: {
Command cmd;
Tcl_Obj *nsObjPtr;
Tcl_Namespace *nsPtr;
/*
* Compile (if uncompiled) and disassemble a lambda term.
*/
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "lambdaTerm");
return TCL_ERROR;
}
if (objv[2]->typePtr == &lambdaType) {
procPtr = objv[2]->internalRep.twoPtrValue.ptr1;
}
if (procPtr == NULL || procPtr->iPtr != (Interp *) interp) {
result = SetLambdaFromAny(interp, objv[2]);
if (result != TCL_OK) {
return result;
}
procPtr = objv[2]->internalRep.twoPtrValue.ptr1;
}
memset(&cmd, 0, sizeof(Command));
nsObjPtr = objv[2]->internalRep.twoPtrValue.ptr2;
result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr);
if (result != TCL_OK) {
return result;
}
cmd.nsPtr = (Namespace *) nsPtr;
procPtr->cmdPtr = &cmd;
result = PushProcCallFrame(procPtr, interp, objc, objv, 1);
if (result != TCL_OK) {
return result;
}
TclPopStackFrame(interp);
codeObjPtr = procPtr->bodyPtr;
break;
}
case DISAS_PROC:
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "procName");
return TCL_ERROR;
}
procPtr = TclFindProc((Interp *) interp, TclGetString(objv[2]));
if (procPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" isn't a procedure", TclGetString(objv[2])));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROC",
TclGetString(objv[2]), NULL);
return TCL_ERROR;
}
/*
* Compile (if uncompiled) and disassemble a procedure.
*/
result = PushProcCallFrame(procPtr, interp, 2, objv+1, 1);
if (result != TCL_OK) {
return result;
}
TclPopStackFrame(interp);
codeObjPtr = procPtr->bodyPtr;
break;
case DISAS_SCRIPT:
/*
* Compile and disassemble a script.
*/
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "script");
return TCL_ERROR;
}
if ((objv[2]->typePtr != &tclByteCodeType)
&& (TclSetByteCodeFromAny(interp, objv[2], NULL, NULL) != TCL_OK)) {
return TCL_ERROR;
}
codeObjPtr = objv[2];
break;
case DISAS_CLASS_METHOD:
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "className methodName");
return TCL_ERROR;
}
/*
* Look up the body of a class method.
*/
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
if (oPtr == NULL) {
return TCL_ERROR;
}
if (oPtr->classPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" is not a class", TclGetString(objv[2])));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
TclGetString(objv[2]), NULL);
return TCL_ERROR;
}
hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods,
(char *) objv[3]);
goto methodBody;
case DISAS_OBJECT_METHOD:
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "objectName methodName");
return TCL_ERROR;
}
/*
* Look up the body of an instance method.
*/
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
if (oPtr == NULL) {
return TCL_ERROR;
}
if (oPtr->methodsPtr == NULL) {
goto unknownMethod;
}
hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[3]);
/*
* Compile (if necessary) and disassemble a method body.
*/
methodBody:
if (hPtr == NULL) {
unknownMethod:
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"unknown method \"%s\"", TclGetString(objv[3])));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
TclGetString(objv[3]), NULL);
return TCL_ERROR;
}
procPtr = TclOOGetProcFromMethod(Tcl_GetHashValue(hPtr));
if (procPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"body not available for this kind of method", -1));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
"METHODTYPE", NULL);
return TCL_ERROR;
}
if (procPtr->bodyPtr->typePtr != &tclByteCodeType) {
Command cmd;
/*
* Yes, this is ugly, but we need to pass the namespace in to the
* compiler in two places.
*/
cmd.nsPtr = (Namespace *) oPtr->namespacePtr;
procPtr->cmdPtr = &cmd;
result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr,
(Namespace *) oPtr->namespacePtr, "body of method",
TclGetString(objv[3]));
procPtr->cmdPtr = NULL;
if (result != TCL_OK) {
return result;
}
}
codeObjPtr = procPtr->bodyPtr;
break;
default:
CLANG_ASSERT(0);
}
/*
* Do the actual disassembly.
*/
if (((ByteCode *) codeObjPtr->internalRep.twoPtrValue.ptr1)->flags
& TCL_BYTECODE_PRECOMPILED) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"may not disassemble prebuilt bytecode", -1));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
"BYTECODE", NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, TclDisassembleByteCodeObj(codeObjPtr));
return TCL_OK;
}
/*
* Local Variables:
* mode: c
+2 -1
View File
@@ -946,7 +946,8 @@ CompileRegexp(
* Tcl_RegExpExecObj to optionally do a fast match (avoids RE engine).
*/
if (TclReToGlob(NULL, string, length, &stringBuf, &exact) == TCL_OK) {
if (TclReToGlob(NULL, string, length, &stringBuf, &exact,
NULL) == TCL_OK) {
regexpPtr->globObjPtr = TclDStringToObj(&stringBuf);
Tcl_IncrRefCount(regexpPtr->globObjPtr);
} else {
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)
/*
*----------------------------------------------------------------------
*
+12 -3
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.
@@ -352,9 +353,17 @@ Tcl_ConditionFinalize(
*/
void
TclFinalizeThreadData(void)
TclFinalizeThreadData(int quick)
{
TclFinalizeThreadDataThread();
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
if (!quick) {
/*
* Quick exit principle makes it useless to terminate allocators
*/
TclFinalizeThreadAllocThread();
}
#endif
}
/*
+37 -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 = TclpSysAlloc(sizeof(Tcl_Obj) * numMove, 0);
if (newObjsPtr == NULL) {
Tcl_Panic("alloc: could not allocate %d new objects", numMove);
}
@@ -964,7 +965,7 @@ GetBlocks(
if (blockPtr == NULL) {
size = MAXALLOC;
blockPtr = malloc(size);
blockPtr = TclpSysAlloc(size, 0);
if (blockPtr == NULL) {
return 0;
}
@@ -1023,6 +1024,33 @@ 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);
}
}
#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:
+3
View File
@@ -2511,6 +2511,9 @@ TclObjCallVarTraces(
if (!part1Ptr) {
part1Ptr = localName(iPtr->varFramePtr, index);
}
if (!part1Ptr) {
Tcl_Panic("Cannot trace a variable with no name");
}
part1 = TclGetString(part1Ptr);
part2 = part2Ptr? TclGetString(part2Ptr) : NULL;
+1154 -1066
View File
File diff suppressed because it is too large Load Diff
+103 -27
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;
@@ -4180,7 +4249,8 @@ TclReToGlob(
const char *reStr,
int reStrLen,
Tcl_DString *dsPtr,
int *exactPtr)
int *exactPtr,
int *quantifiersFoundPtr)
{
int anchorLeft, anchorRight, lastIsStar, numStars;
char *dsStr, *dsStrStart;
@@ -4188,6 +4258,9 @@ TclReToGlob(
strEnd = reStr + reStrLen;
Tcl_DStringInit(dsPtr);
if (quantifiersFoundPtr != NULL) {
*quantifiersFoundPtr = 0;
}
/*
* "***=xxx" == "*xxx*", watch for glob-sensitive chars.
@@ -4300,6 +4373,9 @@ TclReToGlob(
}
break;
case '.':
if (quantifiersFoundPtr != NULL) {
*quantifiersFoundPtr = 1;
}
anchorLeft = 0; /* prevent exact match */
if (p+1 < strEnd) {
if (p[1] == '*') {
+7 -5
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) {
@@ -4402,8 +4405,8 @@ ObjMakeUpvar(
|| !HasLocalVars(varFramePtr)
|| (strstr(TclGetString(myNamePtr), "::") != NULL))) {
Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_ObjPrintf(
"bad variable name \"%s\": upvar won't create "
"namespace variable that refers to procedure variable",
"bad variable name \"%s\": can't create namespace "
"variable that refers to procedure variable",
TclGetString(myNamePtr)));
Tcl_SetErrorCode(interp, "TCL", "UPVAR", "INVERTED", NULL);
return TCL_ERROR;
@@ -4503,9 +4506,8 @@ TclPtrObjMakeUpvar(
*/
Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_ObjPrintf(
"bad variable name \"%s\": upvar won't create a"
" scalar variable that looks like an array element",
myName));
"bad variable name \"%s\": can't create a scalar "
"variable that looks like an array element", myName));
Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT",
NULL);
return TCL_ERROR;
+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.3
# 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

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