Compare commits

...
Author SHA1 Message Date
dgp 790b302275 Optimize case of all single-byte chars. 2016-11-07 20:04:22 +00:00
dgp dc11ffbbdb Consolidate the "find empty string" cases. 2016-11-07 19:41:15 +00:00
dgp 1571dc01bb Implement direct eval [string first] with the refactored engine. 2016-11-07 19:28:25 +00:00
dgp 4dc2505e43 First draft refactoring the [string first] functionality. 2016-11-04 21:29:30 +00:00
dgp 18a2ebc51d [824752f10e] Use LIST_MAX instead of INT_MAX for unknown number of elements to the end of the list. 2016-11-04 14:56:19 +00:00
dgp da3723c942 [8245752f10e] Use LIST_MAX instead of INT_MAX for unknown number of elements
to the end of the list.
2016-11-04 14:54:38 +00:00
dgp 27ef344b9c merge mark 2016-11-04 14:49:22 +00:00
dgp 885ced5608 [824752f10e] More robust, portable check for integer overflow. 2016-11-04 14:48:36 +00:00
dgp b1fe66323b close fork 2016-11-04 14:42:14 +00:00
dgp a188ceee21 [824752f10e] More robust, portable check for integer overflow. 2016-11-04 14:40:54 +00:00
dgp eb87ed60f6 close fork 2016-11-04 14:39:00 +00:00
dgp bc94a394c9 [824752f10e] More robust, portable check for integer overflow. 2016-11-04 14:37:50 +00:00
gahr 46d871617f merge core-8-5-branch ([824752f10e] Avoid calling Tcl_SetObjResult if interp is NULL) 2016-11-04 14:24:42 +00:00
gahr d654ce6429 merge core-8-5-branch ([824752f10e] Avoid calling Tcl_SetObjResult if interp is NULL) 2016-11-04 14:23:43 +00:00
gahr 452f14ebb5 [824752f10e] Avoid calling Tcl_SetObjResult if interp is NULL 2016-11-04 14:21:04 +00:00
jan.nijtmans 0a7d5ef6ed Fix the generated copyright sections in the HTML help file 2016-11-04 11:51:22 +00:00
jan.nijtmans f785a01764 Fix the generated copyright sections in the HTML help file. 2016-11-04 11:50:22 +00:00
jan.nijtmans 274f081025 Make packages msgcat and tcltest work unmodified in "novem". Make more test-cases work unmodified in "novem". 2016-11-04 11:38:09 +00:00
jan.nijtmans 76ed3d5b55 Make packages msgcat and tcltest work unmodified in "novem". 2016-11-04 11:32:44 +00:00
jan.nijtmans fba10e8615 merge core-8-6-branch (http package version update) 2016-11-02 12:45:47 +00:00
jan.nijtmans 1f0c1b800d Update http version number to 2.8.10, due to [838e99a76d] 2016-11-02 12:44:32 +00:00
jan.nijtmans a7e97de50a Update http version number to 2.7.14, due to [838e99a76d] 2016-11-02 12:41:04 +00:00
Joe Mistachkin ea11870f5b Fix the generated copyright sections in the HTML help file. 2016-11-02 01:42:49 +00:00
dgp 95b511bac2 Refactor to channel all [string cat] functions through a single implementation. 2016-11-01 16:18:08 +00:00
dgp 17e1ea228c Replace indexing with pointer increments. 2016-11-01 15:42:50 +00:00
dgp 53abdcc518 Trim away obsolete code. 2016-11-01 15:12:07 +00:00
dgp d963b1acb7 Expand all the cases of the [string cat] engine. 2016-11-01 15:07:30 +00:00
dgp 04432d4dd1 Reduce copies in the pure binary implementation of [string cat]. 2016-10-31 18:10:21 +00:00
dgp 3e4f5907b6 Complete the "pure binary" implementation of the [string cat] engine. 2016-10-31 16:15:16 +00:00
dgp 4a159c5199 merge trunk 2016-10-31 14:18:03 +00:00
dgp b53cf6d38c Coverage tests for INST_STR_CONCAT1 byterarray ops. 2016-10-31 14:17:31 +00:00
dkf 779b8dad76 [253ba6e818] Improved description of [variable] behaviour. 2016-10-30 16:52:50 +00:00
dkf cd428c1a44 [253ba6e818] Improved description of [variable] behaviour. 2016-10-30 16:16:29 +00:00
dkf 16dbe3f5a2 [1ae12987cb] Ensure that deleting the [history] command deletes its storage. 2016-10-30 08:31:21 +00:00
dkf 7b989f0312 [1ae12987cb] Ensure that deleting the [history] command deletes its storage. 2016-10-30 08:22:13 +00:00
dkf 994e1d8062 One more place where the internal API change can be used easily. 2016-10-30 05:07:47 +00:00
dkf de8e3be492 [b26e38a3e4] Ensure that compressing streams manage buffers correctly in all cases. 2016-10-30 05:05:46 +00:00
dkf d44a63b65b [b26e38a3e4] Ensure that compressing streams manage buffers correctly in all cases. 2016-10-30 05:04:54 +00:00
dkf 423d995e0d Fix the bug. Make use of zlib API in this area more like a Tcl API with wrapper function. 2016-10-30 05:02:46 +00:00
dkf 5c37d95180 Added test for bug 2016-10-29 21:03:25 +00:00
dgp 970922295a WIP 2016-10-28 20:33:55 +00:00
dgp 31690ce7fb revise [dict append] to make use of common [string cat] engine. 2016-10-28 16:55:44 +00:00
dgp 630d4b9211 merge trunk 2016-10-28 15:47:07 +00:00
dgp 7faf4f27a4 Add optimization to [dict append]. 2016-10-28 15:46:49 +00:00
dgp dd1c28a788 When appropriate, implement [join] with the common [string cat] engine. 2016-10-28 14:59:27 +00:00
dgp afd6d5649f Add obvious optimizations to [join] implementation. 2016-10-28 14:45:54 +00:00
dgp e9d7b07476 merge trunk 2016-10-28 14:28:40 +00:00
dgp b8ffbb14c4 Add warning commentary making important assumptions explicit. 2016-10-28 14:27:59 +00:00
dgp 39dbbd57af Add warning commentary making important assumptions explicit. 2016-10-28 14:26:18 +00:00
dgp bbfc83c86f Add warning commentary making important assumptions explicit. 2016-10-28 14:23:25 +00:00
dgp d31beb3e7f merge trunk 2016-10-28 14:06:36 +00:00
dgp aa3b157338 Add obvious optimization to Tcl_GetCharLength(). 2016-10-28 14:06:15 +00:00
dgp bf27b64405 Convert INST_STR_CONCAT1 to the common string cat implementation. 2016-10-27 20:06:36 +00:00
dgp 76b6b03be7 Start bringing all string cat operations into one place so it can be coded
correctly one time instead of badly multiple times.
2016-10-27 19:39:49 +00:00
venkat c205f272f7 Merge timezone data tzdata2016h 2016-10-26 08:04:36 +00:00
venkat 0551ecffd6 Merge timezone data tzdata2016h 2016-10-26 08:04:10 +00:00
venkat 13967f965d Update timezone data to tzdata2016h from IETF 2016-10-26 08:03:17 +00:00
dgp 79ff282b02 merge 8.6 2016-10-21 13:12:16 +00:00
dgp 9afdf28497 Repair recently opened memleak. 2016-10-20 20:02:19 +00:00
dgp bfae5bf492 EVIL HACKs are bad. Unnecessary ones are intolerable. Bad tests cause trouble. 2016-10-20 17:54:47 +00:00
dgp 925bd5794e Use memcmp where possible. 2016-10-18 19:16:35 +00:00
dgp ae54e070a1 [eb6b68c1a9] Simple fix for [string replace] error demonstrated by new test. 2016-10-14 19:29:52 +00:00
dgp 8b894ab295 [eb6b68c1a9] Simple fix for [string replace] error demonstrated by new test. 2016-10-14 19:28:46 +00:00
dgp e35292f314 Merge INST_STR_REPLACE fixes and improvements. 2016-10-13 16:56:23 +00:00
dgp 7f0e6652c7 Another streamline. 2016-10-13 16:50:06 +00:00
dgp 7634bdaef2 Stop invading the String internals to work around a bug. Fix it instead. 2016-10-13 16:43:05 +00:00
dgp 9cb330963b Streamline the substring copying case of [string replace] bytecode execution. 2016-10-13 15:37:45 +00:00
dgp 4dc1a8a588 merge TclParseNumber fixes 2016-10-12 13:47:32 +00:00
dgp 66f257a588 [be003d570f] TclParseNumber() failed to fully implement TCL_PARSE_BINARY_ONLY. 2016-10-12 13:46:14 +00:00
dgp 36825d23b9 [be003d570f] TclParseNumber() failed to fully implement TCL_PARSE_OCTAL_ONLY. 2016-10-12 13:42:40 +00:00
dgp 326e0a8fdf Add a test too. 2016-10-12 13:38:28 +00:00
dgp 29fdaa6dcd [be003d570f] TclParseNumber() failed to fully implement TCL_PARSE_OCTAL_ONLY. 2016-10-12 13:31:07 +00:00
dkf ae0ad313fd [74bc0e44f5] Doc tweak. 2016-10-12 09:58:12 +00:00
dkf ec64cc0418 [74bc0e44f5] Doc tweak. 2016-10-12 09:57:49 +00:00
dkf c482675d84 [74bc0e44f5] Doc tweak. 2016-10-12 09:57:15 +00:00
jan.nijtmans 7dd13b72b6 Fix [3cc1d91345]: duplicate calls to TclpFreeAllocCache() on thread exists 2016-10-11 21:52:57 +00:00
jan.nijtmans 54c0881e9d Fix [3cc1d91345]: duplicate calls to TclpFreeAllocCache() on thread exists 2016-10-11 21:43:44 +00:00
jan.nijtmans d81daf76bd Fix [3cc1d91345]: duplicate calls to TclpFreeAllocCache() on thread exists 2016-10-11 21:35:27 +00:00
dkf 11e9b6a9a5 [62b36e326c] Noted edge case in behaviour of [concat] with empty arguments. 2016-10-09 16:02:38 +00:00
dkf 8fe7f3fcdf [62b36e326c] Noted edge case in behaviour of [concat] with empty arguments. 2016-10-09 16:02:16 +00:00
dkf f3e9f9caa3 [62b36e326c] Noted edge case in behaviour of [concat] with empty arguments. 2016-10-09 16:01:53 +00:00
dkf 28d5ff4eb5 [7114ac6141] Improve testing and docs of Tcl_GetInt and Tcl_GetDouble. No behaviour change. 2016-10-09 15:22:20 +00:00
dkf 71c2d1a883 [7114ac6141] Improve testing and docs of Tcl_GetInt and Tcl_GetDouble. No behaviour change. 2016-10-09 15:21:26 +00:00
dkf c8597887e4 Be more accurate about scan's %i 2016-10-09 12:03:30 +00:00
ferrieux 05009534ee Be more accurate about scan's %i 2016-10-09 10:35:24 +00:00
dkf f50a4eed54 [74bc0e44f5] Document result of [http::unregister]. 2016-10-08 17:10:40 +00:00
dkf 90813dfce8 [74bc0e44f5] Document result of [http::unregister]. 2016-10-08 17:10:21 +00:00
dkf a16868a54c [74bc0e44f5] Document result of [http::unregister]. 2016-10-08 17:10:02 +00:00
dkf c4eac3e8eb [838e99a76d] Ensure that encodings are handled with application/xml and friends. 2016-10-08 16:41:51 +00:00
dkf 7b78869343 [838e99a76d] Ensure that encodings are handled with application/xml and friends. 2016-10-08 16:40:35 +00:00
dkf ab8a39e6b9 [838e99a76d] Ensure that encodings are handled with application/xml and friends. 2016-10-08 16:38:42 +00:00
dgp 870f61c05d Update [string map] tests to get illustration of need for pure dict
restriction up to date with ordered dicts.
2016-10-07 18:52:57 +00:00
pooryorick 6585306973 Fix typos in expr documentation. 2016-10-05 04:53:49 +00:00
pooryorick b1d510f1db Rewrite expr documentation. Among other things, fixes [ef5373e6fa0617ee]. 2016-10-05 00:05:55 +00:00
dkf 111f52e7ed [4d5ae7d88a] Stop crashes with asynchronous connects to hosts without addresses. 2016-10-04 19:12:33 +00:00
dkf 6548fc4ad1 [4d5ae7d88a] Stop crashes with asynchronous connects to hosts without addresses. 2016-10-04 19:11:07 +00:00
max a629b0ba31 When opening a server socket on an ephemeral port, make sure that the
port number that gets picked for IPv4 is also available on IPv6. If
not, start all over for up to ten times to find a port number that is
available on both protocols.
2016-10-04 13:31:49 +00:00
pooryorick 8c066a970f Fix documentation of [expr] operators, replacing "divisor" with "dividend" 2016-10-03 16:49:58 +00:00
jan.nijtmans 29b9de871c (cherry-pick): Fix [2bf561854c55a], interp alias to command whose name is the empty string. 2016-10-03 14:53:32 +00:00
pooryorick a9dbadf46a Fix [2bf561854c55a], interp alias to command whose name is the empty string. 2016-10-03 01:10:16 +00:00
venkat 02e79b9ec1 Merge tzdata2016g from ietf.org 2016-10-02 19:26:30 +00:00
venkat 5aa514f49a Merge tzdata2016g from ietf.org 2016-10-02 19:25:58 +00:00
venkat 2bc8d915a2 Update tzdata to 2016g from ietf.org 2016-10-02 19:24:52 +00:00
gahr c4f7e08fc6 [4d5ae7d88a] Restore default-to-error logic in TcpConnect 2016-09-27 20:06:49 +00:00
jan.nijtmans 008c7038cb merge core-8-6-branch 2016-09-26 09:10:35 +00:00
jan.nijtmans dfb2a3f2e2 Fix the 'htmlhelp' target so that it compiles cleanly and includes all the appropriate HTML files.
Permit static linking to the MSVCRT as a stand-alone option. 
Patch by Joe Mistachkin.
2016-09-26 09:08:13 +00:00
jan.nijtmans e8aa220d08 merge core-8-6-branch. Undo changes to coffbase.txt (they cause overlap with Tk) 2016-09-21 09:36:35 +00:00
jan.nijtmans 8d3c0c2e81 Merge core-8-6-branch. Add more comments to tclLiteral.c, contributed by mr_calvin 2016-09-21 09:28:39 +00:00
jan.nijtmans 3adfe07f74 Make it more likely that compiles with VS2012/VS2013 actually work on Windows XP. See: [https://tedwvc.wordpress.com/2014/01/01/how-to-target-xp-with-vc2012-or-vc2013-and-continue-to-use-the-windows-8-x-sdk/] 2016-09-21 09:20:54 +00:00
jan.nijtmans 7aae664d12 Make it more likely that compiled with VS2012/VS2013 actually work on Windows XP. See: [https://tedwvc.wordpress.com/2014/01/01/how-to-target-xp-with-vc2012-or-vc2013-and-continue-to-use-the-windows-8-x-sdk/] 2016-09-21 09:15:34 +00:00
Joe Mistachkin cdb1ef8aac Permit static linking to the MSVCRT as a stand-alone option. Enable WinXP SDK compatibility. 2016-09-19 18:48:16 +00:00
jan.nijtmans e7e4c74b7f merge core-8-6-branch 2016-09-16 09:09:25 +00:00
jan.nijtmans 3d6c6683bb Fix [c7d0bc9a549714e0]: Newly introduced unshared (local-only) literals from cmd resolvers cause Tcl_Obj leaks. 2016-09-16 09:06:41 +00:00
jan.nijtmans bf9e61ca6a Proposed fix for [c7d0bc9a549714e0]. Thanks to mr_calvin 2016-09-15 13:22:49 +00:00
dgp db811061d4 Revert b98ee56376. The "bug" fixed was documented behavior. 2016-09-09 12:36:53 +00:00
gahr 63a316c43b Remove unnecessary use of fpsetround. See https://bugs.freebsd.org/212512 2016-09-09 07:28:45 +00:00
dgp 3da8f74e75 [7f02ff1efa] Fix scope for var unset traces when procs return.
*** POTENTIAL INCOMPATIBILITY ***
2016-09-08 02:38:39 +00:00
dgp 3833c42f54 New test trace-18.5 for the bug. Updated trace-18.1 which was tuned to it. 2016-09-08 02:34:37 +00:00
dgp 2bfb7b96c0 Attempt to fix [7f02ff1efa]. Make trace-18.1 fail. Suspect test is an
experiment that preserves the bug.
2016-09-07 18:31:58 +00:00
dgp 35141afcc9 [4dbdd9af14] Plug mem leak when var unset trace re-creates namespace var. Thanks mr_calvin for report and fix. 2016-09-07 18:09:30 +00:00
dgp 6053836b97 [4dbdd9af14] Plug mem leak when var unset trace re-creates namespace var. Thanks mr_calvin for report and fix. 2016-09-07 17:45:33 +00:00
dgp e13460b1fb [4dbdd9af14] Plug mem leak when var unset trace re-creates namespace var.
Thanks mr_calvin for report and fix.
2016-09-07 17:30:18 +00:00
dgp 41512fe1fa Improve the comments and add a test. 2016-09-07 16:19:42 +00:00
jan.nijtmans 4ef0c69aaa Fix [d4e7780ca1681cd095dbd81fe264feff75c988f7|d4e7780ca1]: "global" cmd literal sharing vs. per-interp resolvers 2016-09-07 13:34:41 +00:00
jan.nijtmans 7660c04aff Fix [d4e7780ca1681cd095dbd81fe264feff75c988f7|d4e7780ca1]: "global" cmd literal sharing vs. per-interp resolvers 2016-09-07 12:54:51 +00:00
dgp 7ca470456b [4dbdd9af14] Proposed fix for mem leak. 2016-09-06 20:30:07 +00:00
dkf ab18c108f7 Fixed bug in pushed transforms with full internal buffers not writing out. 2016-09-06 10:46:49 +00:00
dkf 7ccdd3657b Fixed bug in pushed transforms with full internal buffers not writing out. 2016-09-06 10:44:45 +00:00
jan.nijtmans 98dbefe2cc Additiona patch/suggestion from Gustaf. This indeed fixes the crash in oo.test. Looks good to me, so only waiting for final feedback from Gustaf and eventually feedback from other people. 2016-09-06 08:25:18 +00:00
jan.nijtmans b748232291 some more clean-up 2016-09-05 14:52:01 +00:00
jan.nijtmans d35a5023da merge core-8-6-branch 2016-09-05 14:12:48 +00:00
jan.nijtmans c4b6cab579 merge core-8-6-branch 2016-09-05 13:56:15 +00:00
jan.nijtmans cf8c1e7bdc Allow additional optional "interp" argument for testinterpresolver command. Not used yet in any test-case.
Protect panic in tclLiteral.c for possible null-pointer access. (cherry-picked from Gustaf Neuman's interpresolver patch).
Eliminate some unecessary spacing.
2016-09-05 13:55:00 +00:00
jan.nijtmans 6f860bc18d Some patch clean-up, no change in functionality 2016-09-05 13:14:45 +00:00
jan.nijtmans 2bd794f7cc Proposed patch for [d4e7780ca1681cd095dbd81fe264feff75c988f7|d4e7780ca1], by Gustaf Neumann 2016-09-02 12:11:01 +00:00
jan.nijtmans 5b7e79f851 Don't ever allow UTF-8 sequences of more than 4 characters to be generated or parsed, even when TCL_UTF_MAX>4: According to current Unicode standard, a byte string of >4 characters can never form a single UTF-8 character.
And a few minor micro-optimizations related to UTF-8 handling.
2016-08-30 13:07:10 +00:00
jan.nijtmans 3b2cb79ab1 Don't ever allow UTF-8 sequences of more than 4 characters to be generated or parsed, even when TCL_UTF_MAX>4: According to current Unicode standard, a byte string of >4 characters can never form a single UTF-8 character.
And a few minor micro-optimizations related to UTF-8 handling.
2016-08-30 13:00:32 +00:00
dgp 0cce018c67 Merge dup-removal into search loop so we avoid pre-processing efforts on data that are never used. Contributed patch from Brian Griffin. 2016-08-26 13:49:07 +00:00
dgp f2115ca085 Merge dup-removal into search loop so we avoid pre-processing efforts on
data that are never used. Contributed patch from Brian Griffin.
2016-08-26 13:46:37 +00:00
Joe Mistachkin ac673f63d0 Set the default topic, enable full-text search, and put all help output files under OUT_DIR. 2016-08-10 03:13:46 +00:00
Joe Mistachkin 5001d7d18c Fix the 'htmlhelp' target so that it compiles cleanly and includes all the appropriate HTML files. 2016-08-09 21:03:28 +00:00
dgp a134b03eda merge mark 2016-07-27 18:56:20 +00:00
dgp d823d4a2d5 merge release 2016-07-27 18:55:23 +00:00
dgp 27696b490b a few test & docs fixes 2016-07-26 13:54:57 +00:00
dkf b37c60fe43 [db0a5f6417] Make a few tests resilient to differences in semantics of pipes between OSs. 2016-07-26 10:09:06 +00:00
dkf d0af5aa92c [db0a5f6417] Make a few tests resilient to differences in semantics of pipes between OSs. 2016-07-26 10:08:29 +00:00
dkf d4eb48d90f [6a19dedc2e] "Clarified" what the units are that [chan copy] uses for -size and that synchronous copying returns. 2016-07-24 17:58:13 +00:00
dkf 9faead9d18 [6a19dedc2e] "Clarified" what the units are that [chan copy] uses for -size and that synchronous copying returns. 2016-07-24 13:09:40 +00:00
dkf 404eadfdaf Make a few tests more resilient to differences in the semantics of pipes between operating systems. 2016-07-24 12:45:07 +00:00
dgp 722ba1aa44 test repairs 2016-07-22 15:28:50 +00:00
dgp 4cead413c9 Set release date 2016-07-22 14:00:01 +00:00
dgp 2501dbb8d0 Update changes file. 2016-07-21 16:20:38 +00:00
dgp 0050652afb Stop internals intrusion into lists. 2016-07-20 20:39:16 +00:00
dgp 4704b442fb Streamline TclObjLookupVarEx 2016-07-20 17:39:04 +00:00
dgp 5b8d20e6de Use strchr() to parse array variable syntax. 2016-07-20 16:32:16 +00:00
dgp 2151838b5b Use the new private flag INDEX_TEMP_TABLE in testing command too. 2016-07-20 15:43:08 +00:00
dgp acb9c613f1 merge 8.6 2016-07-20 11:48:44 +00:00
venkat ee54cd02de Merge tzdata 2016f from ietf.org 2016-07-20 03:05:57 +00:00
venkat ad4538af95 Merge tzdata 2016f from ietf.org 2016-07-20 03:05:31 +00:00
venkat c2e7b1ce36 Update tzdata to 2016f from ietf.org 2016-07-20 03:05:01 +00:00
dgp a8f05c5339 Factor out common prologue. 2016-07-19 20:40:27 +00:00
dgp e26431e0f3 merge 8.6 2016-07-19 19:52:59 +00:00
dgp 23a34a26fe "array search" is no longer a registered Tcl_ObjType. 2016-07-19 19:33:35 +00:00
dgp 3cd3541039 [0363f0146c] Fix [array startsearch] id handling to support var name variations 2016-07-19 19:31:28 +00:00
dgp f846b3f965 Remove outdated comment. 2016-07-19 15:00:51 +00:00
dgp a22b8736ec merge 8.6 2016-07-18 17:47:23 +00:00
dgp 87a97e0609 [104f2885bb] Rework the "chan" Tcl_ObjType to properly validate cached channel name lookups.
Also merge backlog of test suite & doc improvements.
2016-07-18 16:50:22 +00:00
dgp f5bf1de995 [104f2885bb] Rework the "chan" Tcl_ObjType to properly validate cached channel name lookups. 2016-07-18 16:46:34 +00:00
dgp 6f9ac81ae9 [104f2885bb] Rework the "chan" Tcl_ObjType to properly validate cached
channel name lookups.
2016-07-18 16:26:44 +00:00
dgp c947326c4a merge mark 2016-07-18 16:14:30 +00:00
dkf 9b1a5dc878 [77d58e3a7a] Test case independence: var. 2016-07-17 12:02:27 +00:00
dkf 4bc50a0a12 [77d58e3a7a] Test case independence: unload. 2016-07-17 11:56:28 +00:00
dgp 26532df53f merge 8.6 2016-07-16 20:50:03 +00:00
dkf 0b8d92332a [77d58e3a7a] Test case independence: io, load, msgcat, namespace, safe. 2016-07-16 11:42:38 +00:00
dgp 0cf3369f9f Remove unmaintained disabled speculative code.
Such things are for branches and history.
2016-07-15 14:20:34 +00:00
dgp 8f28138f6e Factor the cmdName intrep setting code into common utility routine. 2016-07-15 14:19:07 +00:00
dgp c0d0df8550 Stop using the tclCmdNameType to store failed command lookups. If we don't
find a command, there's nothing to store, so better not to shimmer at all.
2016-07-15 12:36:33 +00:00
dkf 67a6300cc4 [77d58e3a7a] Test case independence: interp. 2016-07-15 05:39:09 +00:00
ashok fd72878261 Fix docs and test failures. I had rolled back .PS1 (Powershell files) as being executable without fixing tests and docs. 2016-07-15 03:12:09 +00:00
dgp 9df68a3879 One of the validity checks for the "cmdName" type is to see if the
resolved command has been deleted by checking for the CMD_IS_DELETED flag.
Only one thing sets this flag -- Tcl_DeleteCommandFromToken(), and
every time it sets that flag it also bumps the cmdEpoch of the Command
as well.  The "cmdName" type is already validating that epoch.  It gains
nothing to be checking the CMD_IS_DELETED flag too.  Eliminated the 
pointless test.
2016-07-15 02:33:11 +00:00
dgp bd8c790e2e Stop checking case that can never happen. 2016-07-14 17:58:45 +00:00
dgp 5c3b0101a2 Plug memory leak created in recent variable Tcl_ObjType reform. 2016-07-14 15:17:58 +00:00
dgp fed06f2292 New test demonstrates memleak discovered by Rolf Ade. 2016-07-14 14:40:37 +00:00
dkf 2edc274601 [77d58e3a7a] Test case independence: chanio, cmdah, env, history. 2016-07-14 08:31:00 +00:00
dkf f68e18d159 Tidy up some references to INDEX_TEMP_TABLE. 2016-07-14 08:05:35 +00:00
dgp 66a18f91c0 merge 8.6 2016-07-13 19:19:37 +00:00
dgp 4c4629d5fd New private flag value INDEX_TEMP_TABLE.
Used to signal to Tcl_GetIndexFromObj*() routines that the table in which
lookups are done has a fleeting existence.  Thus there is no value in caching
any results, since the cache can never be useful.  Improvement over existing
hackery where cache is stored and then freed to avoid bogus results.
Likely candidate to eventually push to the public interface.
2016-07-13 19:06:22 +00:00
dkf 89796adf9c [3606125] Make parser-related tests work on their own. 2016-07-12 21:30:34 +00:00
dkf 11b61660d2 [3606388] Make variable-related tests work on their own. 2016-07-12 21:25:27 +00:00
dgp d214692a28 tzdata2016f 2016-07-12 16:46:08 +00:00
dgp eec270dc08 Dup test name. Bump to TclOO 1.0.5. 2016-07-12 16:24:35 +00:00
dgp 34d3a97939 merge 8.6 2016-07-12 14:15:48 +00:00
jan.nijtmans 1f93e78598 Fix "file owned" for Cygwin: st_uid is only 16-bit there. 2016-07-12 14:03:36 +00:00
jan.nijtmans c3c52cf7b0 Fix "file owned" for Cygwin: st_uid is only 16-bit there. 2016-07-12 14:02:17 +00:00
jan.nijtmans b11d2bb62d Make hash type changable by compiling with -DTCL_HASH_TYPE=size_t (for example). Default (unsigned) cannot be changed in Tcl 8.x, that must wait until Tcl 9. 2016-07-12 13:44:26 +00:00
dgp 96d7deb99b Start RC branch for Tcl 8.6.6 2016-07-12 13:23:21 +00:00
dgp e0a4741204 merge 8.6 2016-07-11 22:04:02 +00:00
dgp 0ceae7a885 [cea0344a1] Restore a clearing of the ensemble rewrite in one execution path
so attempts to use the data after free are not made.
Test namespace-50.9 demonstrates the need for this.
2016-07-11 21:56:32 +00:00
dgp e19d125606 Avoid memory leak in test. 2016-07-11 17:13:09 +00:00
dgp 9b324cef64 merge 8.6 2016-07-10 19:33:46 +00:00
dgp 68432b7ed1 [96fe2f1cc7] Plug memory leak. 2016-07-10 19:28:57 +00:00
dkf f1f3820560 [3606121] Making tests less cross-dependent. 2016-07-10 14:15:12 +00:00
dkf 363cf0a6f1 Fixes to namespace-old.test 2016-07-10 14:14:28 +00:00
dkf 508b6fc60d Fix to resolver.test 2016-07-10 12:45:34 +00:00
dkf 75f3cb9d07 Fixes to namespace.test 2016-07-10 07:59:52 +00:00
ashok 31ec149e21 Bugfix [da340d4f32]. clock-55.9 and clock-55.10 test failures. 2016-07-10 06:41:54 +00:00
ashok 6076256c3f Fix compiler warnings (const-ness and unused label) that did not show up
in the non-optimized build before last checkin.
2016-07-10 06:33:20 +00:00
dgp 77e9a375ff merge 8.6 2016-07-09 15:47:28 +00:00
ashok 25f7d3b86e Fix missing constraints for Windows-specific tests 2016-07-09 14:30:54 +00:00
dgp 464153fecd Revise INST_INVOKE_REPLACE to call EvalObjv with TCL_EVAL_INVOKE and
no longer call EvalObjEx which does not support it reliably.  Also
convert to conventional list operations.
2016-07-09 14:26:56 +00:00
ashok 139a16f600 Fixed docs for prior check-in (exec of .CMD files on Windows) 2016-07-09 14:23:24 +00:00
ashok 600487a9d6 Bugfix [9ece99d58b]. Make exec understand .CMD files on Windows. 2016-07-09 14:18:22 +00:00
dkf a2962cc586 [1493a43044] Make [namespace upvar] ignore variable resolvers; the previous situation was completely unintuitive. 2016-07-09 13:26:46 +00:00
ashok d6ae741f7f Bugfix [3613671]. file owned implementation for Windows. 2016-07-09 11:13:48 +00:00
ashok 48e3873f19 Bugfix [ae61a67192]. file {stat, type, size} etc. support for built-in special Windows files/devices like CON. 2016-07-09 08:27:00 +00:00
dgp 57a42f683c Repair some memory corruption problems in EnsembleCmdRep. 2016-07-08 14:19:23 +00:00
jan.nijtmans b2e1bb03b1 (cherry-pick): Bugfix [5d7ea04580]. Treat .cmd and .ps1 files are executable on Windows. 2016-07-08 12:38:35 +00:00
jan.nijtmans d8785b8358 Merge core-8-6-branch: Bug [a47641a031]. TclJoinPath was calling TclNewFSPathObj with a first argument that was not an absolute path. Added a check for that. Fixes Windows test failures fileSystem-1.{3,4} 2016-07-08 10:30:07 +00:00
jan.nijtmans 7de7029fa5 Micro-optimization: Use TclGetStringFromObj in stead of Tcl_GetStringFromObj in many places where possible. 2016-07-08 10:28:48 +00:00
ashok 47620e4ba8 Bug [a47641a031]. TclJoinPath was calling TclNewFSPathObj with a
first argument that was not an absolute path. Added a check for that.
Fixes Windows test failures fileSystem-1.{3,4}
2016-07-08 07:58:00 +00:00
dgp f290d19b27 Missed a cleanup line, which created a memleak. 2016-07-07 19:50:02 +00:00
dgp 1446838d71 To use a Tcl_Command token [aka (Command *)] for epoch checking, we must not
permit it to be freed while we hold it or else it could be mistaken for another
token allocated later that just happens to reside at the same address.

(Command *) preservation machinery already exists, just need to use it.

An extension facing the same problem might have to rely on command delete
traces.  

Earlier revisions used (Namespace *) lifetime to achieve the same
results, but that's really an indirect (possibly non-robust) path to achieving
the proper goal.

Valgrind is happy now.
2016-07-07 18:44:56 +00:00
dkf 8c8c1a6415 Expose the AVOID_RESOLVERS flag to [namespace upvar] implementations, which seem to need it. 2016-07-07 10:08:44 +00:00
dkf 07f3d3e393 Also test the interpreted path. 2016-07-07 08:35:30 +00:00
jan.nijtmans 1e5db76cc1 Merge core-8-6-branch:
New tests to demo the remaining flaw in ensemble dispatch revisions. Itcl 4 also demonstrated these
[bd7f17bce8] Revise ensemble dispatch to call TclNREvalObjv() which supports the TCL_EVAL_INVOKE
Simplify all the Tcl_NRPostProc declarations
Create and use a utility Tcl_NRPostProc when decr ref count of values is all that is needed
Bugfix [5d7ea04580]. Treat .cmd and .ps1 files are executable on Windows
2016-07-07 07:48:53 +00:00
ashok 85d1666247 Bugfix [5d7ea04580]. Treat .cmd and .ps1 files are executable on Windows. 2016-07-07 06:30:58 +00:00
dgp bf0a1dc6c5 Create and use a utility Tcl_NRPostProc when decr ref count of values is
all that is needed.
2016-07-06 16:47:37 +00:00
dgp 31e1e2a8c4 Simplify all the Tcl_NRPostProc declarations. 2016-07-06 15:50:34 +00:00
dgp 8f4ed81159 [bd7f17bce8] Revise ensemble dispatch to call TclNREvalObjv() which supports
the TCL_EVAL_INVOKE flag that is needed.
2016-07-06 15:12:53 +00:00
dkf 966906b7ae Demonstrate that there is a problem. 2016-07-05 22:05:16 +00:00
dgp 20e8eaedc8 New tests to demo the remaining flaw in ensemble dispatch revisions.
Itcl 4 also demonstrated these problems.
2016-07-05 17:03:59 +00:00
jan.nijtmans d65776f03f Fixup the ensemble rewrite conversions 2016-07-05 08:55:04 +00:00
jan.nijtmans 7b6eaf23e9 Fixup the ensemble rewrite conversions (merge fork) 2016-07-05 08:53:17 +00:00
dgp bf33e5524b Fixup the ensemble rewrite conversions. 2016-07-04 20:39:43 +00:00
jan.nijtmans 2ee0bbf7fb Use conventional list operations for ensemble dispatch
Add ability to disassemble TclOO constructors and destructors
2016-07-04 08:39:28 +00:00
jan.nijtmans 23c3438aee typo and end-of-line spacing 2016-07-04 08:36:41 +00:00
dkf 21124cf6ab Add ability to disassemble TclOO constructors and destructors ([1493a43044] motivates) 2016-07-04 08:18:53 +00:00
dgp 1694cf05a6 Use conventional list operations for ensemble dispatch. 2016-07-03 14:09:45 +00:00
dgp 8e39be1340 [09fabeb1fd] test subdirs in sorted order. 2016-07-02 17:58:49 +00:00
dgp 4110638cdd [f961d7d1dd] Repair usage message for ensemble parameters with spaces. 2016-07-02 17:57:58 +00:00
dgp 65bd912b77 [09fabeb1fd] test subdirs in sorted order. 2016-07-02 17:55:51 +00:00
dgp dd879c794d [f961d7d1dd] Repair usage message for ensemble parameters with spaces. 2016-07-02 17:21:53 +00:00
dgp e68b3d0183 [4402cfa58c] Rework the spell check machinery into something that will not be foiled by value sharing. 2016-07-01 20:18:47 +00:00
dgp 1481e6f3da [4402cfa58c] Rework the spell check machinery into something that will not be foiled by value sharing.
Valgrind is not happy with this commit.
Likely suspect is the removal of the nsPtr
field and checking against it.

dkf tried to warn me.
2016-07-01 20:14:14 +00:00
dgp 42c2792287 The EnsembleCmdRep struct that is the internal rep for caching ensemble
dispatches and spelling corrections can now be file static.
2016-07-01 19:42:38 +00:00
dgp 08826b79fe merge 8.6 2016-07-01 19:20:36 +00:00
dgp d5617720bb Add some tests 2016-07-01 19:16:56 +00:00
dgp e95143affd [4402cfa58c] Rework the spell check machinery into something that will not be
foiled by value sharing.
2016-07-01 18:54:36 +00:00
jan.nijtmans a67b58390b Make test-case "for.test" pass, regardless of end-of-line spacing 2016-07-01 14:11:38 +00:00
dgp ced0d271ff Encapsulate the fetching of the ensemble rewrite root, used by [namespace]. 2016-07-01 14:08:22 +00:00
jan.nijtmans b6f5ea3c8f merge core-8-6-branch 2016-07-01 13:34:20 +00:00
jan.nijtmans 38e85a2dbe Use same internal representation for unicode strings in test-cases than in reality, in order to prevent surprises. 2016-07-01 13:32:19 +00:00
dgp 680d1a1513 Disable special hacks for Itcl 3 ensemble error message generation.
Migration paths are in place to bring this to an end.
2016-07-01 13:20:37 +00:00
dgp f2718ded6d Use the utility routines to eliminate the last bit of intrusion into the ensembleRewrite area. 2016-07-01 13:07:39 +00:00
dgp 221b47806c merge 8.6 2016-07-01 12:58:37 +00:00
dgp 286034431c Use the utility routines to eliminate the last bit of intrusion into the
ensembleRewrite area.
2016-07-01 12:21:15 +00:00
jan.nijtmans c1ce97106f Simplify use of "struct" keyword in many places. 2016-06-30 13:16:44 +00:00
jan.nijtmans c8212c36e9 Remove Tcl_Main() function, since it's no longer being used: It has been a macro already for ages. 2016-06-29 15:45:26 +00:00
jan.nijtmans 964477ea36 Eliminate internal use of TCL_STORAGE_CLASS, as it will be gone in 9.0 anyway 2016-06-29 15:28:36 +00:00
jan.nijtmans 88fc841203 Tcl_SetVar -> Tcl_SetVar2 and comparable replacements, eliminating functions which are deprecated. 2016-06-29 11:39:00 +00:00
dgp 04633c731b merge 8.6 2016-06-28 22:49:22 +00:00
dgp 75a582f357 Route all ensemble rewrite activity through a few utility routines. 2016-06-28 22:30:18 +00:00
dgp b28ae0fbb5 Route all ensemble rewrite activity through a few utility routines. 2016-06-28 21:17:28 +00:00
dgp 6c2c1397ff merge 8.6 2016-06-28 14:26:11 +00:00
dgp 73124928ba Re-order loop for fewer gotos. 2016-06-27 20:29:46 +00:00
dgp cc2f6f6a7d Stop parsing white space where there cannot be any. 2016-06-27 19:01:34 +00:00
dgp bf285438a2 Streamline comment parsing. 2016-06-27 15:16:04 +00:00
dkf 844c8c3016 [dd260aaf72] Allow the -dictionary option to be read from a pushed transform. 2016-06-27 14:28:33 +00:00
dkf 16dc425318 [dd260aaf72] Allow the -dictionary option to be read from a pushed transform. 2016-06-27 14:27:43 +00:00
dkf 7a41668df0 [c3d956be5b] Clearer text about positioning of optional arguments. 2016-06-27 13:46:15 +00:00
dkf 9c058fa5d4 [c3d956be5b] Clearer text about positioning of optional arguments. 2016-06-27 13:44:40 +00:00
jan.nijtmans 6c2f2fec8a Make TCL_MAJOR_VERSION/TCL_MINOR_VERSION/TCL_STUB_MAGIC available to Tcl_InitStubs() arguments. Useful for debugging and detection of stub incompatibilities (e.g. for Tcl9) 2016-06-27 10:22:30 +00:00
jan.nijtmans 0cb6ad07c6 Add TCL_NOINLINE macro, useful for micro-optimizations 2016-06-26 09:03:08 +00:00
jan.nijtmans ef99853da4 (cherry-pick) [c30087b04f] Install man pages with permissions 644 instead of 444. 2016-06-26 09:01:26 +00:00
jan.nijtmans cb9a441bb9 (cherry-pick) [c30087b04f] Install man pages with permissions 644 instead of 444. 2016-06-26 09:00:06 +00:00
max bf46c5018d [c30087b04f] Install man pages with permissions 644 instead of 444. 2016-06-24 16:40:30 +00:00
dgp 3619c13393 merge 8.6 2016-06-23 13:18:33 +00:00
dkf e577cd8cf8 [d553228d9f] Stop crashes in [dict update] with low refcount dictionaries. 2016-06-23 08:21:42 +00:00
dkf f05e229780 [d553228d9f] Stop crashes in [dict update] with low refcount dictionaries. 2016-06-23 08:20:16 +00:00
dkf ff29c56ea4 [c95b9fc0e3] Make errorcodes out of level parsing more consistent. 2016-06-22 20:58:14 +00:00
dkf 5cae882ff3 [c95b9fc0e3] Make errorcodes out of level parsing more consistent. 2016-06-22 20:57:18 +00:00
dgp 0592038cf9 merge 8.6 2016-06-22 18:57:07 +00:00
dgp 5207d2fe71 [16896d49fd] Tcl_DStrings should tolerate appends to self. 2016-06-22 18:05:46 +00:00
dgp fab681eb11 [16896d49fd] Tcl_DStrings should tolerate appends to self. 2016-06-22 18:04:23 +00:00
dgp 01e94e53ed [16896d49fd] Tcl_DStrings should tolerate appends to self. 2016-06-22 17:38:31 +00:00
dgp 7f038e4db7 Repair earlier bug fix. Stopped crash, but botched the logic for multiple glob patterns. 2016-06-21 11:11:14 +00:00
dgp e5320ae0d5 Repair earlier bug fix. Stopped crash, but botched the logic for multiple
glob patterns.
2016-06-21 11:10:10 +00:00
jan.nijtmans 8290f077d2 Upgrade internal Unicode tables to Unicode 9.0 2016-06-21 09:59:51 +00:00
jan.nijtmans eccf18644f Upgrade internal Unicode tables to Unicode 9.0 2016-06-21 09:58:54 +00:00
jan.nijtmans e4b872fc07 Upgrade internal Unicode tables to Unicode 9.0 2016-06-21 09:57:14 +00:00
dgp df9f4ed74f [c383ebb5e4] Match DStringInit and DStringFree properly. 2016-06-20 19:31:05 +00:00
dgp 8445a00210 [c383ebb5e4] Match DStringInit and DStringFree properly. 2016-06-20 19:23:17 +00:00
dgp 345d7cf628 merge 8.6 2016-06-17 00:53:04 +00:00
dgp b300fecc27 [4b61afd660] Allow [info frame] to record line info for substituted command names. 2016-06-16 17:15:28 +00:00
dgp 482ab2e9dc [4b61afd660] Allow [info frame] to record line info for substituted command names. 2016-06-16 17:15:00 +00:00
dgp 751453253c [4b61afd660] Allow [info frame] to record line info for substituted command names. 2016-06-16 17:12:45 +00:00
dgp 7b7647f1ab [16828b3744] [vwait] *must* successfully undo its variable trace, or else it risks corrupting memory. Namespace teardown complexities were giving the traces an opportunity to survive. Added another (arguably better) Tcl_UntraceVar() call to be sure we avoid this problem. 2016-06-16 17:09:19 +00:00
dgp fa88074963 [16828b3744] [vwait] *must* successfully undo its variable trace, or else
it risks corrupting memory.  Namespace teardown complexities were giving
the traces an opportunity to survive.  Added another (arguably better)
Tcl_UntraceVar() call to be sure we avoid this problem.
2016-06-16 17:06:25 +00:00
dgp d418226edb Improve fix and add test. 2016-06-16 16:59:09 +00:00
dgp bdfafd3539 merge 8.5 2016-06-16 16:41:50 +00:00
dgp 819b87f1df [16828b3744] [vwait] *must* successfully undo its variable trace, or else
it risks corrupting memory.  Namespace teardown complexities were giving
the traces an opportunity to survive.  Added another (arguably better)
Tcl_UntraceVar() call to be sure we avoid this problem.
2016-06-16 16:38:36 +00:00
dgp b36880503c Merge tip of core-8-6-branch 2016-06-16 16:27:01 +00:00
dgp 3c2b67a4d3 Correct the patch. 2016-06-16 16:14:28 +00:00
dgp 08c3a9b76b Merge ec51e0603e. Segfaults again. 2016-06-16 15:25:55 +00:00
dgp dd519c7dac Merge up to a197e6853e. Still works. Next checkin restarts the segfaults. 2016-06-16 15:19:41 +00:00
dgp f67a341fce Merge up to the 8.6.0 release. 2016-06-16 14:48:35 +00:00
dgp c755ef0815 [16828b3744] Prototype fix for merging forward. 2016-06-16 14:23:15 +00:00
jan.nijtmans be577d6027 Fix [7393be0be6e7f91cbb2016fa777896e3895929e3|7393be0be6]: Tcl Thread library doesn't work in Debug build on Windows_x64 2016-06-14 09:58:47 +00:00
jan.nijtmans 99d3f3c9f3 Fix [7393be0be6e7f91cbb2016fa777896e3895929e3|7393be0be6]: Tcl Thread library doesn't work in Debug build on Windows_x64 2016-06-14 09:57:54 +00:00
jan.nijtmans 0b3a8804eb Fix [7393be0be6e7f91cbb2016fa777896e3895929e3|7393be0be6]: Tcl Thread library doesn't work in Debug build on Windows_x64 2016-06-14 09:55:03 +00:00
jan.nijtmans 92a9b04a12 (cherry-pick): Fix [e14c77b845]: Compilation error over typedef. 2016-06-14 09:12:46 +00:00
dgp a4532de5a0 Corrects reported bug, but makes many tests fail. Something subtle about
what we should expect when recording the line of a command that isn't
known until runtime.
2016-06-10 13:43:13 +00:00
jan.nijtmans 710ec0ef20 Fix [e14c77b845] for MSVC6: Compilation error over typedef 2016-06-09 11:41:31 +00:00
jan.nijtmans b4024d86d1 Fix [e14c77b845] for MSVC6: Compilation error over typedef 2016-06-09 11:38:54 +00:00
dgp 58f5175075 merge 8.6 2016-06-03 13:32:04 +00:00
jan.nijtmans 0789d80b7a Fix [e14c77b845]: Compilation error over typedef. 2016-06-02 14:56:20 +00:00
jan.nijtmans 5aee84a3f3 Fix [e14c77b845]: Compilation error over typedef. 2016-06-02 14:54:38 +00:00
jan.nijtmans e52789c557 (cherry-pick) Merge TIP #447: Execution Time Verbosity Levels in tcltest::configure. Tcltest 2.3.8 -> 2.4.0. 2016-06-02 12:27:55 +00:00
jan.nijtmans c0e9c99a1c tcltest 2.3.9 -> 2.4.0 2016-06-02 12:24:28 +00:00
dgp 67cfc8e178 merge 8.6 2016-06-01 18:25:50 +00:00
jan.nijtmans 47115ff565 Fix [3bd69eba99a395ee]: 'make dist' fails when tclsh9.0 is on $PATH 2016-06-01 12:03:50 +00:00
jan.nijtmans dca8fae05f Fix [3bd69eba99a395ee]: 'make dist' fails when tclsh9.0 is on $PATH 2016-06-01 12:02:02 +00:00
jan.nijtmans 5512629c55 Fix [3bd69eba99a395ee]: 'make dist' fails when tclsh9.0 is on $PATH 2016-06-01 11:56:37 +00:00
gahr cb6e9135f2 Merge TIP #447: Execution Time Verbosity Levels in tcltest::configure 2016-06-01 09:55:40 +00:00
dgp af7e16b8e4 excise debug scaffolding 2016-05-26 17:29:34 +00:00
dgp 63e94b434f constructor invocation ensemble rewrite shenanigans also fit into the
refactored routines.
2016-05-26 17:27:56 +00:00
dgp 41a668a515 Reduce to minimum set of TclResetRewriteEnsemble() calls. 2016-05-26 16:33:37 +00:00
andy 20619d8334 Change "integer string" to "integer" in documentation for [tell]. It's not necessary to emphasize EIAS in every man page. The phrase "integer string" dates back to 1999 [ee1e5d143e], previous was "decimal string" which dates back to 1998, in fact the oldest version in Fossil [196f92fd17]. 2016-05-26 02:19:14 +00:00
dgp d0a8ae5cf7 Another missing reset 2016-05-26 00:00:37 +00:00
dgp 7f43feafd5 Put in some missing Resets. 2016-05-25 18:19:27 +00:00
dgp 2b502a4b2b Refactor all iPtr->ensembleRewrite setting code into TclInitRewriteEnsemble()
calls.  This likely fixes many weird corner case bugs, and definitly makes
future development and maintenance easier.
2016-05-25 17:27:49 +00:00
dgp f95100b44a Adapt and tidy up the bug fix. 2016-05-24 20:39:25 +00:00
dgp 0d4e358f5e Merge the bug fix and test case. 2016-05-24 20:29:35 +00:00
dgp 5f7157f3a2 Now fix the bug. 2016-05-24 20:23:15 +00:00
dgp 7cde8a22a1 New test namespace-53.11 demonstrates the bug. 2016-05-24 20:16:10 +00:00
dgp 535895e577 The handling of ensemble rewriting here is not right, but I've not yet
found the test case to demonstrate it.  Checking in debugging code to
spread to other dev platforms.
2016-05-24 19:29:58 +00:00
dgp 366828918a Appears that the TclInitRewriteEnsemble() routine was created with an intent
to refactor, but never actually got used.  Work on continuing that effort.
2016-05-24 19:28:50 +00:00
gahr 7e85a50a46 Merge trunk 2016-05-23 11:40:10 +00:00
dkf 0e5bc322f1 Fix for [f97d4ee020]; use a two-stage approach to avoid quadratic behavior. 2016-05-21 09:30:02 +00:00
dkf 1195cdbd77 Fix for [f97d4ee020]; use a two-stage approach to avoid quadratic behavior. 2016-05-21 09:27:30 +00:00
dkf 5330c4e5d3 Make the tests pass. 2016-05-21 09:26:07 +00:00
dkf 52799e58d6 Added tests that show that this branch isn't ready to be committed back yet. 2016-05-20 05:14:37 +00:00
dgp 46d0e89d6e merge 8.6 2016-05-17 11:45:44 +00:00
dkf c9bd1f3334 Possible fix for [f97d4ee020]; uses a two-stage approach to avoid quadratic behaviour. 2016-05-16 10:57:36 +00:00
dkf 6d990b9c83 Tweak a test to not leave around extra commands. 2016-05-14 06:38:52 +00:00
dgp 84f95a3ef4 merge 8.6 2016-05-13 15:55:44 +00:00
jan.nijtmans 3a20c7912b Merge core-8-6-branch 2016-05-13 09:09:05 +00:00
jan.nijtmans 008944a5c3 result/sendResult could be 64-bit, so account for that 2016-05-13 09:07:43 +00:00
jan.nijtmans e0c7416333 Merge core-8-6-branch. Eliminate some unnecessary spacing. 2016-05-13 08:01:44 +00:00
jan.nijtmans 7a4ad0872e Make tclreg13.dll work in any Unicode environment (either with 32-bit or 64-bit characters). Adopted from Androwish. Thanks to Christian Werner. version -> 1.3.2 2016-05-13 07:49:50 +00:00
Kevin B Kenny 7f12c0adfa Bug fix: Assembler dereferences a rogue pointer when unstacking an empty exception range. 2016-05-13 00:46:23 +00:00
Kevin B Kenny 885379e2cc Bug fix: Assembler dereferences a rogue pointer when unstacking an empty exception range. 2016-05-13 00:45:55 +00:00
dgp 76d0eb32fc Don't see why the intrep should make and keep copies of things already
stored in the hash table.
2016-05-12 20:23:23 +00:00
dgp 76f6131b81 The "ensembleCommand" Tcl_ObjType has no need for an UpdateString routine.
It is entirely a caching type.  No "pure" value can exist.
2016-05-12 19:49:06 +00:00
dgp 1438a1b7f7 Remove the nsPtr field from the EnsembleCmdRep struct. Cannot see any
justification for keeping it (can get via token), and test suite doesn't care.
2016-05-12 19:44:41 +00:00
dgp 5789574f89 Value correctness over performance myths. Encoding ObjType duplication
needs to dup the typePtr so that each Tcl_GetEncoding() is balanced by
a Tcl_FreeEncoding().
2016-05-10 16:52:53 +00:00
dgp f705798ed7 merge trunk 2016-05-10 16:03:13 +00:00
dgp 024bab4116 Bug fix. Have to arrange to only close a catch once. After the space
has been returned to placeholder values, closing with them as data leads
to memory corruption.

There's probably a better fix available because the error here feels like
it's rooted somewhere else, having us continue to check values we ought to
know have already been closed.
2016-05-06 16:03:15 +00:00
gahr 8e26969a34 Add a note in tcltest manual page to betray false expectations on msec and usec. 2016-05-04 12:23:40 +00:00
gahr ee742713d1 Approximate ms by μs/1000 2016-05-03 19:50:15 +00:00
gahr 00f3aef9ac Merge trunk 2016-05-03 19:40:53 +00:00
dgp 54a8b02774 Rework bytecode intialization to serve different callers better. 2016-04-29 19:31:31 +00:00
gahr d243959c21 Bump tcltest version to 2.3.9 2016-04-20 19:37:31 +00:00
gahr dba0cd17dc Implement msec and usec verbosity levels in tcltest::configure 2016-04-20 19:27:31 +00:00
dgp f816bb2a60 The DupEncodingIntRep() routine is broken. It fails to set the typePtr
field of the duplicated Tcl_Obj to indicate that the intrep is that of
the &encodingType.  The impact must be that refcounting of Tcl_Encodings
are out of balance, at least in the (unusual?) case where "encoding" values
need duplication.  I hesitate to actually commit this fix until I have a
test demonstrating the need for it, and a chance to see the impact on
actual encoding operations.  The lifetime management of encodings has a
history of being tricky and raising controversy.  More work required.
2016-03-28 21:24:22 +00:00
265 changed files with 7802 additions and 6225 deletions
+2
View File
@@ -17,8 +17,10 @@
*/tclsh*
*/tcltest*
*/versions.vc
unix/autoMkindex.tcl
unix/dltest.marker
unix/tcl.pc
unix/tclIndex
unix/pkgs/*
win/pkgs/*
win/tcl.hpj
+1 -1
View File
@@ -119,7 +119,7 @@ retrieve the stack trace when script evaluation returns
\fBTCL_ERROR\fR, like so:
.PP
.CS
int code = Tcl_Eval(interp, script);
int code = Tcl_EvalEx(interp, script, -1, 0);
if (code == TCL_ERROR) {
Tcl_Obj *options = \fBTcl_GetReturnOptions\fR(interp, code);
Tcl_Obj *key = Tcl_NewStringObj("-errorinfo", -1);
+23 -8
View File
@@ -51,27 +51,42 @@ in the interpreter's result, and nothing is stored at *\fIintPtr\fR
or *\fIdoublePtr\fR or *\fIboolPtr\fR.
.PP
\fBTcl_GetInt\fR expects \fIsrc\fR to consist of a collection
of integer digits, optionally signed and optionally preceded by
white space. If the first two characters of \fIsrc\fR
of integer digits, optionally signed and optionally preceded and
followed by white space. If the first two characters of \fIsrc\fR
after the optional white space and sign are
.QW 0x
.QW \fB0x\fR
then \fIsrc\fR is expected to be in hexadecimal form; otherwise,
if the first such characters are
.QW \fB0o\fR
then \fIsrc\fR is expected to be in octal form; otherwise,
if the first such characters are
.QW \fB0b\fR
then \fIsrc\fR is expected to be in binary form; otherwise,
if the first such character is
.QW 0
.QW \fB0\fR
then \fIsrc\fR
is expected to be in octal form; otherwise, \fIsrc\fR is
expected to be in decimal form.
.PP
\fBTcl_GetDouble\fR expects \fIsrc\fR to consist of a floating-point
number, which is: white space; a sign; a sequence of digits; a
decimal point; a sequence of digits; the letter
.QW e ;
decimal point
.QW \fB.\fR ;
a sequence of digits; the letter
.QW \fBe\fR ;
a signed decimal exponent; and more white space.
Any of the fields may be omitted, except that
the digits either before or after the decimal point must be present
and if the
.QW e
is present then it must be followed by the exponent number.
.QW \fBe\fR
is present then it must be followed by the exponent number. If there
are no fields apart from the sign and initial sequence of digits
(i.e., no decimal point or exponent indicator), that
initial sequence of digits should take one of the forms that
\fBTcl_GetInt\fR supports, described above. The use of
.QW \fB,\fR
as a decimal point is not supported nor should any other sort of
inter-digit separator be present.
.PP
\fBTcl_GetBoolean\fR expects \fIsrc\fR to specify a boolean
value. If \fIsrc\fR is any of \fB0\fR, \fBfalse\fR,
+1 -1
View File
@@ -281,7 +281,7 @@ The \fIhashKeyProc\fR member contains the address of a function called to
calculate a hash value for the key.
.PP
.CS
typedef unsigned int \fBTcl_HashKeyProc\fR(
typedef TCL_HASH_TYPE \fBTcl_HashKeyProc\fR(
Tcl_HashTable *\fItablePtr\fR,
void *\fIkeyPtr\fR);
.CE
+1 -1
View File
@@ -164,7 +164,7 @@ The source interpreter will have its result reset by this operation.
.SH "DEPRECATED INTERFACES"
.SS "OLD STRING PROCEDURES"
.PP
Use of the following procedures (is deprecated
Use of the following procedures is deprecated
since they manipulate the Tcl result as a string.
Procedures such as \fBTcl_SetObjResult\fR
that manipulate the result as a value
+20 -6
View File
@@ -287,12 +287,14 @@ slow destinations like network sockets.
.RS
.PP
The \fBchan copy\fR command transfers data from \fIinputChan\fR until
end of file or \fIsize\fR bytes have been transferred. If no
\fB\-size\fR argument is given, then the copy goes until end of file.
All the data read from \fIinputChan\fR is copied to \fIoutputChan\fR.
Without the \fB\-command\fR option, \fBchan copy\fR blocks until the
copy is complete and returns the number of bytes written to
\fIoutputChan\fR.
end of file or \fIsize\fR bytes or characters have been transferred;
\fIsize\fR is in bytes if the two channels are using the same encoding,
and is in characters otherwise. If no \fB\-size\fR argument is given,
then the copy goes until end of file. All the data read from
\fIinputChan\fR is copied to \fIoutputChan\fR. Without the
\fB\-command\fR option, \fBchan copy\fR blocks until the copy is
complete and returns the number of bytes or characters (using the same
rules as for the \fB\-size\fR option) written to \fIoutputChan\fR.
.PP
The \fB\-command\fR argument makes \fBchan copy\fR work in the
background. In this case it returns immediately and the
@@ -547,6 +549,18 @@ this, spawn with "2>@" or
">@" redirection operators onto the write side of a pipe, and then
immediately close it in the parent. This is necessary to get an EOF on
the read side once the child has exited or otherwise closed its output.
.RS
.PP
Note that the pipe buffering semantics can vary at the operating system level
substantially; it is not safe to assume that a write performed on the output
side of the pipe will appear instantly to the input side. This is a
fundamental difference and Tcl cannot conceal it. The overall stream semantics
\fIare\fR compatible, so blocking reads and writes will not see most of the
differences, but the details of what exactly gets written when are not. This
is most likely to show up when using pipelines for testing; care should be
taken to ensure that deadlocks do not occur and that potential short reads are
allowed for.
.RE
.VE 8.6
.TP
\fBchan pop \fIchannelId\fR
+1
View File
@@ -20,6 +20,7 @@ This command joins each of its arguments together with spaces after
trimming leading and trailing white-space from each of them. If all of the
arguments are lists, this has the same effect as concatenating them
into a single list.
Arguments that are empty (after trimming) are ignored entirely.
It permits any number of arguments;
if no \fIarg\fRs are supplied, the result is an empty string.
.SH EXAMPLES
+3 -2
View File
@@ -271,8 +271,9 @@ limitation as \fBexec\fR wants to communicate over pipes. The Expect
extension addresses this issue when communicating with a TUI application.
.PP
When attempting to execute an application, \fBexec\fR first searches for
the name as it was specified. Then, in order, \fB.com\fR, \fB.exe\fR, and
\fB.bat\fR are appended to the end of the specified name and it searches
the name as it was specified. Then, in order,
\fB.com\fR, \fB.exe\fR, \fB.bat\fR and \fB.cmd\fR
are appended to the end of the specified name and it searches
for the longer name. If a directory name was not specified as part of the
application name, the following directories are automatically searched in
order when attempting to locate the application:
+171 -214
View File
@@ -17,14 +17,14 @@ expr \- Evaluate an expression
.BE
.SH DESCRIPTION
.PP
Concatenates \fIarg\fRs (adding separator spaces between them),
evaluates the result as a Tcl expression, and returns the value.
The operators permitted in Tcl expressions include a subset of
Concatenates \fIarg\fRs, separated by a space, into an expression, and evaluates
that expression, returning its value.
The operators permitted in an expression include a subset of
the operators permitted in C expressions. For those operators
common to both Tcl and C, Tcl applies the same meaning and precedence
as the corresponding C operators.
Expressions almost always yield numeric results
(integer or floating-point values).
The value of an expression is often a numeric result, either an integer or a
floating-point value, but may also be a non-numeric value.
For example, the expression
.PP
.CS
@@ -32,78 +32,68 @@ For example, the expression
.CE
.PP
evaluates to 14.2.
Tcl expressions differ from C expressions in the way that
operands are specified. Also, Tcl expressions support
non-numeric operands and string comparisons, as well as some
Expressions differ from C expressions in the way that
operands are specified. Expressions also support
non-numeric operands, string comparisons, and some
additional operators not found in C.
.PP
When an expression evaluates to an integer, the value is the decimal form of
the integer, and when an expression evaluates to a floating-point number, the
value is the form produced by the \fB%g\fR format specifier of Tcl's
\fBformat\fR command.
.SS OPERANDS
.PP
A Tcl expression consists of a combination of operands, operators,
parentheses and commas.
White space may be used between the operands and operators and
parentheses (or commas); it is ignored by the expression's instructions.
Where possible, operands are interpreted as integer values.
Integer values may be specified in decimal (the normal case), in binary
(if the first two characters of the operand are \fB0b\fR), in octal
(if the first two characters of the operand are \fB0o\fR), or in hexadecimal
(if the first two characters of the operand are \fB0x\fR). For
compatibility with older Tcl releases, an octal integer value is also
indicated simply when the first character of the operand is \fB0\fR,
whether or not the second character is also \fBo\fR.
If an operand does not have one of the integer formats given
above, then it is treated as a floating-point number if that is
possible. Floating-point numbers may be specified in any of several
common formats making use of the decimal digits, the decimal point \fB.\fR,
the characters \fBe\fR or \fBE\fR indicating scientific notation, and
the sign characters \fB+\fR or \fB\-\fR. For example, all of the
following are valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16.
Also recognized as floating point values are the strings \fBInf\fR
and \fBNaN\fR making use of any case for each character.
If no numeric interpretation is possible (note that all literal
operands that are not numeric or boolean must be quoted with either
braces or with double quotes), then an operand is left as a string
(and only a limited set of operators may be applied to it).
An expression consists of a combination of operands, operators, parentheses and
commas, possibly with whitespace between any of these elements, which is
ignored.
An integer operand may be specified in decimal, binary
(the first two characters are \fB0b\fR), octal
(the first two characters are \fB0o\fR), or hexadecimal
(the first two characters are \fB0x\fR) form. For
compatibility with older Tcl releases, an operand that begins with \fB0\fR is
interpreted as an octal integer even if the second character is not \fBo\fR.
A floating-point number may be specified in any of several
common decimal formats, and may use the decimal point \fB.\fR,
\fBe\fR or \fBE\fR for scientific notation, and
the sign characters \fB+\fR and \fB\-\fR. The
following are all valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16.
The strings \fBInf\fR
and \fBNaN\fR, in any combination of case, are also recognized as floating point
values. An operand that doesn't have a numeric interpretation must be quoted
with either braces or with double quotes.
.PP
Operands may be specified in any of the following ways:
An operand may be specified in any of the following ways:
.IP [1]
As a numeric value, either integer or floating-point.
.IP [2]
As a boolean value, using any form understood by \fBstring is\fR
\fBboolean\fR.
.IP [3]
As a Tcl variable, using standard \fB$\fR notation.
The variable's value will be used as the operand.
As a variable, using standard \fB$\fR notation.
The value of the variable is then the value of the operand.
.IP [4]
As a string enclosed in double-quotes.
The expression parser will perform backslash, variable, and
command substitutions on the information between the quotes,
and use the resulting value as the operand
Backslash, variable, and command substitution are performed as described in
\fBTcl\fR.
.IP [5]
As a string enclosed in braces.
The characters between the open brace and matching close brace
will be used as the operand without any substitutions.
The operand is treated as a braced value as described in \fBTcl\fR.
.IP [6]
As a Tcl command enclosed in brackets.
The command will be executed and its result will be used as
the operand.
Command substitution is performed as described in \fBTcl\fR.
.IP [7]
As a mathematical function whose arguments have any of the above
forms for operands, such as \fBsin($x)\fR. See \fBMATH FUNCTIONS\fR below for
As a mathematical function such as \fBsin($x)\fR, whose arguments have any of the above
forms for operands. See \fBMATH FUNCTIONS\fR below for
a discussion of how mathematical functions are handled.
.PP
Where the above substitutions occur (e.g. inside quoted strings), they
are performed by the expression's instructions.
However, the command parser may already have performed one round of
substitution before the expression processor was called.
As discussed below, it is usually best to enclose expressions
in braces to prevent the command parser from performing substitutions
on the contents.
Because \fBexpr\fR parses and performs substitutions on values that have
already been parsed and substituted by \fBTcl\fR, it is usually best to enclose
expressions in braces to avoid the first round of substitutions by
\fBTcl\fR.
.PP
For some examples of simple expressions, suppose the variable
\fBa\fR has the value 3 and
the variable \fBb\fR has the value 6.
Then the command on the left side of each of the lines below
will produce the value on the right side of the line:
Below are some examples of simple expressions where the value of \fBa\fR is 3
and the value of \fBb\fR is 6. The command on the left side of each line
produces the value on the right side.
.PP
.CS
.ta 6c
@@ -114,34 +104,41 @@ will produce the value on the right side of the line:
.CE
.SS OPERATORS
.PP
The valid operators (most of which are also available as commands in
the \fBtcl::mathop\fR namespace; see the \fBmathop\fR(n) manual page
for details) are listed below, grouped in decreasing order of precedence:
For operators having both a numeric mode and a string mode, the numeric mode is
chosen when all operands have a numeric interpretation. The integer
interpretation of an operand is preferred over the floating-point
interpretation. To ensure string operations on arbitrary values it is generally a
good idea to use \fBeq\fR, \fBne\fR, or the \fBstring\fR command instead of
more versatile operators such as \fB==\fR.
.PP
Unless otherwise specified, operators accept non-numeric operands. The value
of a boolean operation is 1 if true, 0 otherwise. See also \fBstring is\fR
\fBboolean\fR. The valid operators, most of which are also available as
commands in the \fBtcl::mathop\fR namespace (see \fBmathop\fR(n)), are listed
below, grouped in decreasing order of precedence:
.TP 20
\fB\-\0\0+\0\0~\0\0!\fR
.
Unary minus, unary plus, bit-wise NOT, logical NOT. None of these operators
may be applied to string operands, and bit-wise NOT may be
applied only to integers.
Unary minus, unary plus, bit-wise NOT, logical NOT. These operators
may only be applied to numeric operands, and bit-wise NOT may only be
applied to integers.
.TP 20
\fB**\fR
.
Exponentiation. Valid for any numeric operands.
Exponentiation. Valid for numeric operands.
.TP 20
\fB*\0\0/\0\0%\fR
.
Multiply, divide, remainder. None of these operators may be
applied to string operands, and remainder may be applied only
to integers.
The remainder will always have the same sign as the divisor and
an absolute value smaller than the absolute value of the divisor.
Multiply and divide, which are valid for numeric operands, and remainder, which
is valid for integers. The remainder, an absolute value smaller than the
absolute value of the divisor, has the same sign as the divisor.
.RS
.PP
When applied to integers, the division and remainder operators can be
considered to partition the number line into a sequence of equal-sized
adjacent non-overlapping pieces where each piece is the size of the divisor;
the division result identifies which piece the divisor lay within, and the
remainder result identifies where within that piece the divisor lay. A
When applied to integers, division and remainder can be
considered to partition the number line into a sequence of
adjacent non-overlapping pieces, where each piece is the size of the divisor;
the quotient identifies which piece the dividend lies within, and the
remainder identifies where within that piece the dividend lies. A
consequence of this is that the result of
.QW "-57 \fB/\fR 10"
is always -6, and the result of
@@ -151,177 +148,157 @@ is always 3.
.TP 20
\fB+\0\0\-\fR
.
Add and subtract. Valid for any numeric operands.
Add and subtract. Valid for numeric operands.
.TP 20
\fB<<\0\0>>\fR
.
Left and right shift. Valid for integer operands only.
Left and right shift. Valid for integers.
A right shift always propagates the sign bit.
.TP 20
\fB<\0\0>\0\0<=\0\0>=\fR
.
Boolean less, greater, less than or equal, and greater than or equal.
Each operator produces 1 if the condition is true, 0 otherwise.
These operators may be applied to strings as well as numeric operands,
in which case string comparison is used.
Boolean less than, greater than, less than or equal, and greater than or equal.
.TP 20
\fB==\0\0!=\fR
.
Boolean equal and not equal. Each operator produces a zero/one result.
Valid for all operand types.
Boolean equal and not equal.
.TP 20
\fBeq\0\0ne\fR
.
Boolean string equal and string not equal. Each operator produces a
zero/one result. The operand types are interpreted only as strings.
Boolean string equal and string not equal.
.TP 20
\fBin\0\0ni\fR
.
List containment and negated list containment. Each operator produces
a zero/one result and treats its first argument as a string and its
second argument as a Tcl list. The \fBin\fR operator indicates
whether the first argument is a member of the second argument list;
the \fBni\fR operator inverts the sense of the result.
List containment and negated list containment. The first argument is
interpreted as a string, the second as a list. \fBin\fR tests for membership
in the list, and \fBni\fR is the inverse.
.TP 20
\fB&\fR
.
Bit-wise AND. Valid for integer operands only.
Bit-wise AND. Valid for integer operands.
.TP 20
\fB^\fR
.
Bit-wise exclusive OR. Valid for integer operands only.
Bit-wise exclusive OR. Valid for integer operands.
.TP 20
\fB|\fR
.
Bit-wise OR. Valid for integer operands only.
Bit-wise OR. Valid for integer operands.
.TP 20
\fB&&\fR
.
Logical AND. Produces a 1 result if both operands are non-zero,
0 otherwise.
Valid for boolean and numeric (integers or floating-point) operands only.
Logical AND. If both operands are true, the result is 1, or 0 otherwise.
.TP 20
\fB||\fR
.
Logical OR. Produces a 0 result if both operands are zero, 1 otherwise.
Valid for boolean and numeric (integers or floating-point) operands only.
Logical OR. If both operands are false, the result is 0, or 1 otherwise.
.TP 20
\fIx\fB?\fIy\fB:\fIz\fR
.
If-then-else, as in C. If \fIx\fR
evaluates to non-zero, then the result is the value of \fIy\fR.
Otherwise the result is the value of \fIz\fR.
The \fIx\fR operand must have a boolean or numeric value.
If-then-else, as in C. If \fIx\fR is false , the result is the value of
\fIy\fR. Otherwise the result is the value of \fIz\fR.
.PP
See the C manual for more details on the results
produced by each operator.
The exponentiation operator promotes types like the multiply and
divide operators, and produces a result that is the same as the output
of the \fBpow\fR function (after any type conversions.)
All of the binary operators but exponentiation group left-to-right
within the same precedence level; exponentiation groups right-to-left. For example, the command
The exponentiation operator promotes types in the same way that the multiply
and divide operators do, and the result is is the same as the result of
\fBpow\fR.
Exponentiation groups right-to-left within a precedence level. Other binary
operators group left-to-right. For example, the value of
.PP
.CS
\fBexpr\fR {4*2 < 7}
.CE
.PP
returns 0, while
is 0, while the value of
.PP
.CS
\fBexpr\fR {2**3**2}
.CE
.PP
returns 512.
is 512.
.PP
The \fB&&\fR, \fB||\fR, and \fB?:\fR operators have
As in C, \fB&&\fR, \fB||\fR, and \fB?:\fR feature
.QW "lazy evaluation" ,
just as in C, which means that operands are not evaluated if they are
not needed to determine the outcome. For example, in the command
which means that operands are not evaluated if they are
not needed to determine the outcome. For example, in
.PP
.CS
\fBexpr\fR {$v ? [a] : [b]}
.CE
.PP
only one of
.QW \fB[a]\fR
or
.QW \fB[b]\fR
will actually be evaluated,
depending on the value of \fB$v\fR. Note, however, that this is
only true if the entire expression is enclosed in braces; otherwise
the Tcl parser will evaluate both
.QW \fB[a]\fR
and
.QW \fB[b]\fR
before invoking the \fBexpr\fR command.
only one of \fB[a]\fR or \fB[b]\fR is evaluated,
depending on the value of \fB$v\fR. This is not true of the normal Tcl parser,
so it is normally recommended to enclose the arguments to \fBexpr\fR in braces.
Without braces, as in
\fBexpr\fR $v ? [a] : [b]
both \fB[a]\fR and \fB[b]\fR are evaluated before \fBexpr\fR is even called.
.PP
For more details on the results
produced by each operator, see the documentation for C.
.SS "MATH FUNCTIONS"
.PP
When the expression parser encounters a mathematical function
such as \fBsin($x)\fR, it replaces it with a call to an ordinary
Tcl function in the \fBtcl::mathfunc\fR namespace. The processing
of an expression such as:
A mathematical function such as \fBsin($x)\fR is replaced with a call to an ordinary
Tcl command in the \fBtcl::mathfunc\fR namespace. The evaluation
of an expression such as
.PP
.CS
\fBexpr\fR {sin($x+$y)}
.CE
.PP
is the same in every way as the processing of:
is the same in every way as the evaluation of
.PP
.CS
\fBexpr\fR {[tcl::mathfunc::sin [\fBexpr\fR {$x+$y}]]}
.CE
.PP
which in turn is the same as the processing of:
which in turn is the same as the evaluation of
.PP
.CS
tcl::mathfunc::sin [\fBexpr\fR {$x+$y}]
.CE
.PP
The executor will search for \fBtcl::mathfunc::sin\fR using the usual
rules for resolving functions in namespaces. Either
\fB::tcl::mathfunc::sin\fR or \fB[namespace
current]::tcl::mathfunc::sin\fR will satisfy the request, and others
may as well (depending on the current \fBnamespace path\fR setting).
\fBtcl::mathfunc::sin\fR is resolved as described in
\fBNAMESPACE RESOLUTION\fR in the \fBnamespace\fR(n) documentation. Given the
default value of \fBnamespace path\fR, \fB[namespace
current]::tcl::mathfunc::sin\fR or \fB::tcl::mathfunc::sin\fR are the typical
resolutions.
.PP
Some mathematical functions have several arguments, separated by commas like in C. Thus:
As in C, a mathematical function may accept multiple arguments separated by commas. Thus,
.PP
.CS
\fBexpr\fR {hypot($x,$y)}
.CE
.PP
ends up as
becomes
.PP
.CS
tcl::mathfunc::hypot $x $y
.CE
.PP
See the \fBmathfunc\fR(n) manual page for the math functions that are
See the \fBmathfunc\fR(n) documentation for the math functions that are
available by default.
.SS "TYPES, OVERFLOW, AND PRECISION"
.PP
All internal computations involving integers are done calling on the
LibTomMath multiple precision integer library as required so that all
integer calculations are performed exactly. Note that in Tcl releases
prior to 8.5, integer calculations were performed with one of the C types
When needed to guarantee exact performance, internal computations involving
integers use the LibTomMath multiple precision integer library. In Tcl releases
prior to 8.5, integer calculations were performed using one of the C types
\fIlong int\fR or \fITcl_WideInt\fR, causing implicit range truncation
in those calculations where values overflowed the range of those types.
Any code that relied on these implicit truncations will need to explicitly
add \fBint()\fR or \fBwide()\fR function calls to expressions at the points
where such truncation is required to take place.
Any code that relied on these implicit truncations should instead call
\fBint()\fR or \fBwide()\fR, which do truncate.
.PP
All internal computations involving floating-point are
done with the C type \fIdouble\fR.
When converting a string to floating-point, exponent overflow is
Internal floating-point computations are
performed using the \fIdouble\fR C type.
When converting a string to floating-point value, exponent overflow is
detected and results in the \fIdouble\fR value of \fBInf\fR or
\fB\-Inf\fR as appropriate. Floating-point overflow and underflow
are detected to the degree supported by the hardware, which is generally
pretty reliable.
fairly reliable.
.PP
Conversion among internal representations for integer, floating-point,
and string operands is done automatically as needed.
For arithmetic computations, integers are used until some
floating-point number is introduced, after which floating-point is used.
For example,
Conversion among internal representations for integer, floating-point, and
string operands is done automatically as needed. For arithmetic computations,
integers are used until some floating-point number is introduced, after which
floating-point values are used. For example,
.PP
.CS
\fBexpr\fR {5 / 4}
@@ -335,82 +312,62 @@ returns 1, while
.CE
.PP
both return 1.25.
Floating-point values are always returned with a
A floating-point result can be distinguished from an integer result by the
presence of either
.QW \fB.\fR
or an
or
.QW \fBe\fR
so that they will not look like integer values. For example,
.PP
. For example,
.PP
.CS
\fBexpr\fR {20.0/5.0}
.CE
.PP
returns \fB4.0\fR, not \fB4\fR.
.SS "STRING OPERATIONS"
.PP
String values may be used as operands of the comparison operators,
although the expression evaluator tries to do comparisons as integer
or floating-point when it can,
i.e., when all arguments to the operator allow numeric interpretations,
except in the case of the \fBeq\fR and \fBne\fR operators.
If one of the operands of a comparison is a string and the other
has a numeric value, a canonical string representation of the numeric
operand value is generated to compare with the string operand.
Canonical string representation for integer values is a decimal string
format. Canonical string representation for floating-point values
is that produced by the \fB%g\fR format specifier of Tcl's
\fBformat\fR command. For example, the commands
.PP
.CS
\fBexpr\fR {"0x03" > "2"}
\fBexpr\fR {"0y" > "0x12"}
.CE
.PP
both return 1. The first comparison is done using integer
comparison, and the second is done using string comparison.
Because of Tcl's tendency to treat values as numbers whenever
possible, it is not generally a good idea to use operators like \fB==\fR
when you really want string comparison and the values of the
operands could be arbitrary; it is better in these cases to use
the \fBeq\fR or \fBne\fR operators, or the \fBstring\fR command instead.
.SH "PERFORMANCE CONSIDERATIONS"
.PP
Enclose expressions in braces for the best speed and the smallest
storage requirements.
This allows the Tcl bytecode compiler to generate the best code.
.PP
As mentioned above, expressions are substituted twice:
once by the Tcl parser and once by the \fBexpr\fR command.
For example, the commands
Where an expression contains syntax that Tcl would otherwise perform
substitutions on, enclosing an expression in braces or otherwise quoting it
so that it's a static value allows the Tcl compiler to generate bytecode for
the expression, resulting in better speed and smaller storage requirements.
This also avoids issues that can arise if Tcl is allowed to perform
substitution on the value before \fBexpr\fR is called.
.PP
In the following example, the value of the expression is 11 because the Tcl parser first
substitutes \fB$b\fR and \fBexpr\fR then substitutes \fB$a\fR. Enclosing the
expression in braces would result in a syntax error.
.CS
set a 3
set b {$a + 2}
\fBexpr\fR $b*4
.CE
.PP
return 11, not a multiple of 4.
This is because the Tcl parser will first substitute \fB$a + 2\fR for
the variable \fBb\fR,
then the \fBexpr\fR command will evaluate the expression \fB$a + 2*4\fR.
.PP
Most expressions do not require a second round of substitutions.
Either they are enclosed in braces or, if not,
their variable and command substitutions yield numbers or strings
that do not themselves require substitutions.
However, because a few unbraced expressions
need two rounds of substitutions,
the bytecode compiler must emit
additional instructions to handle this situation.
The most expensive code is required for
unbraced expressions that contain command substitutions.
These expressions must be implemented by generating new code
each time the expression is executed.
When the expression is unbraced to allow the substitution of a function or
operator, consider using the commands documented in the \fBmathfunc\fR(n) or
\fBmathop\fR(n) manual pages directly instead.
When an expression is generated at runtime, like the one above is, the bytcode
compiler must ensure that new code is generated each time the expression
is evaluated. This is the most costly kind of expression from a performance
perspective. In such cases, consider directly using the commands described in
the \fBmathfunc\fR(n) or \fBmathop\fR(n) documentation instead of \fBexpr\fR.
Most expressions are not formed at runtime, but are literal strings or contain
substitutions that don't introduce other substitutions. To allow the bytecode
compiler to work with an expression as a string literal at compilation time,
ensure that it contains no substitutions or that it is enclosed in braces or
otherwise quoted to prevent Tcl from performing substitutions, allowing
\fBexpr\fR to perform them instead.
.SH EXAMPLES
.PP
A numeric comparison whose result is 1:
.CS
\fBexpr\fR {"0x03" > "2"}
.CE
.PP
A string comparison whose result is 1:
.CS
\fBexpr\fR {"0y" > "0x12"}
.CE
.PP
Define a procedure that computes an
.QW interesting
mathematical function:
@@ -444,8 +401,8 @@ each other:
puts "a and b are [\fBexpr\fR {$a eq $b ? {equal} : {different}}]"
.CE
.PP
Set a variable to whether an environment variable is both defined at
all and also set to a true boolean value:
Set a variable indicating whether an environment variable is defined and has
value of true:
.PP
.CS
set isTrue [\fBexpr\fR {
+9 -3
View File
@@ -25,12 +25,15 @@ network sockets.
.PP
The \fBfcopy\fR
command transfers data from \fIinchan\fR until end of file
or \fIsize\fR bytes have been
transferred. If no \fB\-size\fR argument is given,
or \fIsize\fR bytes or characters have been
transferred; \fIsize\fR is in bytes if the two channels are using the
same encoding, and is in characters otherwise.
If no \fB\-size\fR argument is given,
then the copy goes until end of file.
All the data read from \fIinchan\fR is copied to \fIoutchan\fR.
Without the \fB\-command\fR option, \fBfcopy\fR blocks until the copy is complete
and returns the number of bytes written to \fIoutchan\fR.
and returns the number of bytes or characters (using the same rules as
for the \fB\-size\fR option) written to \fIoutchan\fR.
.PP
The \fB\-command\fR argument makes \fBfcopy\fR work in the background.
In this case it returns immediately and the \fIcallback\fR is invoked
@@ -174,3 +177,6 @@ vwait done
eof(n), fblocked(n), fconfigure(n), file(n)
.SH KEYWORDS
blocking, channel, end of line, end of file, nonblocking, read, translation
'\" Local Variables:
'\" mode: nroff
'\" End:
+6 -5
View File
@@ -162,7 +162,9 @@ returns \fB/home\fR (or something similar).
\fBfile executable \fIname\fR
.
Returns \fB1\fR if file \fIname\fR is executable by the current user,
\fB0\fR otherwise.
\fB0\fR otherwise. On Windows, which does not have an executable attribute,
the command treats all directories and any files with extensions
\fBexe\fR, \fBcom\fR, \fBcmd\fR or \fBbat\fR as executable.
.TP
\fBfile exists \fIname\fR
.
@@ -482,10 +484,9 @@ not the effective ones.
.TP
\fBWindows\fR\0\0\0\0
.
The \fBfile owned\fR subcommand currently always reports that the current user
is the owner of the file, without regard for what the operating system
believes to be true, making an ownership test useless. This issue (#3613671)
may be fixed in a future release of Tcl.
The \fBfile owned\fR subcommand uses the user identifier (SID) of
the process token, not the thread token which may be impersonating
some other user.
.SH EXAMPLES
.PP
This procedure shows how to search for C files in a given directory
+4 -1
View File
@@ -418,7 +418,10 @@ set token [::http::geturl https://my.secure.site/]
\fB::http::unregister\fR \fIproto\fR
.
This procedure unregisters a protocol handler that was previously
registered via \fB::http::register\fR.
registered via \fB::http::register\fR, returning a two-item list of
the default port and handler command that was previously installed
(via \fB::http::register\fR) if there was such a handler, and an error if
there was no such handler.
.SH ERRORS
The \fB::http::geturl\fR procedure will raise errors in the following cases:
invalid command line options,
+23 -5
View File
@@ -34,8 +34,9 @@ one or two fields. If there is only a single field in the specifier
then it is the name of the argument; if there are two fields, then
the first is the argument name and the second is its default value.
Arguments with default values that are followed by non-defaulted
arguments become required arguments. In 8.6 this will be considered an
error.
arguments become required arguments; enough actual arguments must be
supplied to allow all arguments up to and including the last required
formal argument.
.PP
When \fIname\fR is invoked a local variable
will be created for each of the formal arguments to the procedure; its
@@ -48,11 +49,14 @@ actual arguments for all the
formal arguments that do not have defaults, and there must not be any extra
actual arguments.
Arguments with default values that are followed by non-defaulted
arguments become required arguments (in 8.6 it will be considered an
error).
arguments become de-facto required arguments, though this may change
in a future version of Tcl; portable code should ensure that all
optional arguments come after all required arguments.
.PP
There is one special case to permit procedures with
variable numbers of arguments. If the last formal argument has the name
\fBargs\fR, then a call to the procedure may contain more actual arguments
.QW \fBargs\fR ,
then a call to the procedure may contain more actual arguments
than the procedure has formal arguments. In this case, all of the actual arguments
starting at the one that would be assigned to \fBargs\fR are combined into
a list (as if the \fBlist\fR command had been used); this combined value
@@ -80,6 +84,20 @@ If an error occurs while executing the procedure
body, then the procedure-as-a-whole will return that same error.
.SH EXAMPLES
.PP
This is a procedure that takes two arguments and prints both their sum
and their product. It also returns the string
.QW OK
to the caller as an explicit result.
.PP
.CS
\fBproc\fR printSumProduct {x y} {
set sum [expr {$x + $y}]
set prod [expr {$x * $y}]
puts "sum is $sum, product is $prod"
return "OK"
}
.CE
.PP
This is a procedure that accepts arbitrarily many arguments and prints
them out, one by one.
.PP
+1 -3
View File
@@ -123,9 +123,7 @@ with conversion character \fBu\fR.
.TP
\fBi\fR
.
The input substring must be an integer. The base (i.e. decimal, binary,
octal, or hexadecimal) is determined in the same fashion as described in
\fBexpr\fR. The integer value is stored in the variable,
The input substring must be an integer. The base (i.e. decimal, octal, or hexadecimal) is determined by the C convention (leading 0 for octal; prefix 0x for hexadecimal). The integer value is stored in the variable,
truncated as required by the size modifier value.
.TP
\fBc\fR
+12 -2
View File
@@ -872,8 +872,8 @@ harness are doing.
.
Sets the type of output verbosity desired to \fIlevel\fR,
a list of zero or more of the elements \fBbody\fR, \fBpass\fR,
\fBskip\fR, \fBstart\fR, \fBerror\fR and \fBline\fR. Default value
is
\fBskip\fR, \fBstart\fR, \fBerror\fR, \fBline\fR, \fBmsec\fR and \fBusec\fR.
Default value is
.QW "\fBbody error\fR" .
Levels are defined as:
.RS
@@ -890,6 +890,16 @@ Print errorInfo and errorCode, if they exist, when a test return code
does not match its expected return code
.IP "line (\fBl\fR)"
Print source file line information of failed tests
.IP "msec (\fBm\fR)"
Print each test's execution time in milliseconds
.IP "usec (\fBu\fR)"
Print each test's execution time in microseconds
.PP
Note that the \fBmsec\fR and \fBusec\fR verbosity levels are provided as
indicative measures only. They do not tackle the problem of repeatibility which
should be considered in performance tests or benchmarks. To use these verbosity
levels to thoroughly track performance degradations, consider wrapping your
test bodies with \fBtime\fR commands.
.PP
The single letter abbreviations noted above are also recognized
so that
+1 -1
View File
@@ -16,7 +16,7 @@ tell \- Return current access position for an open channel
.BE
.SH DESCRIPTION
.PP
Returns an integer string giving the current access position in
Returns an integer giving the current access position in
\fIchannelId\fR. This value returned is a byte offset that can be passed to
\fBseek\fR in order to set the channel to a particular position. Note
that this value is in terms of bytes, not characters like \fBread\fR.
+6 -1
View File
@@ -45,7 +45,8 @@ linked to the corresponding namespace variables (and therefore these
variables are listed by \fBinfo vars\fR.)
In this way the \fBvariable\fR command resembles the \fBglobal\fR command,
although the \fBglobal\fR command
only links to variables in the global namespace.
resolves variable names with respect to the global namespace instead
of the current namespace of the procedure.
If any \fIvalue\fRs are given,
they are used to modify the values of the associated namespace variables.
If a namespace variable does not exist,
@@ -98,3 +99,7 @@ namespace eval foo {
global(n), namespace(n), upvar(n)
.SH KEYWORDS
global, namespace, procedure, variable
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:
+12 -6
View File
@@ -174,7 +174,11 @@ to the \fBzlib push\fR command:
.VS "TIP 400"
Sets the compression dictionary to use when working with compressing or
decompressing the data to be \fIbinData\fR. Not valid for transformations that
work with gzip-format data.
work with gzip-format data. The dictionary should consist of strings (byte
sequences) that are likely to be encountered later in the data to be compressed,
with the most commonly used strings preferably put towards the end of the
dictionary. Tcl provides no mechanism for choosing a good such dictionary for
a particular data sequence.
.VE
.TP
\fB\-header\fI dictionary\fR
@@ -207,11 +211,13 @@ compression algorithm depends on what format is being produced or consumed.
.TP
\fB\-dictionary\fI binData\fR
.VS "TIP 400"
This read-write options gets or sets the compression dictionary to use when
working with compressing or decompressing the data to be \fIbinData\fR. It is
not valid for transformations that work with gzip-format data, and should not
normally be set on compressing transformations other than at the point where
the transformation is stacked.
This read-write options gets or sets the initial compression dictionary to use
when working with compressing or decompressing the data to be \fIbinData\fR.
It is not valid for transformations that work with gzip-format data, and should
not normally be set on compressing transformations other than at the point where
the transformation is stacked. Note that this cannot be used to get the
current active compression dictionary mid-stream, as that information is not
exposed by the underlying library.
.VE
.TP
\fB\-flush\fI type\fR
+202 -191
View File
@@ -140,35 +140,36 @@ static const crange alphaRangeTable[] = {
{0x3f7, 0x481}, {0x48a, 0x52f}, {0x531, 0x556}, {0x561, 0x587},
{0x5d0, 0x5ea}, {0x5f0, 0x5f2}, {0x620, 0x64a}, {0x671, 0x6d3},
{0x6fa, 0x6fc}, {0x712, 0x72f}, {0x74d, 0x7a5}, {0x7ca, 0x7ea},
{0x800, 0x815}, {0x840, 0x858}, {0x8a0, 0x8b4}, {0x904, 0x939},
{0x958, 0x961}, {0x971, 0x980}, {0x985, 0x98c}, {0x993, 0x9a8},
{0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9df, 0x9e1}, {0xa05, 0xa0a},
{0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa59, 0xa5c}, {0xa72, 0xa74},
{0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0},
{0xab5, 0xab9}, {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30},
{0xb35, 0xb39}, {0xb5f, 0xb61}, {0xb85, 0xb8a}, {0xb8e, 0xb90},
{0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9}, {0xc05, 0xc0c},
{0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39}, {0xc58, 0xc5a},
{0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3},
{0xcb5, 0xcb9}, {0xd05, 0xd0c}, {0xd0e, 0xd10}, {0xd12, 0xd3a},
{0xd5f, 0xd61}, {0xd7a, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1},
{0xdb3, 0xdbb}, {0xdc0, 0xdc6}, {0xe01, 0xe30}, {0xe40, 0xe46},
{0xe94, 0xe97}, {0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb0},
{0xec0, 0xec4}, {0xedc, 0xedf}, {0xf40, 0xf47}, {0xf49, 0xf6c},
{0xf88, 0xf8c}, {0x1000, 0x102a}, {0x1050, 0x1055}, {0x105a, 0x105d},
{0x106e, 0x1070}, {0x1075, 0x1081}, {0x10a0, 0x10c5}, {0x10d0, 0x10fa},
{0x10fc, 0x1248}, {0x124a, 0x124d}, {0x1250, 0x1256}, {0x125a, 0x125d},
{0x1260, 0x1288}, {0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5},
{0x12b8, 0x12be}, {0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310},
{0x1312, 0x1315}, {0x1318, 0x135a}, {0x1380, 0x138f}, {0x13a0, 0x13f5},
{0x13f8, 0x13fd}, {0x1401, 0x166c}, {0x166f, 0x167f}, {0x1681, 0x169a},
{0x16a0, 0x16ea}, {0x16f1, 0x16f8}, {0x1700, 0x170c}, {0x170e, 0x1711},
{0x1720, 0x1731}, {0x1740, 0x1751}, {0x1760, 0x176c}, {0x176e, 0x1770},
{0x1780, 0x17b3}, {0x1820, 0x1877}, {0x1880, 0x18a8}, {0x18b0, 0x18f5},
{0x1900, 0x191e}, {0x1950, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab},
{0x19b0, 0x19c9}, {0x1a00, 0x1a16}, {0x1a20, 0x1a54}, {0x1b05, 0x1b33},
{0x1b45, 0x1b4b}, {0x1b83, 0x1ba0}, {0x1bba, 0x1be5}, {0x1c00, 0x1c23},
{0x1c4d, 0x1c4f}, {0x1c5a, 0x1c7d}, {0x1ce9, 0x1cec}, {0x1cee, 0x1cf1},
{0x800, 0x815}, {0x840, 0x858}, {0x8a0, 0x8b4}, {0x8b6, 0x8bd},
{0x904, 0x939}, {0x958, 0x961}, {0x971, 0x980}, {0x985, 0x98c},
{0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9df, 0x9e1},
{0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa59, 0xa5c},
{0xa72, 0xa74}, {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8},
{0xaaa, 0xab0}, {0xab5, 0xab9}, {0xb05, 0xb0c}, {0xb13, 0xb28},
{0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb5f, 0xb61}, {0xb85, 0xb8a},
{0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9},
{0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39},
{0xc58, 0xc5a}, {0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8},
{0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xd05, 0xd0c}, {0xd0e, 0xd10},
{0xd12, 0xd3a}, {0xd54, 0xd56}, {0xd5f, 0xd61}, {0xd7a, 0xd7f},
{0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6},
{0xe01, 0xe30}, {0xe40, 0xe46}, {0xe94, 0xe97}, {0xe99, 0xe9f},
{0xea1, 0xea3}, {0xead, 0xeb0}, {0xec0, 0xec4}, {0xedc, 0xedf},
{0xf40, 0xf47}, {0xf49, 0xf6c}, {0xf88, 0xf8c}, {0x1000, 0x102a},
{0x1050, 0x1055}, {0x105a, 0x105d}, {0x106e, 0x1070}, {0x1075, 0x1081},
{0x10a0, 0x10c5}, {0x10d0, 0x10fa}, {0x10fc, 0x1248}, {0x124a, 0x124d},
{0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288}, {0x128a, 0x128d},
{0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c2, 0x12c5},
{0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135a},
{0x1380, 0x138f}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd}, {0x1401, 0x166c},
{0x166f, 0x167f}, {0x1681, 0x169a}, {0x16a0, 0x16ea}, {0x16f1, 0x16f8},
{0x1700, 0x170c}, {0x170e, 0x1711}, {0x1720, 0x1731}, {0x1740, 0x1751},
{0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17b3}, {0x1820, 0x1877},
{0x1880, 0x1884}, {0x1887, 0x18a8}, {0x18b0, 0x18f5}, {0x1900, 0x191e},
{0x1950, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19b0, 0x19c9},
{0x1a00, 0x1a16}, {0x1a20, 0x1a54}, {0x1b05, 0x1b33}, {0x1b45, 0x1b4b},
{0x1b83, 0x1ba0}, {0x1bba, 0x1be5}, {0x1c00, 0x1c23}, {0x1c4d, 0x1c4f},
{0x1c5a, 0x1c7d}, {0x1c80, 0x1c88}, {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},
@@ -183,7 +184,7 @@ static const crange alphaRangeTable[] = {
{0x3131, 0x318e}, {0x31a0, 0x31ba}, {0x31f0, 0x31ff}, {0x3400, 0x4db5},
{0x4e00, 0x9fd5}, {0xa000, 0xa48c}, {0xa4d0, 0xa4fd}, {0xa500, 0xa60c},
{0xa610, 0xa61f}, {0xa640, 0xa66e}, {0xa67f, 0xa69d}, {0xa6a0, 0xa6e5},
{0xa717, 0xa71f}, {0xa722, 0xa788}, {0xa78b, 0xa7ad}, {0xa7b0, 0xa7b7},
{0xa717, 0xa71f}, {0xa722, 0xa788}, {0xa78b, 0xa7ae}, {0xa7b0, 0xa7b7},
{0xa7f7, 0xa801}, {0xa803, 0xa805}, {0xa807, 0xa80a}, {0xa80c, 0xa822},
{0xa840, 0xa873}, {0xa882, 0xa8b3}, {0xa8f2, 0xa8f7}, {0xa90a, 0xa925},
{0xa930, 0xa946}, {0xa960, 0xa97c}, {0xa984, 0xa9b2}, {0xa9e0, 0xa9e4},
@@ -193,6 +194,8 @@ static const crange alphaRangeTable[] = {
{0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e},
{0xab30, 0xab5a}, {0xab5c, 0xab65}, {0xab70, 0xabe2}, {0xac00, 0xd7a3},
{0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xdc00, 0xdc3e}, {0xdc40, 0xdc7e},
{0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe}, {0xdd00, 0xdd3e}, {0xdd40, 0xdd7e},
{0xdd80, 0xddbe}, {0xddc0, 0xddfe}, {0xde00, 0xde3e}, {0xde40, 0xde7e},
{0xde80, 0xdebe}, {0xdec0, 0xdefe}, {0xdf00, 0xdf3e}, {0xdf40, 0xdf7e},
{0xdf80, 0xdfbe}, {0xdfc0, 0xdffe}, {0xf900, 0xfa6d}, {0xfa70, 0xfad9},
{0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1f, 0xfb28}, {0xfb2a, 0xfb36},
@@ -205,36 +208,38 @@ static const crange alphaRangeTable[] = {
{0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10280, 0x1029c}, {0x102a0, 0x102d0},
{0x10300, 0x1031f}, {0x10330, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375},
{0x10380, 0x1039d}, {0x103a0, 0x103c3}, {0x103c8, 0x103cf}, {0x10400, 0x1049d},
{0x10500, 0x10527}, {0x10530, 0x10563}, {0x10600, 0x10736}, {0x10740, 0x10755},
{0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855},
{0x10860, 0x10876}, {0x10880, 0x1089e}, {0x108e0, 0x108f2}, {0x10900, 0x10915},
{0x10920, 0x10939}, {0x10980, 0x109b7}, {0x10a10, 0x10a13}, {0x10a15, 0x10a17},
{0x10a19, 0x10a33}, {0x10a60, 0x10a7c}, {0x10a80, 0x10a9c}, {0x10ac0, 0x10ac7},
{0x10ac9, 0x10ae4}, {0x10b00, 0x10b35}, {0x10b40, 0x10b55}, {0x10b60, 0x10b72},
{0x10b80, 0x10b91}, {0x10c00, 0x10c48}, {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2},
{0x11003, 0x11037}, {0x11083, 0x110af}, {0x110d0, 0x110e8}, {0x11103, 0x11126},
{0x11150, 0x11172}, {0x11183, 0x111b2}, {0x111c1, 0x111c4}, {0x11200, 0x11211},
{0x11213, 0x1122b}, {0x11280, 0x11286}, {0x1128a, 0x1128d}, {0x1128f, 0x1129d},
{0x1129f, 0x112a8}, {0x112b0, 0x112de}, {0x11305, 0x1130c}, {0x11313, 0x11328},
{0x1132a, 0x11330}, {0x11335, 0x11339}, {0x1135d, 0x11361}, {0x11480, 0x114af},
{0x104b0, 0x104d3}, {0x104d8, 0x104fb}, {0x10500, 0x10527}, {0x10530, 0x10563},
{0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805},
{0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10860, 0x10876}, {0x10880, 0x1089e},
{0x108e0, 0x108f2}, {0x10900, 0x10915}, {0x10920, 0x10939}, {0x10980, 0x109b7},
{0x10a10, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33}, {0x10a60, 0x10a7c},
{0x10a80, 0x10a9c}, {0x10ac0, 0x10ac7}, {0x10ac9, 0x10ae4}, {0x10b00, 0x10b35},
{0x10b40, 0x10b55}, {0x10b60, 0x10b72}, {0x10b80, 0x10b91}, {0x10c00, 0x10c48},
{0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x11003, 0x11037}, {0x11083, 0x110af},
{0x110d0, 0x110e8}, {0x11103, 0x11126}, {0x11150, 0x11172}, {0x11183, 0x111b2},
{0x111c1, 0x111c4}, {0x11200, 0x11211}, {0x11213, 0x1122b}, {0x11280, 0x11286},
{0x1128a, 0x1128d}, {0x1128f, 0x1129d}, {0x1129f, 0x112a8}, {0x112b0, 0x112de},
{0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339},
{0x1135d, 0x11361}, {0x11400, 0x11434}, {0x11447, 0x1144a}, {0x11480, 0x114af},
{0x11580, 0x115ae}, {0x115d8, 0x115db}, {0x11600, 0x1162f}, {0x11680, 0x116aa},
{0x11700, 0x11719}, {0x118a0, 0x118df}, {0x11ac0, 0x11af8}, {0x12000, 0x12399},
{0x12480, 0x12543}, {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38},
{0x16a40, 0x16a5e}, {0x16ad0, 0x16aed}, {0x16b00, 0x16b2f}, {0x16b40, 0x16b43},
{0x16b63, 0x16b77}, {0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f},
{0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99},
{0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9},
{0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514},
{0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544},
{0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0}, {0x1d6c2, 0x1d6da},
{0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734}, {0x1d736, 0x1d74e},
{0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8}, {0x1d7aa, 0x1d7c2},
{0x1d7c4, 0x1d7cb}, {0x1e800, 0x1e8c4}, {0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f},
{0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a},
{0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89},
{0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb},
{0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d}, {0x2b820, 0x2cea1},
{0x2f800, 0x2fa1d}
{0x11700, 0x11719}, {0x118a0, 0x118df}, {0x11ac0, 0x11af8}, {0x11c00, 0x11c08},
{0x11c0a, 0x11c2e}, {0x11c72, 0x11c8f}, {0x12000, 0x12399}, {0x12480, 0x12543},
{0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e},
{0x16ad0, 0x16aed}, {0x16b00, 0x16b2f}, {0x16b40, 0x16b43}, {0x16b63, 0x16b77},
{0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f}, {0x17000, 0x187ec},
{0x18800, 0x18af2}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88},
{0x1bc90, 0x1bc99}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
{0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a},
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e},
{0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0},
{0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734},
{0x1d736, 0x1d74e}, {0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8},
{0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7cb}, {0x1e800, 0x1e8c4}, {0x1e900, 0x1e943},
{0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37},
{0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77},
{0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3},
{0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734},
{0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d}
#endif
};
@@ -249,24 +254,24 @@ static const chr alphaCharTable[] = {
0xa39, 0xa5e, 0xab2, 0xab3, 0xabd, 0xad0, 0xae0, 0xae1, 0xaf9,
0xb0f, 0xb10, 0xb32, 0xb33, 0xb3d, 0xb5c, 0xb5d, 0xb71, 0xb83,
0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4, 0xbd0, 0xc3d,
0xc60, 0xc61, 0xcbd, 0xcde, 0xce0, 0xce1, 0xcf1, 0xcf2, 0xd3d,
0xd4e, 0xdbd, 0xe32, 0xe33, 0xe81, 0xe82, 0xe84, 0xe87, 0xe88,
0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xeb2, 0xeb3, 0xebd,
0xec6, 0xf00, 0x103f, 0x1061, 0x1065, 0x1066, 0x108e, 0x10c7, 0x10cd,
0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1bae, 0x1baf, 0x1cf5,
0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f, 0x2102, 0x2107,
0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183, 0x2184, 0x2cf2, 0x2cf3,
0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b, 0x303c, 0xa62a,
0xa62b, 0xa8fb, 0xa8fd, 0xa9cf, 0xaa7a, 0xaab1, 0xaab5, 0xaab6, 0xaac0,
0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44
0xc60, 0xc61, 0xc80, 0xcbd, 0xcde, 0xce0, 0xce1, 0xcf1, 0xcf2,
0xd3d, 0xd4e, 0xdbd, 0xe32, 0xe33, 0xe81, 0xe82, 0xe84, 0xe87,
0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xeb2, 0xeb3,
0xebd, 0xec6, 0xf00, 0x103f, 0x1061, 0x1065, 0x1066, 0x108e, 0x10c7,
0x10cd, 0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1bae, 0x1baf,
0x1cf5, 0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f, 0x2102,
0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183, 0x2184, 0x2cf2,
0x2cf3, 0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b, 0x303c,
0xa62a, 0xa62b, 0xa8fb, 0xa8fd, 0xa9cf, 0xaa7a, 0xaab1, 0xaab5, 0xaab6,
0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44
#if TCL_UTF_MAX > 4
,0x1003c, 0x1003d, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4, 0x108f5, 0x109be,
0x109bf, 0x10a00, 0x11176, 0x111da, 0x111dc, 0x11288, 0x1130f, 0x11310, 0x11332,
0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644, 0x118ff, 0x16f50,
0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546,
0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49,
0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f,
0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e
0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644, 0x118ff, 0x11c40,
0x16f50, 0x16fe0, 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
};
@@ -289,7 +294,7 @@ static const crange controlRangeTable[] = {
#define NUM_CONTROL_RANGE (sizeof(controlRangeTable)/sizeof(crange))
static const chr controlCharTable[] = {
0xad, 0x61c, 0x6dd, 0x70f, 0x180e, 0xfeff
0xad, 0x61c, 0x6dd, 0x70f, 0x8e2, 0x180e, 0xfeff
#if TCL_UTF_MAX > 4
,0x110bd, 0xe0001
#endif
@@ -314,9 +319,10 @@ static const crange digitRangeTable[] = {
{0xff10, 0xff19}
#if TCL_UTF_MAX > 4
,{0x104a0, 0x104a9}, {0x11066, 0x1106f}, {0x110f0, 0x110f9}, {0x11136, 0x1113f},
{0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x114d0, 0x114d9}, {0x11650, 0x11659},
{0x116c0, 0x116c9}, {0x11730, 0x11739}, {0x118e0, 0x118e9}, {0x16a60, 0x16a69},
{0x16b50, 0x16b59}, {0x1d7ce, 0x1d7ff}
{0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x11450, 0x11459}, {0x114d0, 0x114d9},
{0x11650, 0x11659}, {0x116c0, 0x116c9}, {0x11730, 0x11739}, {0x118e0, 0x118e9},
{0x11c50, 0x11c59}, {0x16a60, 0x16a69}, {0x16b50, 0x16b59}, {0x1d7ce, 0x1d7ff},
{0x1e950, 0x1e959}
#endif
};
@@ -339,7 +345,7 @@ 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, 0x2e42},
{0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e44},
{0x3001, 0x3003}, {0x3008, 0x3011}, {0x3014, 0x301f}, {0xa60d, 0xa60f},
{0xa6f2, 0xa6f7}, {0xa874, 0xa877}, {0xa8f8, 0xa8fa}, {0xa9c1, 0xa9cd},
{0xaa5c, 0xaa5f}, {0xfe10, 0xfe19}, {0xfe30, 0xfe52}, {0xfe54, 0xfe61},
@@ -348,9 +354,9 @@ static const crange punctRangeTable[] = {
#if TCL_UTF_MAX > 4
,{0x10100, 0x10102}, {0x10a50, 0x10a58}, {0x10af0, 0x10af6}, {0x10b39, 0x10b3f},
{0x10b99, 0x10b9c}, {0x11047, 0x1104d}, {0x110be, 0x110c1}, {0x11140, 0x11143},
{0x111c5, 0x111c9}, {0x111dd, 0x111df}, {0x11238, 0x1123d}, {0x115c1, 0x115d7},
{0x11641, 0x11643}, {0x1173c, 0x1173e}, {0x12470, 0x12474}, {0x16b37, 0x16b3b},
{0x1da87, 0x1da8b}
{0x111c5, 0x111c9}, {0x111dd, 0x111df}, {0x11238, 0x1123d}, {0x1144b, 0x1144f},
{0x115c1, 0x115d7}, {0x11641, 0x11643}, {0x11660, 0x1166c}, {0x1173c, 0x1173e},
{0x11c41, 0x11c45}, {0x12470, 0x12474}, {0x16b37, 0x16b3b}, {0x1da87, 0x1da8b}
#endif
};
@@ -371,8 +377,8 @@ static const chr punctCharTable[] = {
0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f, 0xff5b, 0xff5d
#if TCL_UTF_MAX > 4
,0x1039f, 0x103d0, 0x1056f, 0x10857, 0x1091f, 0x1093f, 0x10a7f, 0x110bb, 0x110bc,
0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x114c6, 0x16a6e, 0x16a6f, 0x16af5,
0x16b44, 0x1bc9f
0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x1145b, 0x1145d, 0x114c6, 0x11c70,
0x11c71, 0x16a6e, 0x16a6f, 0x16af5, 0x16b44, 0x1bc9f, 0x1e95e, 0x1e95f
#endif
};
@@ -404,24 +410,24 @@ static const crange lowerRangeTable[] = {
{0x199, 0x19b}, {0x1bd, 0x1bf}, {0x233, 0x239}, {0x24f, 0x293},
{0x295, 0x2af}, {0x37b, 0x37d}, {0x3ac, 0x3ce}, {0x3d5, 0x3d7},
{0x3ef, 0x3f3}, {0x430, 0x45f}, {0x561, 0x587}, {0x13f8, 0x13fd},
{0x1d00, 0x1d2b}, {0x1d6b, 0x1d77}, {0x1d79, 0x1d9a}, {0x1e95, 0x1e9d},
{0x1eff, 0x1f07}, {0x1f10, 0x1f15}, {0x1f20, 0x1f27}, {0x1f30, 0x1f37},
{0x1f40, 0x1f45}, {0x1f50, 0x1f57}, {0x1f60, 0x1f67}, {0x1f70, 0x1f7d},
{0x1f80, 0x1f87}, {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7}, {0x1fb0, 0x1fb4},
{0x1fc2, 0x1fc4}, {0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7}, {0x1ff2, 0x1ff4},
{0x2146, 0x2149}, {0x2c30, 0x2c5e}, {0x2c76, 0x2c7b}, {0x2d00, 0x2d25},
{0xa72f, 0xa731}, {0xa771, 0xa778}, {0xa793, 0xa795}, {0xab30, 0xab5a},
{0xab60, 0xab65}, {0xab70, 0xabbf}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17},
{0xff41, 0xff5a}
{0x1c80, 0x1c88}, {0x1d00, 0x1d2b}, {0x1d6b, 0x1d77}, {0x1d79, 0x1d9a},
{0x1e95, 0x1e9d}, {0x1eff, 0x1f07}, {0x1f10, 0x1f15}, {0x1f20, 0x1f27},
{0x1f30, 0x1f37}, {0x1f40, 0x1f45}, {0x1f50, 0x1f57}, {0x1f60, 0x1f67},
{0x1f70, 0x1f7d}, {0x1f80, 0x1f87}, {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7},
{0x1fb0, 0x1fb4}, {0x1fc2, 0x1fc4}, {0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7},
{0x1ff2, 0x1ff4}, {0x2146, 0x2149}, {0x2c30, 0x2c5e}, {0x2c76, 0x2c7b},
{0x2d00, 0x2d25}, {0xa72f, 0xa731}, {0xa771, 0xa778}, {0xa793, 0xa795},
{0xab30, 0xab5a}, {0xab60, 0xab65}, {0xab70, 0xabbf}, {0xfb00, 0xfb06},
{0xfb13, 0xfb17}, {0xff41, 0xff5a}
#if TCL_UTF_MAX > 4
,{0x10428, 0x1044f}, {0x10cc0, 0x10cf2}, {0x118c0, 0x118df}, {0x1d41a, 0x1d433},
{0x1d44e, 0x1d454}, {0x1d456, 0x1d467}, {0x1d482, 0x1d49b}, {0x1d4b6, 0x1d4b9},
{0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf}, {0x1d4ea, 0x1d503}, {0x1d51e, 0x1d537},
{0x1d552, 0x1d56b}, {0x1d586, 0x1d59f}, {0x1d5ba, 0x1d5d3}, {0x1d5ee, 0x1d607},
{0x1d622, 0x1d63b}, {0x1d656, 0x1d66f}, {0x1d68a, 0x1d6a5}, {0x1d6c2, 0x1d6da},
{0x1d6dc, 0x1d6e1}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d71b}, {0x1d736, 0x1d74e},
{0x1d750, 0x1d755}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d78f}, {0x1d7aa, 0x1d7c2},
{0x1d7c4, 0x1d7c9}
,{0x10428, 0x1044f}, {0x104d8, 0x104fb}, {0x10cc0, 0x10cf2}, {0x118c0, 0x118df},
{0x1d41a, 0x1d433}, {0x1d44e, 0x1d454}, {0x1d456, 0x1d467}, {0x1d482, 0x1d49b},
{0x1d4b6, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf}, {0x1d4ea, 0x1d503},
{0x1d51e, 0x1d537}, {0x1d552, 0x1d56b}, {0x1d586, 0x1d59f}, {0x1d5ba, 0x1d5d3},
{0x1d5ee, 0x1d607}, {0x1d622, 0x1d63b}, {0x1d656, 0x1d66f}, {0x1d68a, 0x1d6a5},
{0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6e1}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d71b},
{0x1d736, 0x1d74e}, {0x1d750, 0x1d755}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d78f},
{0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9}, {0x1e922, 0x1e943}
#endif
};
@@ -513,15 +519,15 @@ static const crange upperRangeTable[] = {
{0x1fc8, 0x1fcb}, {0x1fd8, 0x1fdb}, {0x1fe8, 0x1fec}, {0x1ff8, 0x1ffb},
{0x210b, 0x210d}, {0x2110, 0x2112}, {0x2119, 0x211d}, {0x212a, 0x212d},
{0x2130, 0x2133}, {0x2c00, 0x2c2e}, {0x2c62, 0x2c64}, {0x2c6d, 0x2c70},
{0x2c7e, 0x2c80}, {0xa7aa, 0xa7ad}, {0xa7b0, 0xa7b4}, {0xff21, 0xff3a}
{0x2c7e, 0x2c80}, {0xa7aa, 0xa7ae}, {0xa7b0, 0xa7b4}, {0xff21, 0xff3a}
#if TCL_UTF_MAX > 4
,{0x10400, 0x10427}, {0x10c80, 0x10cb2}, {0x118a0, 0x118bf}, {0x1d400, 0x1d419},
{0x1d434, 0x1d44d}, {0x1d468, 0x1d481}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b5},
{0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c},
{0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d56c, 0x1d585},
{0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed}, {0x1d608, 0x1d621}, {0x1d63c, 0x1d655},
{0x1d670, 0x1d689}, {0x1d6a8, 0x1d6c0}, {0x1d6e2, 0x1d6fa}, {0x1d71c, 0x1d734},
{0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8}
,{0x10400, 0x10427}, {0x104b0, 0x104d3}, {0x10c80, 0x10cb2}, {0x118a0, 0x118bf},
{0x1d400, 0x1d419}, {0x1d434, 0x1d44d}, {0x1d468, 0x1d481}, {0x1d4a9, 0x1d4ac},
{0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514},
{0x1d516, 0x1d51c}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550},
{0x1d56c, 0x1d585}, {0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed}, {0x1d608, 0x1d621},
{0x1d63c, 0x1d655}, {0x1d670, 0x1d689}, {0x1d6a8, 0x1d6c0}, {0x1d6e2, 0x1d6fa},
{0x1d71c, 0x1d734}, {0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8}, {0x1e900, 0x1e921}
#endif
};
@@ -610,26 +616,26 @@ static const crange graphRangeTable[] = {
{0x5d0, 0x5ea}, {0x5f0, 0x5f4}, {0x606, 0x61b}, {0x61e, 0x6dc},
{0x6de, 0x70d}, {0x710, 0x74a}, {0x74d, 0x7b1}, {0x7c0, 0x7fa},
{0x800, 0x82d}, {0x830, 0x83e}, {0x840, 0x85b}, {0x8a0, 0x8b4},
{0x8e3, 0x983}, {0x985, 0x98c}, {0x993, 0x9a8}, {0x9aa, 0x9b0},
{0x9b6, 0x9b9}, {0x9bc, 0x9c4}, {0x9cb, 0x9ce}, {0x9df, 0x9e3},
{0x9e6, 0x9fb}, {0xa01, 0xa03}, {0xa05, 0xa0a}, {0xa13, 0xa28},
{0xa2a, 0xa30}, {0xa3e, 0xa42}, {0xa4b, 0xa4d}, {0xa59, 0xa5c},
{0xa66, 0xa75}, {0xa81, 0xa83}, {0xa85, 0xa8d}, {0xa8f, 0xa91},
{0xa93, 0xaa8}, {0xaaa, 0xab0}, {0xab5, 0xab9}, {0xabc, 0xac5},
{0xac7, 0xac9}, {0xacb, 0xacd}, {0xae0, 0xae3}, {0xae6, 0xaf1},
{0xb01, 0xb03}, {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30},
{0xb35, 0xb39}, {0xb3c, 0xb44}, {0xb4b, 0xb4d}, {0xb5f, 0xb63},
{0xb66, 0xb77}, {0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95},
{0xba8, 0xbaa}, {0xbae, 0xbb9}, {0xbbe, 0xbc2}, {0xbc6, 0xbc8},
{0xbca, 0xbcd}, {0xbe6, 0xbfa}, {0xc00, 0xc03}, {0xc05, 0xc0c},
{0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39}, {0xc3d, 0xc44},
{0xc46, 0xc48}, {0xc4a, 0xc4d}, {0xc58, 0xc5a}, {0xc60, 0xc63},
{0xc66, 0xc6f}, {0xc78, 0xc7f}, {0xc81, 0xc83}, {0xc85, 0xc8c},
{0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9},
{0xcbc, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd}, {0xce0, 0xce3},
{0xce6, 0xcef}, {0xd01, 0xd03}, {0xd05, 0xd0c}, {0xd0e, 0xd10},
{0xd12, 0xd3a}, {0xd3d, 0xd44}, {0xd46, 0xd48}, {0xd4a, 0xd4e},
{0xd5f, 0xd63}, {0xd66, 0xd75}, {0xd79, 0xd7f}, {0xd85, 0xd96},
{0x8b6, 0x8bd}, {0x8d4, 0x8e1}, {0x8e3, 0x983}, {0x985, 0x98c},
{0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9bc, 0x9c4},
{0x9cb, 0x9ce}, {0x9df, 0x9e3}, {0x9e6, 0x9fb}, {0xa01, 0xa03},
{0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa3e, 0xa42},
{0xa4b, 0xa4d}, {0xa59, 0xa5c}, {0xa66, 0xa75}, {0xa81, 0xa83},
{0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0},
{0xab5, 0xab9}, {0xabc, 0xac5}, {0xac7, 0xac9}, {0xacb, 0xacd},
{0xae0, 0xae3}, {0xae6, 0xaf1}, {0xb01, 0xb03}, {0xb05, 0xb0c},
{0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb3c, 0xb44},
{0xb4b, 0xb4d}, {0xb5f, 0xb63}, {0xb66, 0xb77}, {0xb85, 0xb8a},
{0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9},
{0xbbe, 0xbc2}, {0xbc6, 0xbc8}, {0xbca, 0xbcd}, {0xbe6, 0xbfa},
{0xc00, 0xc03}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28},
{0xc2a, 0xc39}, {0xc3d, 0xc44}, {0xc46, 0xc48}, {0xc4a, 0xc4d},
{0xc58, 0xc5a}, {0xc60, 0xc63}, {0xc66, 0xc6f}, {0xc78, 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, 0xd4f}, {0xd54, 0xd63}, {0xd66, 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},
@@ -650,25 +656,25 @@ static const crange graphRangeTable[] = {
{0x19de, 0x1a1b}, {0x1a1e, 0x1a5e}, {0x1a60, 0x1a7c}, {0x1a7f, 0x1a89},
{0x1a90, 0x1a99}, {0x1aa0, 0x1aad}, {0x1ab0, 0x1abe}, {0x1b00, 0x1b4b},
{0x1b50, 0x1b7c}, {0x1b80, 0x1bf3}, {0x1bfc, 0x1c37}, {0x1c3b, 0x1c49},
{0x1c4d, 0x1c7f}, {0x1cc0, 0x1cc7}, {0x1cd0, 0x1cf6}, {0x1d00, 0x1df5},
{0x1dfc, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d},
{0x1c4d, 0x1c88}, {0x1cc0, 0x1cc7}, {0x1cd0, 0x1cf6}, {0x1d00, 0x1df5},
{0x1dfb, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d},
{0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fc4},
{0x1fc6, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef}, {0x1ff2, 0x1ff4},
{0x1ff6, 0x1ffe}, {0x2010, 0x2027}, {0x2030, 0x205e}, {0x2074, 0x208e},
{0x2090, 0x209c}, {0x20a0, 0x20be}, {0x20d0, 0x20f0}, {0x2100, 0x218b},
{0x2190, 0x23fa}, {0x2400, 0x2426}, {0x2440, 0x244a}, {0x2460, 0x2b73},
{0x2190, 0x23fe}, {0x2400, 0x2426}, {0x2440, 0x244a}, {0x2460, 0x2b73},
{0x2b76, 0x2b95}, {0x2b98, 0x2bb9}, {0x2bbd, 0x2bc8}, {0x2bca, 0x2bd1},
{0x2bec, 0x2bef}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2cf3},
{0x2cf9, 0x2d25}, {0x2d30, 0x2d67}, {0x2d7f, 0x2d96}, {0x2da0, 0x2da6},
{0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6},
{0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e42},
{0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e44},
{0x2e80, 0x2e99}, {0x2e9b, 0x2ef3}, {0x2f00, 0x2fd5}, {0x2ff0, 0x2ffb},
{0x3001, 0x303f}, {0x3041, 0x3096}, {0x3099, 0x30ff}, {0x3105, 0x312d},
{0x3131, 0x318e}, {0x3190, 0x31ba}, {0x31c0, 0x31e3}, {0x31f0, 0x321e},
{0x3220, 0x32fe}, {0x3300, 0x4db5}, {0x4dc0, 0x9fd5}, {0xa000, 0xa48c},
{0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa6f7}, {0xa700, 0xa7ad},
{0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa6f7}, {0xa700, 0xa7ae},
{0xa7b0, 0xa7b7}, {0xa7f7, 0xa82b}, {0xa830, 0xa839}, {0xa840, 0xa877},
{0xa880, 0xa8c4}, {0xa8ce, 0xa8d9}, {0xa8e0, 0xa8fd}, {0xa900, 0xa953},
{0xa880, 0xa8c5}, {0xa8ce, 0xa8d9}, {0xa8e0, 0xa8fd}, {0xa900, 0xa953},
{0xa95f, 0xa97c}, {0xa980, 0xa9cd}, {0xa9cf, 0xa9d9}, {0xa9de, 0xa9fe},
{0xaa00, 0xaa36}, {0xaa40, 0xaa4d}, {0xaa50, 0xaa59}, {0xaa5c, 0xaac2},
{0xaadb, 0xaaf6}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16},
@@ -687,54 +693,59 @@ static const crange graphRangeTable[] = {
#if TCL_UTF_MAX > 4
,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d},
{0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10100, 0x10102}, {0x10107, 0x10133},
{0x10137, 0x1018c}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c},
{0x10137, 0x1018e}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c},
{0x102a0, 0x102d0}, {0x102e0, 0x102fb}, {0x10300, 0x10323}, {0x10330, 0x1034a},
{0x10350, 0x1037a}, {0x10380, 0x1039d}, {0x1039f, 0x103c3}, {0x103c8, 0x103d5},
{0x10400, 0x1049d}, {0x104a0, 0x104a9}, {0x10500, 0x10527}, {0x10530, 0x10563},
{0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805},
{0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10857, 0x1089e}, {0x108a7, 0x108af},
{0x108e0, 0x108f2}, {0x108fb, 0x1091b}, {0x1091f, 0x10939}, {0x10980, 0x109b7},
{0x109bc, 0x109cf}, {0x109d2, 0x10a03}, {0x10a0c, 0x10a13}, {0x10a15, 0x10a17},
{0x10a19, 0x10a33}, {0x10a38, 0x10a3a}, {0x10a3f, 0x10a47}, {0x10a50, 0x10a58},
{0x10a60, 0x10a9f}, {0x10ac0, 0x10ae6}, {0x10aeb, 0x10af6}, {0x10b00, 0x10b35},
{0x10b39, 0x10b55}, {0x10b58, 0x10b72}, {0x10b78, 0x10b91}, {0x10b99, 0x10b9c},
{0x10ba9, 0x10baf}, {0x10c00, 0x10c48}, {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2},
{0x10cfa, 0x10cff}, {0x10e60, 0x10e7e}, {0x11000, 0x1104d}, {0x11052, 0x1106f},
{0x1107f, 0x110bc}, {0x110be, 0x110c1}, {0x110d0, 0x110e8}, {0x110f0, 0x110f9},
{0x11100, 0x11134}, {0x11136, 0x11143}, {0x11150, 0x11176}, {0x11180, 0x111cd},
{0x111d0, 0x111df}, {0x111e1, 0x111f4}, {0x11200, 0x11211}, {0x11213, 0x1123d},
{0x11280, 0x11286}, {0x1128a, 0x1128d}, {0x1128f, 0x1129d}, {0x1129f, 0x112a9},
{0x112b0, 0x112ea}, {0x112f0, 0x112f9}, {0x11300, 0x11303}, {0x11305, 0x1130c},
{0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339}, {0x1133c, 0x11344},
{0x1134b, 0x1134d}, {0x1135d, 0x11363}, {0x11366, 0x1136c}, {0x11370, 0x11374},
{0x11480, 0x114c7}, {0x114d0, 0x114d9}, {0x11580, 0x115b5}, {0x115b8, 0x115dd},
{0x11600, 0x11644}, {0x11650, 0x11659}, {0x11680, 0x116b7}, {0x116c0, 0x116c9},
{0x10400, 0x1049d}, {0x104a0, 0x104a9}, {0x104b0, 0x104d3}, {0x104d8, 0x104fb},
{0x10500, 0x10527}, {0x10530, 0x10563}, {0x10600, 0x10736}, {0x10740, 0x10755},
{0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855},
{0x10857, 0x1089e}, {0x108a7, 0x108af}, {0x108e0, 0x108f2}, {0x108fb, 0x1091b},
{0x1091f, 0x10939}, {0x10980, 0x109b7}, {0x109bc, 0x109cf}, {0x109d2, 0x10a03},
{0x10a0c, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33}, {0x10a38, 0x10a3a},
{0x10a3f, 0x10a47}, {0x10a50, 0x10a58}, {0x10a60, 0x10a9f}, {0x10ac0, 0x10ae6},
{0x10aeb, 0x10af6}, {0x10b00, 0x10b35}, {0x10b39, 0x10b55}, {0x10b58, 0x10b72},
{0x10b78, 0x10b91}, {0x10b99, 0x10b9c}, {0x10ba9, 0x10baf}, {0x10c00, 0x10c48},
{0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10cfa, 0x10cff}, {0x10e60, 0x10e7e},
{0x11000, 0x1104d}, {0x11052, 0x1106f}, {0x1107f, 0x110bc}, {0x110be, 0x110c1},
{0x110d0, 0x110e8}, {0x110f0, 0x110f9}, {0x11100, 0x11134}, {0x11136, 0x11143},
{0x11150, 0x11176}, {0x11180, 0x111cd}, {0x111d0, 0x111df}, {0x111e1, 0x111f4},
{0x11200, 0x11211}, {0x11213, 0x1123e}, {0x11280, 0x11286}, {0x1128a, 0x1128d},
{0x1128f, 0x1129d}, {0x1129f, 0x112a9}, {0x112b0, 0x112ea}, {0x112f0, 0x112f9},
{0x11300, 0x11303}, {0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330},
{0x11335, 0x11339}, {0x1133c, 0x11344}, {0x1134b, 0x1134d}, {0x1135d, 0x11363},
{0x11366, 0x1136c}, {0x11370, 0x11374}, {0x11400, 0x11459}, {0x11480, 0x114c7},
{0x114d0, 0x114d9}, {0x11580, 0x115b5}, {0x115b8, 0x115dd}, {0x11600, 0x11644},
{0x11650, 0x11659}, {0x11660, 0x1166c}, {0x11680, 0x116b7}, {0x116c0, 0x116c9},
{0x11700, 0x11719}, {0x1171d, 0x1172b}, {0x11730, 0x1173f}, {0x118a0, 0x118f2},
{0x11ac0, 0x11af8}, {0x12000, 0x12399}, {0x12400, 0x1246e}, {0x12470, 0x12474},
{0x12480, 0x12543}, {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38},
{0x16a40, 0x16a5e}, {0x16a60, 0x16a69}, {0x16ad0, 0x16aed}, {0x16af0, 0x16af5},
{0x16b00, 0x16b45}, {0x16b50, 0x16b59}, {0x16b5b, 0x16b61}, {0x16b63, 0x16b77},
{0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f},
{0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99},
{0x1bc9c, 0x1bc9f}, {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126}, {0x1d129, 0x1d172},
{0x1d17b, 0x1d1e8}, {0x1d200, 0x1d245}, {0x1d300, 0x1d356}, {0x1d360, 0x1d371},
{0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9},
{0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514},
{0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544},
{0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb}, {0x1d7ce, 0x1da8b},
{0x1da9b, 0x1da9f}, {0x1daa1, 0x1daaf}, {0x1e800, 0x1e8c4}, {0x1e8c7, 0x1e8d6},
{0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37},
{0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77},
{0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3},
{0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b}, {0x1f030, 0x1f093},
{0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5},
{0x1f100, 0x1f10c}, {0x1f110, 0x1f12e}, {0x1f130, 0x1f16b}, {0x1f170, 0x1f19a},
{0x1f1e6, 0x1f202}, {0x1f210, 0x1f23a}, {0x1f240, 0x1f248}, {0x1f300, 0x1f579},
{0x1f57b, 0x1f5a3}, {0x1f5a5, 0x1f6d0}, {0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6f3},
{0x1f700, 0x1f773}, {0x1f780, 0x1f7d4}, {0x1f800, 0x1f80b}, {0x1f810, 0x1f847},
{0x1f850, 0x1f859}, {0x1f860, 0x1f887}, {0x1f890, 0x1f8ad}, {0x1f910, 0x1f918},
{0x1f980, 0x1f984}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d},
{0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef}
{0x11ac0, 0x11af8}, {0x11c00, 0x11c08}, {0x11c0a, 0x11c36}, {0x11c38, 0x11c45},
{0x11c50, 0x11c6c}, {0x11c70, 0x11c8f}, {0x11c92, 0x11ca7}, {0x11ca9, 0x11cb6},
{0x12000, 0x12399}, {0x12400, 0x1246e}, {0x12470, 0x12474}, {0x12480, 0x12543},
{0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e},
{0x16a60, 0x16a69}, {0x16ad0, 0x16aed}, {0x16af0, 0x16af5}, {0x16b00, 0x16b45},
{0x16b50, 0x16b59}, {0x16b5b, 0x16b61}, {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f},
{0x16f00, 0x16f44}, {0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f}, {0x17000, 0x187ec},
{0x18800, 0x18af2}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88},
{0x1bc90, 0x1bc99}, {0x1bc9c, 0x1bc9f}, {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126},
{0x1d129, 0x1d172}, {0x1d17b, 0x1d1e8}, {0x1d200, 0x1d245}, {0x1d300, 0x1d356},
{0x1d360, 0x1d371}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
{0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a},
{0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e},
{0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb},
{0x1d7ce, 0x1da8b}, {0x1da9b, 0x1da9f}, {0x1daa1, 0x1daaf}, {0x1e000, 0x1e006},
{0x1e008, 0x1e018}, {0x1e01b, 0x1e021}, {0x1e026, 0x1e02a}, {0x1e800, 0x1e8c4},
{0x1e8c7, 0x1e8d6}, {0x1e900, 0x1e94a}, {0x1e950, 0x1e959}, {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, 0x1f1ac}, {0x1f1e6, 0x1f202},
{0x1f210, 0x1f23b}, {0x1f240, 0x1f248}, {0x1f300, 0x1f6d2}, {0x1f6e0, 0x1f6ec},
{0x1f6f0, 0x1f6f6}, {0x1f700, 0x1f773}, {0x1f780, 0x1f7d4}, {0x1f800, 0x1f80b},
{0x1f810, 0x1f847}, {0x1f850, 0x1f859}, {0x1f860, 0x1f887}, {0x1f890, 0x1f8ad},
{0x1f910, 0x1f91e}, {0x1f920, 0x1f927}, {0x1f933, 0x1f93e}, {0x1f940, 0x1f94b},
{0x1f950, 0x1f95e}, {0x1f980, 0x1f991}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734},
{0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef}
#endif
};
@@ -747,20 +758,20 @@ static const chr graphCharTable[] = {
0xad0, 0xaf9, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb47, 0xb48, 0xb56,
0xb57, 0xb5c, 0xb5d, 0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e,
0xb9f, 0xba3, 0xba4, 0xbd0, 0xbd7, 0xc55, 0xc56, 0xcd5, 0xcd6,
0xcde, 0xcf1, 0xcf2, 0xd57, 0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6,
0xe81, 0xe82, 0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7,
0xeaa, 0xeab, 0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773,
0x1940, 0x1cf8, 0x1cf9, 0x1f59, 0x1f5b, 0x1f5d, 0x2070, 0x2071, 0x2d27,
0x2d2d, 0x2d6f, 0x2d70, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc,
0xfffd
0xcde, 0xcf1, 0xcf2, 0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6, 0xe81,
0xe82, 0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa,
0xeab, 0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940,
0x1cf8, 0x1cf9, 0x1f59, 0x1f5b, 0x1f5d, 0x2070, 0x2071, 0x2d27, 0x2d2d,
0x2d6f, 0x2d70, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc, 0xfffd
#if TCL_UTF_MAX > 4
,0x1003c, 0x1003d, 0x101a0, 0x1056f, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4,
0x108f5, 0x1093f, 0x10a05, 0x10a06, 0x11288, 0x1130f, 0x11310, 0x11332, 0x11333,
0x11347, 0x11348, 0x11350, 0x11357, 0x118ff, 0x16a6e, 0x16a6f, 0x1b000, 0x1b001,
0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22,
0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51,
0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62,
0x1ee64, 0x1ee7e, 0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f9c0
0x11347, 0x11348, 0x11350, 0x11357, 0x1145b, 0x1145d, 0x118ff, 0x16a6e, 0x16a6f,
0x16fe0, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb,
0x1d546, 0x1e023, 0x1e024, 0x1e95e, 0x1e95f, 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, 0x1f930, 0x1f9c0
#endif
};
+17 -11
View File
@@ -144,6 +144,7 @@ extern "C" {
#if defined(__GNUC__) && (__GNUC__ > 2)
# define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__printf__, a, b)))
# define TCL_NORETURN __attribute__ ((noreturn))
# define TCL_NOINLINE __attribute__ ((noinline))
# if defined(BUILD_tcl) || defined(BUILD_tk)
# define TCL_NORETURN1 __attribute__ ((noreturn))
# else
@@ -153,8 +154,10 @@ extern "C" {
# define TCL_FORMAT_PRINTF(a,b)
# if defined(_MSC_VER) && (_MSC_VER >= 1310)
# define TCL_NORETURN _declspec(noreturn)
# define TCL_NOINLINE __declspec(noinline)
# else
# define TCL_NORETURN /* nothing */
# define TCL_NOINLINE /* nothing */
# endif
# define TCL_NORETURN1 /* nothing */
#endif
@@ -1154,11 +1157,15 @@ typedef struct Tcl_DString {
* Forward declarations of Tcl_HashTable and related types.
*/
#ifndef TCL_HASH_TYPE
# define TCL_HASH_TYPE unsigned
#endif
typedef struct Tcl_HashKeyType Tcl_HashKeyType;
typedef struct Tcl_HashTable Tcl_HashTable;
typedef struct Tcl_HashEntry Tcl_HashEntry;
typedef unsigned (Tcl_HashKeyProc) (Tcl_HashTable *tablePtr, void *keyPtr);
typedef TCL_HASH_TYPE (Tcl_HashKeyProc) (Tcl_HashTable *tablePtr, void *keyPtr);
typedef int (Tcl_CompareHashKeysProc) (void *keyPtr, Tcl_HashEntry *hPtr);
typedef Tcl_HashEntry * (Tcl_AllocHashEntryProc) (Tcl_HashTable *tablePtr,
void *keyPtr);
@@ -2374,9 +2381,6 @@ typedef int (Tcl_NRPostProc) (ClientData data[], Tcl_Interp *interp,
*----------------------------------------------------------------------------
* The following constant is used to test for older versions of Tcl in the
* stubs tables.
*
* Jan Nijtman's plus patch uses 0xFCA1BACF, so we need to pick a different
* value since the stubs tables don't match.
*/
#define TCL_STUB_MAGIC ((int) 0xFCA3BACF)
@@ -2389,17 +2393,19 @@ typedef int (Tcl_NRPostProc) (ClientData data[], Tcl_Interp *interp,
*/
const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version,
int exact);
int exact, int magic);
const char * TclTomMathInitializeStubs(Tcl_Interp *interp,
const char *version, int epoch, int revision);
/*
* When not using stubs, make it a macro.
*/
#ifndef USE_TCL_STUBS
#ifdef USE_TCL_STUBS
#define Tcl_InitStubs(interp, version, exact) \
Tcl_PkgInitStubsCheck(interp, version, exact)
(Tcl_InitStubs)(interp, version, \
(exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16), \
TCL_STUB_MAGIC)
#else
#define Tcl_InitStubs(interp, version, exact) \
Tcl_PkgInitStubsCheck(interp, version, \
(exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16))
#endif
/*
+12 -10
View File
@@ -1299,8 +1299,8 @@ AssembleOneLine(
if (GetNextOperand(assemEnvPtr, &tokenPtr, &operand1Obj) != TCL_OK) {
goto cleanup;
}
operand1 = Tcl_GetStringFromObj(operand1Obj, &operand1Len);
litIndex = TclRegisterNewLiteral(envPtr, operand1, operand1Len);
operand1 = TclGetStringFromObj(operand1Obj, &operand1Len);
litIndex = TclRegisterLiteral(envPtr, operand1, operand1Len, 0);
BBEmitInst1or4(assemEnvPtr, tblIdx, litIndex, 0);
break;
@@ -1448,8 +1448,8 @@ AssembleOneLine(
&operand1Obj) != TCL_OK) {
goto cleanup;
} else {
operand1 = Tcl_GetStringFromObj(operand1Obj, &operand1Len);
litIndex = TclRegisterNewLiteral(envPtr, operand1, operand1Len);
operand1 = TclGetStringFromObj(operand1Obj, &operand1Len);
litIndex = TclRegisterLiteral(envPtr, operand1, operand1Len, 0);
/*
* Assumes that PUSH is the first slot!
@@ -2288,7 +2288,7 @@ FindLocalVar(
if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &varNameObj) != TCL_OK) {
return -1;
}
varNameStr = Tcl_GetStringFromObj(varNameObj, &varNameLen);
varNameStr = TclGetStringFromObj(varNameObj, &varNameLen);
if (CheckNamespaceQualifiers(interp, varNameStr, varNameLen)) {
Tcl_DecrRefCount(varNameObj);
return -1;
@@ -3541,7 +3541,7 @@ StackCheckExit(
* Emit a 'push' of the empty literal.
*/
litIndex = TclRegisterNewLiteral(envPtr, "", 0);
litIndex = TclRegisterLiteral(envPtr, "", 0, 0);
/*
* Assumes that 'push' is at slot 0 in TalInstructionTable.
@@ -3982,10 +3982,12 @@ UnstackExpiredCatches(
while (catchDepth > bbPtr->catchDepth) {
--catchDepth;
range = envPtr->exceptArrayPtr + catchIndices[catchDepth];
range->numCodeBytes = bbPtr->startOffset - range->codeOffset;
catches[catchDepth] = NULL;
catchIndices[catchDepth] = -1;
if (catches[catchDepth] != NULL) {
range = envPtr->exceptArrayPtr + catchIndices[catchDepth];
range->numCodeBytes = bbPtr->startOffset - range->codeOffset;
catches[catchDepth] = NULL;
catchIndices[catchDepth] = -1;
}
}
/*
+27 -22
View File
@@ -128,7 +128,7 @@ static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected,
int actual, Tcl_Obj *const *objv);
static Tcl_NRPostProc NRCoroutineCallerCallback;
static Tcl_NRPostProc NRCoroutineExitCallback;
static int NRCommand(ClientData data[], Tcl_Interp *interp, int result);
static Tcl_NRPostProc NRCommand;
static Tcl_ObjCmdProc OldMathFuncProc;
static void OldMathFuncDeleteProc(ClientData clientData);
@@ -146,7 +146,6 @@ static int TEOV_RunEnterTraces(Tcl_Interp *interp,
Command **cmdPtrPtr, Tcl_Obj *commandPtr, int objc,
Tcl_Obj *const objv[]);
static Tcl_NRPostProc RewindCoroutineCallback;
static Tcl_NRPostProc TailcallCleanup;
static Tcl_NRPostProc TEOEx_ByteCodeCallback;
static Tcl_NRPostProc TEOEx_ListCallback;
static Tcl_NRPostProc TEOV_Error;
@@ -724,9 +723,7 @@ Tcl_CreateInterp(void)
* Initialize the ensemble error message rewriting support.
*/
iPtr->ensembleRewrite.sourceObjs = NULL;
iPtr->ensembleRewrite.numRemovedObjs = 0;
iPtr->ensembleRewrite.numInsertedObjs = 0;
TclResetRewriteEnsemble(interp, 1);
/*
* TIP#143: Initialise the resource limit support.
@@ -943,8 +940,8 @@ Tcl_CreateInterp(void)
* Set up other variables such as tcl_version and tcl_library
*/
Tcl_SetVar(interp, "tcl_patchLevel", TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);
Tcl_SetVar(interp, "tcl_version", TCL_VERSION, TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "tcl_patchLevel", NULL, TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "tcl_version", NULL, TCL_VERSION, TCL_GLOBAL_ONLY);
Tcl_TraceVar2(interp, "tcl_precision", NULL,
TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
TclPrecTraceProc, NULL);
@@ -3946,7 +3943,7 @@ Tcl_Canceled(
*/
if (iPtr->asyncCancelMsg != NULL) {
message = Tcl_GetStringFromObj(iPtr->asyncCancelMsg, &length);
message = TclGetStringFromObj(iPtr->asyncCancelMsg, &length);
} else {
length = 0;
}
@@ -4045,7 +4042,7 @@ Tcl_CancelEval(
*/
if (resultObjPtr != NULL) {
result = Tcl_GetStringFromObj(resultObjPtr, &cancelInfo->length);
result = TclGetStringFromObj(resultObjPtr, &cancelInfo->length);
cancelInfo->result = ckrealloc(cancelInfo->result,cancelInfo->length);
memcpy(cancelInfo->result, result, (size_t) cancelInfo->length);
TclDecrRefCount(resultObjPtr); /* Discard their result object. */
@@ -4221,7 +4218,7 @@ EvalObjvCore(
* TCL_EVAL_INVOKE was not set: clear rewrite rules
*/
iPtr->ensembleRewrite.sourceObjs = NULL;
TclResetRewriteEnsemble(interp, 1);
if (flags & TCL_EVAL_GLOBAL) {
TEOV_SwitchVarFrame(interp);
@@ -4557,7 +4554,7 @@ TEOV_Error(
*/
listPtr = Tcl_NewListObj(objc, objv);
cmdString = Tcl_GetStringFromObj(listPtr, &cmdLen);
cmdString = TclGetStringFromObj(listPtr, &cmdLen);
Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen);
Tcl_DecrRefCount(listPtr);
}
@@ -4703,7 +4700,7 @@ TEOV_RunEnterTraces(
Command *cmdPtr = *cmdPtrPtr;
int newEpoch, cmdEpoch = cmdPtr->cmdEpoch;
int length, traceCode = TCL_OK;
const char *command = Tcl_GetStringFromObj(commandPtr, &length);
const char *command = TclGetStringFromObj(commandPtr, &length);
/*
* Call trace functions.
@@ -4755,7 +4752,7 @@ TEOV_RunLeaveTraces(
Command *cmdPtr = data[2];
Tcl_Obj **objv = data[3];
int length;
const char *command = Tcl_GetStringFromObj(commandPtr, &length);
const char *command = TclGetStringFromObj(commandPtr, &length);
if (!(cmdPtr->flags & CMD_IS_DELETED)) {
if (cmdPtr->flags & CMD_HAS_EXEC_TRACES){
@@ -6120,7 +6117,7 @@ TclNREvalObjEx(
Tcl_IncrRefCount(objPtr);
script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
script = TclGetStringFromObj(objPtr, &numSrcBytes);
result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
TclDecrRefCount(objPtr);
@@ -6151,7 +6148,7 @@ TEOEx_ByteCodeCallback(
ProcessUnexpectedResult(interp, result);
result = TCL_ERROR;
script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
script = TclGetStringFromObj(objPtr, &numSrcBytes);
Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
}
@@ -6850,7 +6847,7 @@ Tcl_VarEvalVA(
Tcl_DStringAppend(&buf, string, -1);
}
result = Tcl_Eval(interp, Tcl_DStringValue(&buf));
result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
Tcl_DStringFree(&buf);
return result;
}
@@ -6920,7 +6917,7 @@ Tcl_GlobalEval(
savedVarFramePtr = iPtr->varFramePtr;
iPtr->varFramePtr = iPtr->rootFramePtr;
result = Tcl_Eval(interp, command);
result = Tcl_EvalEx(interp, command, -1, 0);
iPtr->varFramePtr = savedVarFramePtr;
return result;
}
@@ -8374,7 +8371,7 @@ TclNRTailcallEval(
* a now-gone namespace: cleanup and return.
*/
TailcallCleanup(data, interp, result);
Tcl_DecrRefCount(listPtr);
return result;
}
@@ -8383,18 +8380,26 @@ TclNRTailcallEval(
*/
TclMarkTailcall(interp);
TclNRAddCallback(interp, TailcallCleanup, listPtr, NULL, NULL,NULL);
TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL);
iPtr->lookupNsPtr = (Namespace *) nsPtr;
return TclNREvalObjv(interp, objc-1, objv+1, 0, NULL);
}
static int
TailcallCleanup(
int
TclNRReleaseValues(
ClientData data[],
Tcl_Interp *interp,
int result)
{
Tcl_DecrRefCount((Tcl_Obj *) data[0]);
int i = 0;
while (i < 4) {
if (data[i]) {
Tcl_DecrRefCount((Tcl_Obj *) data[i]);
} else {
break;
}
i++;
}
return result;
}
+1 -1
View File
@@ -2500,7 +2500,7 @@ BinaryEncode64(
}
break;
case OPT_WRAPCHAR:
wrapchar = Tcl_GetStringFromObj(objv[i+1], &wrapcharlen);
wrapchar = TclGetStringFromObj(objv[i+1], &wrapcharlen);
if (wrapcharlen == 0) {
maxlen = 0;
}
+12
View File
@@ -1499,7 +1499,19 @@ GetJulianDayFromEraYearMonthDay(
* Try an initial conversion in the Gregorian calendar.
*/
#if 0 /* BUG http://core.tcl.tk/tcl/tktview?name=da340d4f32 */
ym1o4 = ym1 / 4;
#else
/*
* Have to make sure quotient is truncated towards 0 when negative.
* See above bug for details. The casts are necessary.
*/
if (ym1 >= 0)
ym1o4 = ym1 / 4;
else {
ym1o4 = - (int) (((unsigned int) -ym1) / 4);
}
#endif
if (ym1 % 4 < 0) {
ym1o4--;
}
+31 -12
View File
@@ -12,6 +12,9 @@
*/
#include "tclInt.h"
#ifdef _WIN32
# include "tclWinInt.h"
#endif
#include <locale.h>
/*
@@ -1157,6 +1160,16 @@ FileAttrAccessTimeCmd(
if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) {
return TCL_ERROR;
}
#if defined(_WIN32)
/* We use a value of 0 to indicate the access time not available */
if (buf.st_atime == 0) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"could not get access time for file \"%s\"",
TclGetString(objv[1])));
return TCL_ERROR;
}
#endif
if (objc == 3) {
/*
* Need separate variable for reading longs from an object on 64-bit
@@ -1229,6 +1242,15 @@ FileAttrModifyTimeCmd(
if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) {
return TCL_ERROR;
}
#if defined(_WIN32)
/* We use a value of 0 to indicate the modification time not available */
if (buf.st_mtime == 0) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"could not get modification time for file \"%s\"",
TclGetString(objv[1])));
return TCL_ERROR;
}
#endif
if (objc == 3) {
/*
* Need separate variable for reading longs from an object on 64-bit
@@ -1574,28 +1596,25 @@ FileAttrIsOwnedCmd(
int objc,
Tcl_Obj *const objv[])
{
#ifdef __CYGWIN__
#define geteuid() (short)(geteuid)()
#endif
#if !defined(_WIN32)
Tcl_StatBuf buf;
#endif
int value = 0;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "name");
return TCL_ERROR;
}
if (GetStatBuf(NULL, objv[1], Tcl_FSStat, &buf) == TCL_OK) {
/*
* For Windows, there are no user ids associated with a file, so we
* always return 1.
*
* TODO: use GetSecurityInfo to get the real owner of the file and
* test for equivalence to the current user.
*/
#if defined(_WIN32) || defined(__CYGWIN__)
value = 1;
#if defined(_WIN32)
value = TclWinFileOwned(objv[1]);
#else
if (GetStatBuf(NULL, objv[1], Tcl_FSStat, &buf) == TCL_OK) {
value = (geteuid() == buf.st_uid);
#endif
}
#endif
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
return TCL_OK;
}
+42 -15
View File
@@ -105,8 +105,7 @@ typedef struct SortInfo {
*/
static int DictionaryCompare(const char *left, const char *right);
static int IfConditionCallback(ClientData data[],
Tcl_Interp *interp, int result);
static Tcl_NRPostProc IfConditionCallback;
static int InfoArgsCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
static int InfoBodyCmd(ClientData dummy, Tcl_Interp *interp,
@@ -1203,7 +1202,7 @@ InfoFrameCmd(
levelError:
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad level \"%s\"", TclGetString(objv[1])));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "STACK_FRAME",
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL",
TclGetString(objv[1]), NULL);
code = TCL_ERROR;
goto done;
@@ -1638,7 +1637,7 @@ InfoLevelCmd(
levelError:
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad level \"%s\"", TclGetString(objv[1])));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "STACK_LEVEL",
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL",
TclGetString(objv[1]), NULL);
return TCL_ERROR;
}
@@ -1678,7 +1677,7 @@ InfoLibraryCmd(
return TCL_ERROR;
}
libDirName = Tcl_GetVar(interp, "tcl_library", TCL_GLOBAL_ONLY);
libDirName = Tcl_GetVar2(interp, "tcl_library", NULL, TCL_GLOBAL_ONLY);
if (libDirName != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(libDirName, -1));
return TCL_OK;
@@ -1804,7 +1803,7 @@ InfoPatchLevelCmd(
return TCL_ERROR;
}
patchlevel = Tcl_GetVar(interp, "tcl_patchLevel",
patchlevel = Tcl_GetVar2(interp, "tcl_patchLevel", NULL,
(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
if (patchlevel != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(patchlevel, -1));
@@ -2156,8 +2155,8 @@ Tcl_JoinObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* The argument objects. */
{
int listLen, i;
Tcl_Obj *resObjPtr, *joinObjPtr, **elemPtrs;
int listLen;
Tcl_Obj *resObjPtr = NULL, *joinObjPtr, **elemPtrs;
if ((objc < 2) || (objc > 3)) {
Tcl_WrongNumArgs(interp, 1, objv, "list ?joinString?");
@@ -2174,19 +2173,47 @@ Tcl_JoinObjCmd(
return TCL_ERROR;
}
if (listLen == 0) {
/* No elements to join; default empty result is correct. */
return TCL_OK;
}
if (listLen == 1) {
/* One element; return it */
Tcl_SetObjResult(interp, elemPtrs[0]);
return TCL_OK;
}
joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2];
Tcl_IncrRefCount(joinObjPtr);
resObjPtr = Tcl_NewObj();
for (i = 0; i < listLen; i++) {
if (i > 0) {
Tcl_AppendObjToObj(resObjPtr, joinObjPtr);
if (Tcl_GetCharLength(joinObjPtr) == 0) {
TclStringCatObjv(interp, /* inPlace */ 0, listLen, elemPtrs,
&resObjPtr);
} else {
int i;
resObjPtr = Tcl_NewObj();
for (i = 0; i < listLen; i++) {
if (i > 0) {
/*
* NOTE: This code is relying on Tcl_AppendObjToObj() **NOT**
* to shimmer joinObjPtr. If it did, then the case where
* objv[1] and objv[2] are the same value would not be safe.
* Accessing elemPtrs would crash.
*/
Tcl_AppendObjToObj(resObjPtr, joinObjPtr);
}
Tcl_AppendObjToObj(resObjPtr, elemPtrs[i]);
}
Tcl_AppendObjToObj(resObjPtr, elemPtrs[i]);
}
Tcl_DecrRefCount(joinObjPtr);
Tcl_SetObjResult(interp, resObjPtr);
return TCL_OK;
if (resObjPtr) {
Tcl_SetObjResult(interp, resObjPtr);
return TCL_OK;
}
return TCL_ERROR;
}
/*
+24 -88
View File
@@ -22,14 +22,10 @@
static inline Tcl_Obj * During(Tcl_Interp *interp, int resultCode,
Tcl_Obj *oldOptions, Tcl_Obj *errorInfo);
static int SwitchPostProc(ClientData data[], Tcl_Interp *interp,
int result);
static int TryPostBody(ClientData data[], Tcl_Interp *interp,
int result);
static int TryPostFinal(ClientData data[], Tcl_Interp *interp,
int result);
static int TryPostHandler(ClientData data[], Tcl_Interp *interp,
int result);
static Tcl_NRPostProc SwitchPostProc;
static Tcl_NRPostProc TryPostBody;
static Tcl_NRPostProc TryPostFinal;
static Tcl_NRPostProc TryPostHandler;
static int UniCharIsAscii(int character);
static int UniCharIsHexDigit(int character);
@@ -1180,8 +1176,7 @@ StringFirstCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_UniChar *needleStr, *haystackStr;
int match, start, needleLen, haystackLen;
int start = 0;
if (objc < 3 || objc > 4) {
Tcl_WrongNumArgs(interp, 1, objv,
@@ -1189,82 +1184,23 @@ StringFirstCmd(
return TCL_ERROR;
}
/*
* We are searching haystackStr for the sequence needleStr.
*/
match = -1;
start = 0;
haystackLen = -1;
needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen);
haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen);
if (objc == 4) {
/*
* If a startIndex is specified, we will need to fast forward to that
* point in the string before we think about a match.
*/
int size = Tcl_GetCharLength(objv[2]);
if (TclGetIntForIndexM(interp, objv[3], haystackLen-1,
&start) != TCL_OK){
if (TCL_OK != TclGetIntForIndexM(interp, objv[3], size - 1, &start)) {
return TCL_ERROR;
}
/*
* Reread to prevent shimmering problems.
*/
needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen);
haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen);
if (start >= haystackLen) {
goto str_first_done;
} else if (start > 0) {
haystackStr += start;
haystackLen -= start;
} else if (start < 0) {
/*
* Invalid start index mapped to string start; Bug #423581
*/
if (start < 0) {
start = 0;
}
}
/*
* If the length of the needle is more than the length of the haystack, it
* cannot be contained in there so we can avoid searching. [Bug 2960021]
*/
if (needleLen > 0 && needleLen <= haystackLen) {
register Tcl_UniChar *p, *end;
end = haystackStr + haystackLen - needleLen + 1;
for (p = haystackStr; p < end; p++) {
/*
* Scan forward to find the first character.
*/
if ((*p == *needleStr) && (TclUniCharNcmp(needleStr, p,
(unsigned long) needleLen) == 0)) {
match = p - haystackStr;
break;
}
if (start >= size) {
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
return TCL_OK;
}
}
/*
* Compute the character index of the matching string by counting the
* number of characters before the match.
*/
if ((match != -1) && (objc == 4)) {
match += start;
}
str_first_done:
Tcl_SetObjResult(interp, Tcl_NewIntObj(match));
Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringFind(objv[1],
objv[2], start)));
return TCL_OK;
}
@@ -1877,7 +1813,7 @@ StringMapCmd(
/*
* This test is tricky, but has to be that way or you get other strange
* inconsistencies (see test string-10.20 for illustration why!)
* inconsistencies (see test string-10.20.1 for illustration why!)
*/
if (objv[objc-2]->typePtr == &tclDictType && objv[objc-2]->bytes == NULL){
@@ -2859,7 +2795,7 @@ StringCatCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
int i;
int code;
Tcl_Obj *objResultPtr;
if (objc < 2) {
@@ -2876,16 +2812,16 @@ StringCatCmd(
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;
code = TclStringCatObjv(interp, /* inPlace */ 1, objc-1, objv+1,
&objResultPtr);
if (code == TCL_OK) {
Tcl_SetObjResult(interp, objResultPtr);
return TCL_OK;
}
return code;
}
/*
+6 -17
View File
@@ -801,7 +801,7 @@ TclCompileConcatCmd(
Tcl_ListObjGetElements(NULL, listObj, &len, &objs);
objPtr = Tcl_ConcatObj(len, objs);
Tcl_DecrRefCount(listObj);
bytes = Tcl_GetStringFromObj(objPtr, &len);
bytes = TclGetStringFromObj(objPtr, &len);
PushLiteral(envPtr, bytes, len);
Tcl_DecrRefCount(objPtr);
return TCL_OK;
@@ -1209,7 +1209,7 @@ TclCompileDictCreateCmd(
* We did! Excellent. The "verifyDict" is to do type forcing.
*/
bytes = Tcl_GetStringFromObj(dictObj, &len);
bytes = TclGetStringFromObj(dictObj, &len);
PushLiteral(envPtr, bytes, len);
TclEmitOpcode( INST_DUP, envPtr);
TclEmitOpcode( INST_DICT_VERIFY, envPtr);
@@ -2650,7 +2650,7 @@ CompileEachloopCmd(
int numBytes, varIndex;
Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj);
bytes = Tcl_GetStringFromObj(varNameObj, &numBytes);
bytes = TclGetStringFromObj(varNameObj, &numBytes);
varIndex = LocalScalar(bytes, numBytes, envPtr);
if (varIndex < 0) {
code = TCL_ERROR;
@@ -3087,7 +3087,7 @@ TclCompileFormatCmd(
* literal. Job done.
*/
bytes = Tcl_GetStringFromObj(tmpObj, &len);
bytes = TclGetStringFromObj(tmpObj, &len);
PushLiteral(envPtr, bytes, len);
Tcl_DecrRefCount(tmpObj);
return TCL_OK;
@@ -3158,7 +3158,7 @@ TclCompileFormatCmd(
if (*++bytes == '%') {
Tcl_AppendToObj(tmpObj, "%", 1);
} else {
char *b = Tcl_GetStringFromObj(tmpObj, &len);
char *b = TclGetStringFromObj(tmpObj, &len);
/*
* If there is a non-empty literal from the format string,
@@ -3192,7 +3192,7 @@ TclCompileFormatCmd(
*/
Tcl_AppendToObj(tmpObj, start, bytes - start);
bytes = Tcl_GetStringFromObj(tmpObj, &len);
bytes = TclGetStringFromObj(tmpObj, &len);
if (len > 0) {
PushLiteral(envPtr, bytes, len);
i++;
@@ -3206,17 +3206,6 @@ TclCompileFormatCmd(
*/
TclEmitInstInt1(INST_STR_CONCAT1, i, envPtr);
} else {
/*
* EVIL HACK! Force there to be a string representation in the case
* where there's just a "%s" in the format; case covered by the test
* format-20.1 (and it is horrible...)
*/
TclEmitOpcode(INST_DUP, envPtr);
PushStringLiteral(envPtr, "");
TclEmitOpcode(INST_STR_EQ, envPtr);
TclEmitOpcode(INST_POP, envPtr);
}
return TCL_OK;
}
+3 -3
View File
@@ -2451,7 +2451,7 @@ TclCompileRegsubCmd(
* replacement "simple"?
*/
bytes = Tcl_GetStringFromObj(patternObj, &len);
bytes = TclGetStringFromObj(patternObj, &len);
if (TclReToGlob(NULL, bytes, len, &pattern, &exact, &quantified)
!= TCL_OK || exact || quantified) {
goto done;
@@ -2499,7 +2499,7 @@ TclCompileRegsubCmd(
result = TCL_OK;
bytes = Tcl_DStringValue(&pattern) + 1;
PushLiteral(envPtr, bytes, len);
bytes = Tcl_GetStringFromObj(replacementObj, &len);
bytes = TclGetStringFromObj(replacementObj, &len);
PushLiteral(envPtr, bytes, len);
CompileWord(envPtr, stringTokenPtr, interp, parsePtr->numWords-2);
TclEmitOpcode( INST_STR_MAP, envPtr);
@@ -2761,7 +2761,7 @@ TclCompileSyntaxError(
const char *bytes = TclGetStringFromObj(msg, &numBytes);
TclErrorStackResetIf(interp, bytes, numBytes);
TclEmitPush(TclRegisterNewLiteral(envPtr, bytes, numBytes), envPtr);
TclEmitPush(TclRegisterLiteral(envPtr, bytes, numBytes, 0), envPtr);
CompileReturnInternal(envPtr, INST_SYNTAX, TCL_ERROR, 0,
TclNoErrorStack(interp, Tcl_GetReturnOptions(interp, TCL_ERROR)));
Tcl_ResetResult(interp);
+12 -12
View File
@@ -312,7 +312,7 @@ TclCompileStringCatCmd(
Tcl_DecrRefCount(obj);
if (folded) {
int len;
const char *bytes = Tcl_GetStringFromObj(folded, &len);
const char *bytes = TclGetStringFromObj(folded, &len);
PushLiteral(envPtr, bytes, len);
Tcl_DecrRefCount(folded);
@@ -330,7 +330,7 @@ TclCompileStringCatCmd(
}
if (folded) {
int len;
const char *bytes = Tcl_GetStringFromObj(folded, &len);
const char *bytes = TclGetStringFromObj(folded, &len);
PushLiteral(envPtr, bytes, len);
Tcl_DecrRefCount(folded);
@@ -948,12 +948,12 @@ TclCompileStringMapCmd(
* correct semantics for mapping.
*/
bytes = Tcl_GetStringFromObj(objv[0], &len);
bytes = TclGetStringFromObj(objv[0], &len);
if (len == 0) {
CompileWord(envPtr, stringTokenPtr, interp, 2);
} else {
PushLiteral(envPtr, bytes, len);
bytes = Tcl_GetStringFromObj(objv[1], &len);
bytes = TclGetStringFromObj(objv[1], &len);
PushLiteral(envPtr, bytes, len);
CompileWord(envPtr, stringTokenPtr, interp, 2);
OP(STR_MAP);
@@ -1456,8 +1456,8 @@ TclSubstCompile(
switch (tokenPtr->type) {
case TCL_TOKEN_TEXT:
literal = TclRegisterNewLiteral(envPtr,
tokenPtr->start, tokenPtr->size);
literal = TclRegisterLiteral(envPtr,
tokenPtr->start, tokenPtr->size, 0);
TclEmitPush(literal, envPtr);
TclAdvanceLines(&bline, tokenPtr->start,
tokenPtr->start + tokenPtr->size);
@@ -1466,7 +1466,7 @@ TclSubstCompile(
case TCL_TOKEN_BS:
length = TclParseBackslash(tokenPtr->start, tokenPtr->size,
NULL, buf);
literal = TclRegisterNewLiteral(envPtr, buf, length);
literal = TclRegisterLiteral(envPtr, buf, length, 0);
TclEmitPush(literal, envPtr);
count++;
continue;
@@ -2825,7 +2825,7 @@ TclCompileTryCmd(
}
if (objc > 0) {
int len;
const char *varname = Tcl_GetStringFromObj(objv[0], &len);
const char *varname = TclGetStringFromObj(objv[0], &len);
resultVarIndices[i] = LocalScalar(varname, len, envPtr);
if (resultVarIndices[i] < 0) {
@@ -2837,7 +2837,7 @@ TclCompileTryCmd(
}
if (objc == 2) {
int len;
const char *varname = Tcl_GetStringFromObj(objv[1], &len);
const char *varname = TclGetStringFromObj(objv[1], &len);
optionVarIndices[i] = LocalScalar(varname, len, envPtr);
if (optionVarIndices[i] < 0) {
@@ -3040,7 +3040,7 @@ IssueTryClausesInstructions(
OP4( DICT_GET, 1);
TclAdjustStackDepth(-1, envPtr);
OP44( LIST_RANGE_IMM, 0, len-1);
p = Tcl_GetStringFromObj(matchClauses[i], &len);
p = TclGetStringFromObj(matchClauses[i], &len);
PushLiteral(envPtr, p, len);
OP( STR_EQ);
JUMP4( JUMP_FALSE, notECJumpSource);
@@ -3251,7 +3251,7 @@ IssueTryClausesFinallyInstructions(
OP4( DICT_GET, 1);
TclAdjustStackDepth(-1, envPtr);
OP44( LIST_RANGE_IMM, 0, len-1);
p = Tcl_GetStringFromObj(matchClauses[i], &len);
p = TclGetStringFromObj(matchClauses[i], &len);
PushLiteral(envPtr, p, len);
OP( STR_EQ);
JUMP4( JUMP_FALSE, notECJumpSource);
@@ -3579,7 +3579,7 @@ TclCompileUnsetCmd(
const char *bytes;
int len;
bytes = Tcl_GetStringFromObj(leadingWord, &len);
bytes = TclGetStringFromObj(leadingWord, &len);
if (i == 1 && len == 11 && !strncmp("-nocomplain", bytes, 11)) {
flags = 0;
haveFlags++;
+9 -9
View File
@@ -2267,9 +2267,9 @@ CompileExprTree(
p = TclGetStringFromObj(*funcObjv, &length);
funcObjv++;
Tcl_DStringAppend(&cmdName, p, length);
TclEmitPush(TclRegisterNewCmdLiteral(envPtr,
TclEmitPush(TclRegisterLiteral(envPtr,
Tcl_DStringValue(&cmdName),
Tcl_DStringLength(&cmdName)), envPtr);
Tcl_DStringLength(&cmdName), LITERAL_CMD_NAME), envPtr);
Tcl_DStringFree(&cmdName);
/*
@@ -2376,8 +2376,8 @@ CompileExprTree(
pc1 = CurrentOffset(envPtr);
TclEmitInstInt1((nodePtr->lexeme == AND) ? INST_JUMP_FALSE1
: INST_JUMP_TRUE1, 0, envPtr);
TclEmitPush(TclRegisterNewLiteral(envPtr,
(nodePtr->lexeme == AND) ? "1" : "0", 1), envPtr);
TclEmitPush(TclRegisterLiteral(envPtr,
(nodePtr->lexeme == AND) ? "1" : "0", 1, 0), envPtr);
pc2 = CurrentOffset(envPtr);
TclEmitInstInt1(INST_JUMP1, 0, envPtr);
TclAdjustStackDepth(-1, envPtr);
@@ -2386,8 +2386,8 @@ CompileExprTree(
if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) {
pc2 += 3;
}
TclEmitPush(TclRegisterNewLiteral(envPtr,
(nodePtr->lexeme == AND) ? "0" : "1", 1), envPtr);
TclEmitPush(TclRegisterLiteral(envPtr,
(nodePtr->lexeme == AND) ? "0" : "1", 1, 0), envPtr);
TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc2,
envPtr->codeStart + pc2 + 1);
convert = 0;
@@ -2421,7 +2421,7 @@ CompileExprTree(
if (optimize) {
int length;
const char *bytes = TclGetStringFromObj(literal, &length);
int index = TclRegisterNewLiteral(envPtr, bytes, length);
int index = TclRegisterLiteral(envPtr, bytes, length, 0);
Tcl_Obj *objPtr = TclFetchLiteral(envPtr, index);
if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) {
@@ -2479,8 +2479,8 @@ CompileExprTree(
if (objPtr->bytes) {
Tcl_Obj *tableValue;
index = TclRegisterNewLiteral(envPtr, objPtr->bytes,
objPtr->length);
index = TclRegisterLiteral(envPtr, objPtr->bytes,
objPtr->length, 0);
tableValue = TclFetchLiteral(envPtr, index);
if ((tableValue->typePtr == NULL) &&
(objPtr->typePtr != NULL)) {
+22 -12
View File
@@ -993,7 +993,7 @@ FreeByteCodeInternalRep(
void
TclPreserveByteCode(
register ByteCode *codePtr)
register ByteCode *codePtr)
{
codePtr->refCount++;
}
@@ -1314,7 +1314,7 @@ CompileSubstObj(
if (objPtr->typePtr != &substCodeType) {
CompileEnv compEnv;
int numBytes;
const char *bytes = Tcl_GetStringFromObj(objPtr, &numBytes);
const char *bytes = TclGetStringFromObj(objPtr, &numBytes);
/* TODO: Check for more TIP 280 */
TclInitCompileEnv(interp, &compEnv, bytes, numBytes, NULL, 0);
@@ -1792,9 +1792,17 @@ CompileCmdLiteral(
CompileEnv *envPtr)
{
int numBytes;
const char *bytes = Tcl_GetStringFromObj(cmdObj, &numBytes);
int cmdLitIdx = TclRegisterNewCmdLiteral(envPtr, bytes, numBytes);
Command *cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdObj);
const char *bytes;
Command *cmdPtr;
int cmdLitIdx, extraLiteralFlags = LITERAL_CMD_NAME;
cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdObj);
if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) {
extraLiteralFlags |= LITERAL_UNSHARED;
}
bytes = Tcl_GetStringFromObj(cmdObj, &numBytes);
cmdLitIdx = TclRegisterLiteral(envPtr, bytes, numBytes, extraLiteralFlags);
if (cmdPtr) {
TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLitIdx), cmdPtr);
@@ -1829,8 +1837,8 @@ TclCompileInvocation(
continue;
}
objIdx = TclRegisterNewLiteral(envPtr,
tokenPtr[1].start, tokenPtr[1].size);
objIdx = TclRegisterLiteral(envPtr,
tokenPtr[1].start, tokenPtr[1].size, 0);
if (envPtr->clNext) {
TclContinuationsEnterDerived(TclFetchLiteral(envPtr, objIdx),
tokenPtr[1].start - envPtr->source, envPtr->clNext);
@@ -1879,8 +1887,8 @@ CompileExpanded(
continue;
}
objIdx = TclRegisterNewLiteral(envPtr,
tokenPtr[1].start, tokenPtr[1].size);
objIdx = TclRegisterLiteral(envPtr,
tokenPtr[1].start, tokenPtr[1].size, 0);
if (envPtr->clNext) {
TclContinuationsEnterDerived(TclFetchLiteral(envPtr, objIdx),
tokenPtr[1].start - envPtr->source, envPtr->clNext);
@@ -2729,7 +2737,7 @@ PreventCycle(
* the intrep.
*/
int numBytes;
const char *bytes = Tcl_GetStringFromObj(objPtr, &numBytes);
const char *bytes = TclGetStringFromObj(objPtr, &numBytes);
Tcl_Obj *copyPtr = Tcl_NewStringObj(bytes, numBytes);
Tcl_IncrRefCount(copyPtr);
@@ -2968,7 +2976,7 @@ TclFindCompiledLocal(
varNamePtr = &cachePtr->varName0;
for (i=0; i < cachePtr->numVars; varNamePtr++, i++) {
if (*varNamePtr) {
localName = Tcl_GetStringFromObj(*varNamePtr, &len);
localName = TclGetStringFromObj(*varNamePtr, &len);
if ((len == nameBytes) && !strncmp(name, localName, len)) {
return i;
}
@@ -3276,8 +3284,10 @@ EnterCmdWordData(
TclAdvanceLines(&wordLine, last, tokenPtr->start);
TclAdvanceContinuations(&wordLine, &wordNext,
tokenPtr->start - envPtr->source);
/* See Ticket 4b61afd660 */
wwlines[wordIdx] =
(TclWordKnownAtCompileTime(tokenPtr, NULL) ? wordLine : -1);
((wordIdx == 0) || TclWordKnownAtCompileTime(tokenPtr, NULL))
? wordLine : -1;
ePtr->line[wordIdx] = wordLine;
ePtr->next[wordIdx] = wordNext;
last = tokenPtr->start;
+4 -26
View File
@@ -1095,7 +1095,7 @@ MODULE_SCOPE int TclCreateAuxData(ClientData clientData,
MODULE_SCOPE int TclCreateExceptRange(ExceptionRangeType type,
CompileEnv *envPtr);
MODULE_SCOPE ExecEnv * TclCreateExecEnv(Tcl_Interp *interp, int size);
MODULE_SCOPE Tcl_Obj * TclCreateLiteral(Interp *iPtr, char *bytes,
MODULE_SCOPE Tcl_Obj * TclCreateLiteral(Interp *iPtr, const char *bytes,
int length, unsigned int hash, int *newPtr,
Namespace *nsPtr, int flags,
LiteralEntry **globalPtrPtr);
@@ -1210,29 +1210,7 @@ MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData,
#define LITERAL_ON_HEAP 0x01
#define LITERAL_CMD_NAME 0x02
/*
* Form of TclRegisterLiteral with flags == 0. In that case, it is safe to
* cast away constness, and it is cleanest to do that here, all in one place.
*
* int TclRegisterNewLiteral(CompileEnv *envPtr, const char *bytes,
* int length);
*/
#define TclRegisterNewLiteral(envPtr, bytes, length) \
TclRegisterLiteral(envPtr, (char *)(bytes), length, /*flags*/ 0)
/*
* Form of TclRegisterLiteral with flags == LITERAL_CMD_NAME. In that case, it
* is safe to cast away constness, and it is cleanest to do that here, all in
* one place.
*
* int TclRegisterNewNSLiteral(CompileEnv *envPtr, const char *bytes,
* int length);
*/
#define TclRegisterNewCmdLiteral(envPtr, bytes, length) \
TclRegisterLiteral(envPtr, (char *)(bytes), length, LITERAL_CMD_NAME)
#define LITERAL_UNSHARED 0x04
/*
* Macro used to manually adjust the stack requirements; used in cases where
@@ -1549,9 +1527,9 @@ MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData,
*/
#define PushLiteral(envPtr, string, length) \
TclEmitPush(TclRegisterNewLiteral((envPtr), (string), (length)), (envPtr))
TclEmitPush(TclRegisterLiteral(envPtr, string, length, 0), (envPtr))
#define PushStringLiteral(envPtr, string) \
PushLiteral((envPtr), (string), (int) (sizeof(string "") - 1))
PushLiteral(envPtr, string, (int) (sizeof(string "") - 1))
/*
* Macro to advance to the next token; it is more mnemonic than the address
+1 -7
View File
@@ -359,14 +359,8 @@ typedef short int yytype_int16;
#ifndef YYSIZE_T
# ifdef __SIZE_TYPE__
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
# define YYSIZE_T unsigned int
# define YYSIZE_T size_t
# endif
#endif
+43 -22
View File
@@ -70,18 +70,12 @@ static inline void DeleteChainTable(struct Dict *dict);
static inline Tcl_HashEntry *CreateChainEntry(struct Dict *dict,
Tcl_Obj *keyPtr, int *newPtr);
static inline int DeleteChainEntry(struct Dict *dict, Tcl_Obj *keyPtr);
static int FinalizeDictUpdate(ClientData data[],
Tcl_Interp *interp, int result);
static int FinalizeDictWith(ClientData data[],
Tcl_Interp *interp, int result);
static int DictForNRCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv);
static int DictMapNRCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv);
static int DictForLoopCallback(ClientData data[],
Tcl_Interp *interp, int result);
static int DictMapLoopCallback(ClientData data[],
Tcl_Interp *interp, int result);
static Tcl_NRPostProc FinalizeDictUpdate;
static Tcl_NRPostProc FinalizeDictWith;
static Tcl_ObjCmdProc DictForNRCmd;
static Tcl_ObjCmdProc DictMapNRCmd;
static Tcl_NRPostProc DictForLoopCallback;
static Tcl_NRPostProc DictMapLoopCallback;
/*
* Table of dict subcommand names and implementations.
@@ -2288,7 +2282,7 @@ DictAppendCmd(
Tcl_Obj *const *objv)
{
Tcl_Obj *dictPtr, *valuePtr, *resultPtr;
int i, allocatedDict = 0;
int allocatedDict = 0;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?value ...?");
@@ -2311,17 +2305,44 @@ DictAppendCmd(
return TCL_ERROR;
}
if (valuePtr == NULL) {
TclNewObj(valuePtr);
} else if (Tcl_IsShared(valuePtr)) {
valuePtr = Tcl_DuplicateObj(valuePtr);
if ((objc > 3) || (valuePtr == NULL)) {
/* Only go through append activites when something will change. */
Tcl_Obj *appendObjPtr = NULL;
if (objc > 3) {
/* Something to append */
if (objc == 4) {
appendObjPtr = objv[3];
} else if (TCL_OK != TclStringCatObjv(interp, /* inPlace */ 1,
objc-3, objv+3, &appendObjPtr)) {
return TCL_ERROR;
}
}
if (appendObjPtr == NULL) {
/* => (objc == 3) => (valuePtr == NULL) */
TclNewObj(valuePtr);
} else if (valuePtr == NULL) {
valuePtr = appendObjPtr;
appendObjPtr = NULL;
}
if (appendObjPtr) {
if (Tcl_IsShared(valuePtr)) {
valuePtr = Tcl_DuplicateObj(valuePtr);
}
Tcl_AppendObjToObj(valuePtr, appendObjPtr);
}
Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr);
}
for (i=3 ; i<objc ; i++) {
Tcl_AppendObjToObj(valuePtr, objv[i]);
}
Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr);
/*
* Even if nothing changed, we still overwrite so that variable
* trace expectations are met.
*/
resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr,
TCL_LEAVE_ERR_MSG);
+136 -3
View File
@@ -6,7 +6,7 @@
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc.
* Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
* Copyright (c) 2013 Donal K. Fellows.
* Copyright (c) 2013-2016 Donal K. Fellows.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -193,7 +193,7 @@ TclPrintObject(
char *bytes;
int length;
bytes = Tcl_GetStringFromObj(objPtr, &length);
bytes = TclGetStringFromObj(objPtr, &length);
TclPrintSource(outFile, bytes, TclMin(length, maxChars));
}
@@ -650,7 +650,7 @@ FormatInstruction(
int length;
Tcl_AppendToObj(bufferObj, "\t# ", -1);
bytes = Tcl_GetStringFromObj(codePtr->objArrayPtr[opnd], &length);
bytes = TclGetStringFromObj(codePtr->objArrayPtr[opnd], &length);
PrintSourceToObj(bufferObj, bytes, TclMin(length, 40));
} else if (suffixBuffer[0]) {
Tcl_AppendPrintfToObj(bufferObj, "\t# %s", suffixBuffer);
@@ -1279,9 +1279,11 @@ Tcl_DisassembleObjCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
static const char *const types[] = {
"constructor", "destructor",
"lambda", "method", "objmethod", "proc", "script", NULL
};
enum Types {
DISAS_CLASS_CONSTRUCTOR, DISAS_CLASS_DESTRUCTOR,
DISAS_LAMBDA, DISAS_CLASS_METHOD, DISAS_OBJECT_METHOD, DISAS_PROC,
DISAS_SCRIPT
};
@@ -1290,6 +1292,7 @@ Tcl_DisassembleObjCmd(
Proc *procPtr = NULL;
Tcl_HashEntry *hPtr;
Object *oPtr;
Method *methodPtr;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "type ...");
@@ -1384,6 +1387,136 @@ Tcl_DisassembleObjCmd(
codeObjPtr = objv[2];
break;
case DISAS_CLASS_CONSTRUCTOR:
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "className");
return TCL_ERROR;
}
/*
* Look up the body of a constructor.
*/
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;
}
methodPtr = oPtr->classPtr->constructorPtr;
if (methodPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" has no defined constructor",
TclGetString(objv[2])));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
"CONSRUCTOR", NULL);
return TCL_ERROR;
}
procPtr = TclOOGetProcFromMethod(methodPtr);
if (procPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"body not available for this kind of constructor", -1));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
"METHODTYPE", NULL);
return TCL_ERROR;
}
/*
* Compile if necessary.
*/
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 constructor",
TclGetString(objv[2]));
procPtr->cmdPtr = NULL;
if (result != TCL_OK) {
return result;
}
}
codeObjPtr = procPtr->bodyPtr;
break;
case DISAS_CLASS_DESTRUCTOR:
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "className");
return TCL_ERROR;
}
/*
* Look up the body of a destructor.
*/
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;
}
methodPtr = oPtr->classPtr->destructorPtr;
if (methodPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" has no defined destructor",
TclGetString(objv[2])));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
"DESRUCTOR", NULL);
return TCL_ERROR;
}
procPtr = TclOOGetProcFromMethod(methodPtr);
if (procPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"body not available for this kind of destructor", -1));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
"METHODTYPE", NULL);
return TCL_ERROR;
}
/*
* Compile if necessary.
*/
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 destructor",
TclGetString(objv[2]));
procPtr->cmdPtr = NULL;
if (result != TCL_OK) {
return result;
}
}
codeObjPtr = procPtr->bodyPtr;
break;
case DISAS_CLASS_METHOD:
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "className methodName");
+2 -1
View File
@@ -355,6 +355,7 @@ DupEncodingIntRep(
Tcl_Obj *dupPtr)
{
dupPtr->internalRep.twoPtrValue.ptr1 = Tcl_GetEncoding(NULL, srcPtr->bytes);
dupPtr->typePtr = &encodingType;
}
/*
@@ -3632,7 +3633,7 @@ InitializeEncodingSearchPath(
if (*encodingPtr) {
((Encoding *)(*encodingPtr))->refCount++;
}
bytes = Tcl_GetStringFromObj(searchPathObj, &numBytes);
bytes = TclGetStringFromObj(searchPathObj, &numBytes);
*lengthPtr = numBytes;
*valuePtr = ckalloc(numBytes + 1);
+254 -159
View File
@@ -30,11 +30,10 @@ static int NsEnsembleStringOrder(const void *strPtr1,
const void *strPtr2);
static void DeleteEnsembleConfig(ClientData clientData);
static void MakeCachedEnsembleCommand(Tcl_Obj *objPtr,
EnsembleConfig *ensemblePtr,
const char *subcmdName, Tcl_Obj *prefixObjPtr);
EnsembleConfig *ensemblePtr, Tcl_HashEntry *hPtr,
Tcl_Obj *fix);
static void FreeEnsembleCmdRep(Tcl_Obj *objPtr);
static void DupEnsembleCmdRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
static void StringOfEnsembleCmdRep(Tcl_Obj *objPtr);
static void CompileToInvokedCommand(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Tcl_Obj *replacements,
Command *cmdPtr, CompileEnv *envPtr);
@@ -42,6 +41,8 @@ static int CompileBasicNArgCommand(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
CompileEnv *envPtr);
static Tcl_NRPostProc FreeER;
/*
* The lists of subcommands and options for the [namespace ensemble] command.
*/
@@ -77,14 +78,30 @@ enum EnsConfigOpts {
* that implements it.
*/
const Tcl_ObjType tclEnsembleCmdType = {
static const Tcl_ObjType ensembleCmdType = {
"ensembleCommand", /* the type's name */
FreeEnsembleCmdRep, /* freeIntRepProc */
DupEnsembleCmdRep, /* dupIntRepProc */
StringOfEnsembleCmdRep, /* updateStringProc */
NULL, /* updateStringProc */
NULL /* setFromAnyProc */
};
/*
* The internal rep for caching ensemble subcommand lookups and
* spell corrections.
*/
typedef struct {
int epoch; /* Used to confirm when the data in this
* really structure matches up with the
* ensemble. */
Command *token; /* Reference to the command for which this
* structure is a cache of the resolution. */
Tcl_Obj *fix; /* Corrected spelling, if needed. */
Tcl_HashEntry *hPtr; /* Direct link to entry in the subcommand
* hash table. */
} EnsembleCmdRep;
static inline Tcl_Obj *
NewNsObj(
@@ -1643,6 +1660,8 @@ NsEnsembleImplementationCmdNR(
* names. */
int reparseCount = 0; /* Number of reparses. */
Tcl_Obj *errorObj; /* Used for building error messages. */
Tcl_Obj *subObj;
int subIdx;
/*
* Must recheck objc, since numParameters might have changed. Cf. test
@@ -1650,24 +1669,18 @@ NsEnsembleImplementationCmdNR(
*/
restartEnsembleParse:
if (objc < 2 + ensemblePtr->numParameters) {
subIdx = 1 + ensemblePtr->numParameters;
if (objc < subIdx + 1) {
/*
* We don't have a subcommand argument. Make error message.
*/
Tcl_DString buf; /* Message being built */
Tcl_Obj **elemPtrs; /* Parameter names */
int len; /* Number of parameters to append */
Tcl_DStringInit(&buf);
if (ensemblePtr->parameterList == NULL) {
len = 0;
} else if (TclListObjGetElements(NULL, ensemblePtr->parameterList,
&len, &elemPtrs) != TCL_OK) {
Tcl_Panic("List of ensemble parameters is not a list");
}
for (; len>0; len--,elemPtrs++) {
TclDStringAppendObj(&buf, *elemPtrs);
if (ensemblePtr->parameterList) {
Tcl_DStringAppend(&buf,
TclGetString(ensemblePtr->parameterList), -1);
TclDStringAppendLiteral(&buf, " ");
}
TclDStringAppendLiteral(&buf, "subcommand ?arg ...?");
@@ -1695,6 +1708,8 @@ NsEnsembleImplementationCmdNR(
* up in there and go straight to dispatch.
*/
subObj = objv[subIdx];
if (ensemblePtr->epoch == ensemblePtr->nsPtr->exportLookupEpoch) {
/*
* Table of subcommands is still valid; therefore there might be a
@@ -1703,15 +1718,16 @@ NsEnsembleImplementationCmdNR(
* part where we do the invocation of the subcommand.
*/
if (objv[1+ensemblePtr->numParameters]->typePtr==&tclEnsembleCmdType){
EnsembleCmdRep *ensembleCmd = objv[1+ensemblePtr->numParameters]
->internalRep.twoPtrValue.ptr1;
if (subObj->typePtr==&ensembleCmdType){
EnsembleCmdRep *ensembleCmd = subObj->internalRep.twoPtrValue.ptr1;
if (ensembleCmd->nsPtr == ensemblePtr->nsPtr &&
ensembleCmd->epoch == ensemblePtr->epoch &&
ensembleCmd->token == ensemblePtr->token) {
prefixObj = ensembleCmd->realPrefixObj;
if (ensembleCmd->epoch == ensemblePtr->epoch &&
ensembleCmd->token == (Command *)ensemblePtr->token) {
prefixObj = Tcl_GetHashValue(ensembleCmd->hPtr);
Tcl_IncrRefCount(prefixObj);
if (ensembleCmd->fix) {
TclSpellFix(interp, objv, objc, subIdx, subObj, ensembleCmd->fix);
}
goto runResultingSubcommand;
}
}
@@ -1726,18 +1742,14 @@ NsEnsembleImplementationCmdNR(
*/
hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable,
TclGetString(objv[1 + ensemblePtr->numParameters]));
TclGetString(subObj));
if (hPtr != NULL) {
char *fullName = Tcl_GetHashKey(&ensemblePtr->subcommandTable, hPtr);
prefixObj = Tcl_GetHashValue(hPtr);
/*
* Cache for later in the subcommand object.
*/
MakeCachedEnsembleCommand(objv[1 + ensemblePtr->numParameters],
ensemblePtr, fullName, prefixObj);
MakeCachedEnsembleCommand(subObj, ensemblePtr, hPtr, NULL);
} else if (!(ensemblePtr->flags & TCL_ENSEMBLE_PREFIX)) {
/*
* Could not map, no prefixing, go to unknown/error handling.
@@ -1757,9 +1769,9 @@ NsEnsembleImplementationCmdNR(
char *fullName = NULL; /* Full name of the subcommand. */
int stringLength, i;
int tableLength = ensemblePtr->subcommandTable.numEntries;
Tcl_Obj *fix;
subcmdName = TclGetString(objv[1 + ensemblePtr->numParameters]);
stringLength = objv[1 + ensemblePtr->numParameters]->length;
subcmdName = TclGetStringFromObj(subObj, &stringLength);
for (i=0 ; i<tableLength ; i++) {
register int cmp = strncmp(subcmdName,
ensemblePtr->subcommandArrayPtr[i],
@@ -1799,16 +1811,22 @@ NsEnsembleImplementationCmdNR(
Tcl_Panic("full name %s not found in supposedly synchronized hash",
fullName);
}
prefixObj = Tcl_GetHashValue(hPtr);
/*
* Record the spelling correction for usage message.
*/
fix = Tcl_NewStringObj(fullName, -1);
/*
* Cache for later in the subcommand object.
*/
MakeCachedEnsembleCommand(objv[1 + ensemblePtr->numParameters],
ensemblePtr, fullName, prefixObj);
MakeCachedEnsembleCommand(subObj, ensemblePtr, hPtr, fix);
TclSpellFix(interp, objv, objc, subIdx, subObj, fix);
}
prefixObj = Tcl_GetHashValue(hPtr);
Tcl_IncrRefCount(prefixObj);
runResultingSubcommand:
@@ -1827,47 +1845,26 @@ NsEnsembleImplementationCmdNR(
*/
{
Tcl_Obj **prefixObjv; /* The list of objects to substitute in as the
* target command prefix. */
Tcl_Obj *copyPtr; /* The actual list of words to dispatch to.
* Will be freed by the dispatch engine. */
int prefixObjc, copyObjc;
Interp *iPtr = (Interp *) interp;
Tcl_Obj **copyObjv;
int copyObjc, prefixObjc;
/*
* Get the prefix that we're rewriting to. To do this we need to
* ensure that the internal representation of the list does not change
* so that we can safely keep the internal representations of the
* elements in the list.
*
* TODO: Use conventional list operations to make this code sane!
*/
Tcl_ListObjLength(NULL, prefixObj, &prefixObjc);
TclListObjGetElements(NULL, prefixObj, &prefixObjc, &prefixObjv);
copyObjc = objc - 2 + prefixObjc;
copyPtr = Tcl_NewListObj(copyObjc, NULL);
if (copyObjc > 0) {
register Tcl_Obj **copyObjv;
/* Space used to construct the list of
* arguments to pass to the command that
* implements the ensemble subcommand. */
register List *listRepPtr = copyPtr->internalRep.twoPtrValue.ptr1;
register int i;
listRepPtr->elemCount = copyObjc;
copyObjv = &listRepPtr->elements;
memcpy(copyObjv, prefixObjv, sizeof(Tcl_Obj *) * prefixObjc);
memcpy(copyObjv+prefixObjc, objv+1,
sizeof(Tcl_Obj *) * ensemblePtr->numParameters);
memcpy(copyObjv+prefixObjc+ensemblePtr->numParameters,
objv+ensemblePtr->numParameters+2,
sizeof(Tcl_Obj *) * (objc-ensemblePtr->numParameters-2));
for (i=0; i < copyObjc; i++) {
Tcl_IncrRefCount(copyObjv[i]);
}
if (objc == 2) {
copyPtr = TclListObjCopy(NULL, prefixObj);
} else {
copyPtr = Tcl_NewListObj(objc - 2 + prefixObjc, NULL);
Tcl_ListObjAppendList(NULL, copyPtr, prefixObj);
Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
ensemblePtr->numParameters, objv + 1);
Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
objc - 2 - ensemblePtr->numParameters,
objv + 2 + ensemblePtr->numParameters);
}
Tcl_IncrRefCount(copyPtr);
TclNRAddCallback(interp, TclNRReleaseValues, copyPtr, NULL, NULL, NULL);
TclDecrRefCount(prefixObj);
/*
@@ -1876,25 +1873,10 @@ NsEnsembleImplementationCmdNR(
* count both as inserted and removed arguments.
*/
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
iPtr->ensembleRewrite.sourceObjs = objv;
iPtr->ensembleRewrite.numRemovedObjs =
2 + ensemblePtr->numParameters;
iPtr->ensembleRewrite.numInsertedObjs =
prefixObjc + ensemblePtr->numParameters;
if (TclInitRewriteEnsemble(interp, 2 + ensemblePtr->numParameters,
prefixObjc + ensemblePtr->numParameters, objv)) {
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL,
NULL);
} else {
register int ni = 2 + ensemblePtr->numParameters
- iPtr->ensembleRewrite.numInsertedObjs;
/* Position in objv of new front of insertion
* relative to old one. */
if (ni > 0) {
iPtr->ensembleRewrite.numRemovedObjs += ni;
iPtr->ensembleRewrite.numInsertedObjs += prefixObjc-1;
} else {
iPtr->ensembleRewrite.numInsertedObjs += prefixObjc-2;
}
}
/*
@@ -1902,7 +1884,8 @@ NsEnsembleImplementationCmdNR(
*/
TclSkipTailcall(interp);
return TclNREvalObjEx(interp, copyPtr, TCL_EVAL_INVOKE, NULL,INT_MIN);
Tcl_ListObjGetElements(NULL, copyPtr, &copyObjc, &copyObjv);
return TclNREvalObjv(interp, copyObjc, copyObjv, TCL_EVAL_INVOKE, NULL);
}
unknownOrAmbiguousSubcommand:
@@ -1934,20 +1917,17 @@ NsEnsembleImplementationCmdNR(
Tcl_ResetResult(interp);
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND",
TclGetString(objv[1+ensemblePtr->numParameters]), NULL);
TclGetString(subObj), NULL);
if (ensemblePtr->subcommandTable.numEntries == 0) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"unknown subcommand \"%s\": namespace %s does not"
" export any commands",
TclGetString(objv[1+ensemblePtr->numParameters]),
" export any commands", TclGetString(subObj),
ensemblePtr->nsPtr->fullName));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND",
TclGetString(objv[1+ensemblePtr->numParameters]), NULL);
return TCL_ERROR;
}
errorObj = Tcl_ObjPrintf("unknown%s subcommand \"%s\": must be ",
(ensemblePtr->flags & TCL_ENSEMBLE_PREFIX ? " or ambiguous" : ""),
TclGetString(objv[1+ensemblePtr->numParameters]));
TclGetString(subObj));
if (ensemblePtr->subcommandTable.numEntries == 1) {
Tcl_AppendToObj(errorObj, ensemblePtr->subcommandArrayPtr[0], -1);
} else {
@@ -2013,7 +1993,7 @@ TclInitRewriteEnsemble(
if (numIns < numRemoved) {
iPtr->ensembleRewrite.numRemovedObjs += numRemoved - numIns;
iPtr->ensembleRewrite.numInsertedObjs += numInserted - 1;
iPtr->ensembleRewrite.numInsertedObjs = numInserted;
} else {
iPtr->ensembleRewrite.numInsertedObjs += numInserted - numRemoved;
}
@@ -2053,6 +2033,149 @@ TclResetRewriteEnsemble(
}
}
/*
*----------------------------------------------------------------------
*
* TclSpellFix --
*
* Record a spelling correction that needs making in the
* generation of the WrongNumArgs usage message.
*
* Results:
* None.
*
* Side effects:
* Can create an alternative ensemble rewrite structure.
*
*----------------------------------------------------------------------
*/
static int
FreeER(
ClientData data[],
Tcl_Interp *interp,
int result)
{
Tcl_Obj **tmp = (Tcl_Obj **)data[0];
ckfree(tmp[2]);
ckfree(tmp);
return result;
}
void
TclSpellFix(
Tcl_Interp *interp,
Tcl_Obj *const *objv,
int objc,
int badIdx,
Tcl_Obj *bad,
Tcl_Obj *fix)
{
Interp *iPtr = (Interp *) interp;
Tcl_Obj *const *search;
Tcl_Obj **store;
int idx;
int size;
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
iPtr->ensembleRewrite.sourceObjs = objv;
iPtr->ensembleRewrite.numRemovedObjs = 0;
iPtr->ensembleRewrite.numInsertedObjs = 0;
}
/* Compute the valid length of the ensemble root */
size = iPtr->ensembleRewrite.numRemovedObjs + objc
- iPtr->ensembleRewrite.numInsertedObjs;
search = iPtr->ensembleRewrite.sourceObjs;
if (search[0] == NULL) {
/* Awful casting abuse here */
search = (Tcl_Obj *const *) search[1];
}
if (badIdx < iPtr->ensembleRewrite.numInsertedObjs) {
/*
* Misspelled value was inserted. We cannot directly jump
* to the bad value, but have to search.
*/
idx = 1;
while (idx < size) {
if (search[idx] == bad) {
break;
}
idx++;
}
if (idx == size) {
return;
}
} else {
/* Jump to the misspelled value. */
idx = iPtr->ensembleRewrite.numRemovedObjs + badIdx
- iPtr->ensembleRewrite.numInsertedObjs;
/* Verify */
if (search[idx] != bad) {
Tcl_Panic("SpellFix: programming error");
}
}
search = iPtr->ensembleRewrite.sourceObjs;
if (search[0] == NULL) {
store = (Tcl_Obj **)search[2];
} else {
Tcl_Obj **tmp = ckalloc(3 * sizeof(Tcl_Obj *));
tmp[0] = NULL;
tmp[1] = (Tcl_Obj *)iPtr->ensembleRewrite.sourceObjs;
tmp[2] = (Tcl_Obj *)ckalloc(size * sizeof(Tcl_Obj *));
memcpy(tmp[2], tmp[1], size*sizeof(Tcl_Obj *));
iPtr->ensembleRewrite.sourceObjs = (Tcl_Obj *const *) tmp;
TclNRAddCallback(interp, FreeER, tmp, NULL, NULL, NULL);
store = (Tcl_Obj **)tmp[2];
}
store[idx] = fix;
Tcl_IncrRefCount(fix);
TclNRAddCallback(interp, TclNRReleaseValues, fix, NULL, NULL, NULL);
}
/*
*----------------------------------------------------------------------
*
* TclFetchEnsembleRoot --
*
* Returns the root of ensemble rewriting, if any.
* If no root exists, returns objv instead.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *const *
TclFetchEnsembleRoot(
Tcl_Interp *interp,
Tcl_Obj *const *objv,
int objc,
int *objcPtr)
{
Interp *iPtr = (Interp *) interp;
if (iPtr->ensembleRewrite.sourceObjs) {
*objcPtr = objc + iPtr->ensembleRewrite.numRemovedObjs
- iPtr->ensembleRewrite.numInsertedObjs;
return iPtr->ensembleRewrite.sourceObjs;
}
*objcPtr = objc;
return objv;
}
/*
* ----------------------------------------------------------------------
*
@@ -2218,17 +2341,17 @@ static void
MakeCachedEnsembleCommand(
Tcl_Obj *objPtr,
EnsembleConfig *ensemblePtr,
const char *subcommandName,
Tcl_Obj *prefixObjPtr)
Tcl_HashEntry *hPtr,
Tcl_Obj *fix)
{
register EnsembleCmdRep *ensembleCmd;
int length;
if (objPtr->typePtr == &tclEnsembleCmdType) {
if (objPtr->typePtr == &ensembleCmdType) {
ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
TclNsDecrRefCount(ensembleCmd->nsPtr);
ckfree(ensembleCmd->fullSubcmdName);
TclCleanupCommandMacro(ensembleCmd->token);
if (ensembleCmd->fix) {
Tcl_DecrRefCount(ensembleCmd->fix);
}
} else {
/*
* Kill the old internal rep, and replace it with a brand new one of
@@ -2238,22 +2361,21 @@ MakeCachedEnsembleCommand(
TclFreeIntRep(objPtr);
ensembleCmd = ckalloc(sizeof(EnsembleCmdRep));
objPtr->internalRep.twoPtrValue.ptr1 = ensembleCmd;
objPtr->typePtr = &tclEnsembleCmdType;
objPtr->typePtr = &ensembleCmdType;
}
/*
* Populate the internal rep.
*/
ensembleCmd->nsPtr = ensemblePtr->nsPtr;
ensembleCmd->epoch = ensemblePtr->epoch;
ensembleCmd->token = ensemblePtr->token;
ensemblePtr->nsPtr->refCount++;
ensembleCmd->realPrefixObj = prefixObjPtr;
length = strlen(subcommandName)+1;
ensembleCmd->fullSubcmdName = ckalloc(length);
memcpy(ensembleCmd->fullSubcmdName, subcommandName, (unsigned) length);
Tcl_IncrRefCount(ensembleCmd->realPrefixObj);
ensembleCmd->token = (Command *) ensemblePtr->token;
ensembleCmd->token->refCount++;
if (fix) {
Tcl_IncrRefCount(fix);
}
ensembleCmd->fix = fix;
ensembleCmd->hPtr = hPtr;
}
/*
@@ -2634,9 +2756,10 @@ FreeEnsembleCmdRep(
{
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
ckfree(ensembleCmd->fullSubcmdName);
TclNsDecrRefCount(ensembleCmd->nsPtr);
TclCleanupCommandMacro(ensembleCmd->token);
if (ensembleCmd->fix) {
Tcl_DecrRefCount(ensembleCmd->fix);
}
ckfree(ensembleCmd);
objPtr->typePtr = NULL;
}
@@ -2666,48 +2789,17 @@ DupEnsembleCmdRep(
{
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
EnsembleCmdRep *ensembleCopy = ckalloc(sizeof(EnsembleCmdRep));
int length = strlen(ensembleCmd->fullSubcmdName);
copyPtr->typePtr = &tclEnsembleCmdType;
copyPtr->typePtr = &ensembleCmdType;
copyPtr->internalRep.twoPtrValue.ptr1 = ensembleCopy;
ensembleCopy->nsPtr = ensembleCmd->nsPtr;
ensembleCopy->epoch = ensembleCmd->epoch;
ensembleCopy->token = ensembleCmd->token;
ensembleCopy->nsPtr->refCount++;
ensembleCopy->realPrefixObj = ensembleCmd->realPrefixObj;
Tcl_IncrRefCount(ensembleCopy->realPrefixObj);
ensembleCopy->fullSubcmdName = ckalloc(length + 1);
memcpy(ensembleCopy->fullSubcmdName, ensembleCmd->fullSubcmdName,
(unsigned) length+1);
}
/*
*----------------------------------------------------------------------
*
* StringOfEnsembleCmdRep --
*
* Creates a string representation of a Tcl_Obj that holds a subcommand
* of an ensemble.
*
* Results:
* None.
*
* Side effects:
* The object gains a string (UTF-8) representation.
*
*----------------------------------------------------------------------
*/
static void
StringOfEnsembleCmdRep(
Tcl_Obj *objPtr)
{
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
int length = strlen(ensembleCmd->fullSubcmdName);
objPtr->length = length;
objPtr->bytes = ckalloc(length + 1);
memcpy(objPtr->bytes, ensembleCmd->fullSubcmdName, (unsigned) length+1);
ensembleCopy->token->refCount++;
ensembleCopy->fix = ensembleCmd->fix;
if (ensembleCopy->fix) {
Tcl_IncrRefCount(ensembleCopy->fix);
}
ensembleCopy->hPtr = ensembleCmd->hPtr;
}
/*
@@ -2825,7 +2917,7 @@ TclCompileEnsemble(
goto failed;
}
for (i=0 ; i<len ; i++) {
str = Tcl_GetStringFromObj(elems[i], &sclen);
str = TclGetStringFromObj(elems[i], &sclen);
if ((sclen == (int) numBytes) && !memcmp(word, str, numBytes)) {
/*
* Exact match! Excellent!
@@ -3043,7 +3135,7 @@ TclCompileEnsemble(
* any extra elements that might have been appended by failing
* pathways above.
*/
(void) Tcl_ListObjReplace(NULL, replaced, depth-1, INT_MAX, 0, NULL);
(void) Tcl_ListObjReplace(NULL, replaced, depth-1, LIST_MAX, 0, NULL);
/*
* TODO: Reconsider whether we ought to call CompileToInvokedCommand()
@@ -3214,7 +3306,7 @@ CompileToInvokedCommand(
Tcl_Token *tokPtr;
Tcl_Obj *objPtr, **words;
char *bytes;
int length, i, numWords, cmdLit;
int length, i, numWords, cmdLit, extraLiteralFlags = LITERAL_CMD_NAME;
DefineLineInformation;
/*
@@ -3227,15 +3319,15 @@ CompileToInvokedCommand(
for (i = 0, tokPtr = parsePtr->tokenPtr; i < parsePtr->numWords;
i++, tokPtr = TokenAfter(tokPtr)) {
if (i > 0 && i < numWords+1) {
bytes = Tcl_GetStringFromObj(words[i-1], &length);
bytes = TclGetStringFromObj(words[i-1], &length);
PushLiteral(envPtr, bytes, length);
continue;
}
SetLineInformation(i);
if (tokPtr->type == TCL_TOKEN_SIMPLE_WORD) {
int literal = TclRegisterNewLiteral(envPtr,
tokPtr[1].start, tokPtr[1].size);
int literal = TclRegisterLiteral(envPtr,
tokPtr[1].start, tokPtr[1].size, 0);
if (envPtr->clNext) {
TclContinuationsEnterDerived(
@@ -3257,7 +3349,10 @@ CompileToInvokedCommand(
objPtr = Tcl_NewObj();
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr);
bytes = Tcl_GetStringFromObj(objPtr, &length);
cmdLit = TclRegisterNewCmdLiteral(envPtr, bytes, length);
if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) {
extraLiteralFlags |= LITERAL_UNSHARED;
}
cmdLit = TclRegisterLiteral(envPtr, bytes, length, extraLiteralFlags);
TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLit), cmdPtr);
TclEmitPush(cmdLit, envPtr);
TclDecrRefCount(objPtr);
+2
View File
@@ -1465,6 +1465,8 @@ VwaitVarProc(
int *donePtr = clientData;
*donePtr = 1;
Tcl_UntraceVar(interp, name1, TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
VwaitVarProc, clientData);
return NULL;
}
+92 -277
View File
@@ -19,7 +19,6 @@
#include "tclCompile.h"
#include "tclOOInt.h"
#include "tommath.h"
#include "tclStringRep.h"
#include <math.h>
#include <assert.h>
@@ -1554,7 +1553,7 @@ CompileExprObj(
*/
if (compEnv.codeNext == compEnv.codeStart) {
TclEmitPush(TclRegisterNewLiteral(&compEnv, "0", 1),
TclEmitPush(TclRegisterLiteral(&compEnv, "0", 1, 0),
&compEnv);
}
@@ -2070,6 +2069,13 @@ TclNRExecuteByteCode(
iPtr->stats.numExecutions++;
#endif
/*
* Test namespace-50.9 demonstrates the need for this call.
* Use a --enable-symbols=mem bug to see.
*/
TclResetRewriteEnsemble(interp, 1);
/*
* Push the callback for bytecode execution
*/
@@ -2678,154 +2684,18 @@ TEBCresume(
NEXT_INST_F(5, 0, 0);
}
case INST_STR_CONCAT1: {
int appendLen = 0;
char *bytes, *p;
Tcl_Obj **currPtr;
int onlyb = 1;
case INST_STR_CONCAT1:
opnd = TclGetUInt1AtPtr(pc+1);
/*
* Detect only-bytearray-or-null case.
*/
for (currPtr=&OBJ_AT_DEPTH(opnd-1); currPtr<=&OBJ_AT_TOS; currPtr++) {
if (((*currPtr)->typePtr != &tclByteArrayType)
&& ((*currPtr)->bytes != tclEmptyStringRep)) {
onlyb = 0;
break;
} else if (((*currPtr)->typePtr == &tclByteArrayType) &&
((*currPtr)->bytes != NULL)) {
onlyb = 0;
break;
}
}
/*
* Compute the length to be appended.
*/
if (onlyb) {
for (currPtr = &OBJ_AT_DEPTH(opnd-2);
appendLen >= 0 && currPtr <= &OBJ_AT_TOS; currPtr++) {
if ((*currPtr)->bytes != tclEmptyStringRep) {
Tcl_GetByteArrayFromObj(*currPtr, &length);
appendLen += length;
}
}
} else {
for (currPtr = &OBJ_AT_DEPTH(opnd-2);
appendLen >= 0 && currPtr <= &OBJ_AT_TOS; currPtr++) {
bytes = TclGetStringFromObj(*currPtr, &length);
if (bytes != NULL) {
appendLen += length;
}
}
}
if (appendLen < 0) {
/* TODO: convert panic to error ? */
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
}
/*
* If nothing is to be appended, just return the first object by
* dropping all the others from the stack; this saves both the
* computation and copy of the string rep of the first object,
* enabling the fast '$x[set x {}]' idiom for 'K $x [set x {}]'.
*/
if (appendLen == 0) {
TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
NEXT_INST_V(2, (opnd-1), 0);
}
/*
* If the first object is shared, we need a new obj for the result;
* otherwise, we can reuse the first object. In any case, make sure it
* has enough room to accomodate all the concatenated bytes. Note that
* if it is unshared its bytes are copied by ckrealloc, so that we set
* the loop parameters to avoid copying them again: p points to the
* end of the already copied bytes, currPtr to the second object.
*/
objResultPtr = OBJ_AT_DEPTH(opnd-1);
if (!onlyb) {
bytes = TclGetStringFromObj(objResultPtr, &length);
if (length + appendLen < 0) {
/* TODO: convert panic to error ? */
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded",
INT_MAX);
}
#ifndef TCL_COMPILE_DEBUG
if (bytes != tclEmptyStringRep && !Tcl_IsShared(objResultPtr)) {
TclFreeIntRep(objResultPtr);
objResultPtr->bytes = ckrealloc(bytes, length+appendLen+1);
objResultPtr->length = length + appendLen;
p = TclGetString(objResultPtr) + length;
currPtr = &OBJ_AT_DEPTH(opnd - 2);
} else
#endif
{
p = ckalloc(length + appendLen + 1);
TclNewObj(objResultPtr);
objResultPtr->bytes = p;
objResultPtr->length = length + appendLen;
currPtr = &OBJ_AT_DEPTH(opnd - 1);
}
/*
* Append the remaining characters.
*/
for (; currPtr <= &OBJ_AT_TOS; currPtr++) {
bytes = TclGetStringFromObj(*currPtr, &length);
if (bytes != NULL) {
memcpy(p, bytes, (size_t) length);
p += length;
}
}
*p = '\0';
} else {
bytes = (char *) Tcl_GetByteArrayFromObj(objResultPtr, &length);
if (length + appendLen < 0) {
/* TODO: convert panic to error ? */
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded",
INT_MAX);
}
#ifndef TCL_COMPILE_DEBUG
if (!Tcl_IsShared(objResultPtr)) {
bytes = (char *) Tcl_SetByteArrayLength(objResultPtr,
length + appendLen);
p = bytes + length;
currPtr = &OBJ_AT_DEPTH(opnd - 2);
} else
#endif
{
TclNewObj(objResultPtr);
bytes = (char *) Tcl_SetByteArrayLength(objResultPtr,
length + appendLen);
p = bytes;
currPtr = &OBJ_AT_DEPTH(opnd - 1);
}
/*
* Append the remaining characters.
*/
for (; currPtr <= &OBJ_AT_TOS; currPtr++) {
if ((*currPtr)->bytes != tclEmptyStringRep) {
bytes = (char *) Tcl_GetByteArrayFromObj(*currPtr,&length);
memcpy(p, bytes, (size_t) length);
p += length;
}
}
if (TCL_OK != TclStringCatObjv(interp, /* inPlace */ 1,
opnd, &OBJ_AT_DEPTH(opnd-1), &objResultPtr)) {
TRACE_ERROR(interp);
goto gotError;
}
TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
NEXT_INST_V(2, opnd, 1);
}
case INST_CONCAT_STK:
/*
@@ -3153,35 +3023,34 @@ TEBCresume(
fflush(stdout);
}
#endif /*TCL_COMPILE_DEBUG*/
{
Tcl_Obj *copyPtr = Tcl_NewListObj(objc - opnd + 1, NULL);
register List *listRepPtr = copyPtr->internalRep.twoPtrValue.ptr1;
Tcl_Obj **copyObjv = &listRepPtr->elements;
int i;
listRepPtr->elemCount = objc - opnd + 1;
copyObjv[0] = objPtr;
memcpy(copyObjv+1, objv+opnd, sizeof(Tcl_Obj *) * (objc - opnd));
for (i=1 ; i<objc-opnd+1 ; i++) {
Tcl_IncrRefCount(copyObjv[i]);
}
objPtr = copyPtr;
}
bcFramePtr->data.tebc.pc = (char *) pc;
iPtr->cmdFramePtr = bcFramePtr;
if (iPtr->flags & INTERP_DEBUG_FRAME) {
ArgumentBCEnter(interp, codePtr, TD, pc, objc, objv);
}
iPtr->ensembleRewrite.sourceObjs = objv;
iPtr->ensembleRewrite.numRemovedObjs = opnd;
iPtr->ensembleRewrite.numInsertedObjs = 1;
TclInitRewriteEnsemble(interp, opnd, 1, objv);
{
Tcl_Obj *copyPtr = Tcl_NewListObj(objc - opnd + 1, NULL);
Tcl_ListObjAppendElement(NULL, copyPtr, objPtr);
Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
objc - opnd, objv + opnd);
Tcl_DecrRefCount(objPtr);
objPtr = copyPtr;
}
DECACHE_STACK_INFO();
pc += 6;
TEBC_YIELD();
TclMarkTailcall(interp);
TclNRAddCallback(interp, TclClearRootEnsemble, NULL,NULL,NULL,NULL);
return TclNREvalObjEx(interp, objPtr, TCL_EVAL_INVOKE, NULL, INT_MIN);
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv);
TclNRAddCallback(interp, TclNRReleaseValues, objPtr, NULL, NULL, NULL);
return TclNREvalObjv(interp, objc, objv, TCL_EVAL_INVOKE, NULL);
/*
* -----------------------------------------------------------------
@@ -4414,8 +4283,8 @@ TEBCresume(
savedNsPtr = iPtr->varFramePtr->nsPtr;
iPtr->varFramePtr->nsPtr = (Namespace *) nsPtr;
otherPtr = TclObjLookupVarEx(interp, OBJ_AT_TOS, NULL,
(TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access",
/*createPart1*/ 1, /*createPart2*/ 1, &varPtr);
(TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG|TCL_AVOID_RESOLVERS),
"access", /*createPart1*/ 1, /*createPart2*/ 1, &varPtr);
iPtr->varFramePtr->nsPtr = savedNsPtr;
if (!otherPtr) {
TRACE_ERROR(interp);
@@ -5277,23 +5146,10 @@ TEBCresume(
toIdx = objc-1;
}
if (fromIdx == 0 && toIdx != objc-1 && !Tcl_IsShared(valuePtr)) {
/*
* BEWARE! This is looking inside the implementation of the
* list type.
*/
List *listPtr = valuePtr->internalRep.twoPtrValue.ptr1;
if (listPtr->refCount == 1) {
for (index=toIdx+1; index<objc ; index++) {
TclDecrRefCount(objv[index]);
}
listPtr->elemCount = toIdx+1;
listPtr->canonicalFlag = 1;
TclInvalidateStringRep(valuePtr);
TRACE_APPEND(("%.30s\n", O2S(valuePtr)));
NEXT_INST_F(9, 0, 0);
}
Tcl_ListObjReplace(interp, valuePtr,
toIdx + 1, LIST_MAX, 0, NULL);
TRACE_APPEND(("%.30s\n", O2S(valuePtr)));
NEXT_INST_F(9, 0, 0);
}
objResultPtr = Tcl_NewListObj(toIdx-fromIdx+1, objv+fromIdx);
} else {
@@ -5718,17 +5574,6 @@ TEBCresume(
length3 = Tcl_GetCharLength(value3Ptr);
/*
* Remove substring. In-place.
*/
if (length3 == 0 && !Tcl_IsShared(valuePtr) && toIdx == length) {
TclDecrRefCount(value3Ptr);
Tcl_SetObjLength(valuePtr, fromIdx);
TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
NEXT_INST_F(1, 0, 0);
}
/*
* See if we can splice in place. This happens when the number of
* characters being replaced is the same as the number of characters
@@ -5738,51 +5583,29 @@ TEBCresume(
if (length3 - 1 == toIdx - fromIdx) {
unsigned char *bytes1, *bytes2;
/*
* Flush the info in the string internal rep that refers to the
* about-to-be-invalidated UTF-8 rep. This indicates that a new
* buffer needs to be allocated, and assumes that the value is
* already of tclStringTypePtr type, which should be true provided
* we call it after Tcl_GetUnicodeFromObj.
*/
#define MarkStringInternalRepForFlush(objPtr) \
(GET_STRING(objPtr)->allocated = 0)
if (Tcl_IsShared(valuePtr)) {
objResultPtr = Tcl_DuplicateObj(valuePtr);
if (TclIsPureByteArray(objResultPtr)
&& TclIsPureByteArray(value3Ptr)) {
bytes1 = Tcl_GetByteArrayFromObj(objResultPtr, NULL);
bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL);
memcpy(bytes1 + fromIdx, bytes2, length3);
} else {
ustring1 = Tcl_GetUnicodeFromObj(objResultPtr, NULL);
ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL);
memcpy(ustring1 + fromIdx, ustring2,
length3 * sizeof(Tcl_UniChar));
MarkStringInternalRepForFlush(objResultPtr);
}
Tcl_InvalidateStringRep(objResultPtr);
TclDecrRefCount(value3Ptr);
TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
NEXT_INST_F(1, 1, 1);
} else {
if (TclIsPureByteArray(valuePtr)
&& TclIsPureByteArray(value3Ptr)) {
bytes1 = Tcl_GetByteArrayFromObj(valuePtr, NULL);
bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL);
memcpy(bytes1 + fromIdx, bytes2, length3);
} else {
ustring1 = Tcl_GetUnicodeFromObj(valuePtr, NULL);
ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL);
memcpy(ustring1 + fromIdx, ustring2,
length3 * sizeof(Tcl_UniChar));
MarkStringInternalRepForFlush(valuePtr);
}
Tcl_InvalidateStringRep(valuePtr);
TclDecrRefCount(value3Ptr);
TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
objResultPtr = valuePtr;
}
if (TclIsPureByteArray(objResultPtr)
&& TclIsPureByteArray(value3Ptr)) {
bytes1 = Tcl_GetByteArrayFromObj(objResultPtr, NULL);
bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL);
memcpy(bytes1 + fromIdx, bytes2, length3);
} else {
ustring1 = Tcl_GetUnicodeFromObj(objResultPtr, NULL);
ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL);
memcpy(ustring1 + fromIdx, ustring2,
length3 * sizeof(Tcl_UniChar));
}
Tcl_InvalidateStringRep(objResultPtr);
TclDecrRefCount(value3Ptr);
TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
if (objResultPtr == valuePtr) {
NEXT_INST_F(1, 0, 0);
} else {
NEXT_INST_F(1, 1, 1);
}
}
@@ -5798,54 +5621,38 @@ TEBCresume(
* Remove substring using copying.
*/
if (length3 == 0) {
if (fromIdx > 0) {
objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx);
if (toIdx < length) {
Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1,
length - toIdx);
}
objResultPtr = NULL;
if (fromIdx > 0) {
objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx);
}
if (length3 > 0) {
if (objResultPtr) {
Tcl_AppendObjToObj(objResultPtr, value3Ptr);
} else if (Tcl_IsShared(value3Ptr)) {
objResultPtr = Tcl_DuplicateObj(value3Ptr);
} else {
objResultPtr = value3Ptr;
}
}
if (toIdx < length) {
if (objResultPtr) {
Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1,
length - toIdx);
} else {
objResultPtr = Tcl_NewUnicodeObj(ustring1 + toIdx + 1,
length - toIdx);
}
TclDecrRefCount(value3Ptr);
TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
NEXT_INST_F(1, 1, 1);
}
/*
* Splice string pieces by full copying.
*/
if (fromIdx > 0) {
objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx);
Tcl_AppendObjToObj(objResultPtr, value3Ptr);
if (toIdx < length) {
Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1,
length - toIdx);
}
} else if (Tcl_IsShared(value3Ptr)) {
objResultPtr = Tcl_DuplicateObj(value3Ptr);
if (toIdx < length) {
Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1,
length - toIdx);
}
} else {
/*
* Be careful with splicing the stack in this case; we have a
* refCount:1 object in value3Ptr and we want to append to it and
* make it be the refCount:1 object at the top of the stack
* afterwards. [Bug 82e7f67325]
*/
if (toIdx < length) {
Tcl_AppendUnicodeToObj(value3Ptr, ustring1 + toIdx + 1,
length - toIdx);
}
if (objResultPtr == NULL) {
/* This has to be the case [string replace $s 0 end {}] */
/* which has result {} which is same as value3Ptr. */
objResultPtr = value3Ptr;
}
if (objResultPtr == value3Ptr) {
/* See [Bug 82e7f67325] */
TclDecrRefCount(OBJ_AT_TOS);
OBJ_AT_TOS = value3Ptr;
TRACE_APPEND(("\"%.30s\"\n", O2S(value3Ptr)));
TclDecrRefCount(valuePtr);
OBJ_AT_TOS = value3Ptr; /* Tricky! */
NEXT_INST_F(1, 0, 0);
}
TclDecrRefCount(value3Ptr);
@@ -5913,6 +5720,9 @@ TEBCresume(
NEXT_INST_V(1, 3, 1);
case INST_STR_FIND:
#if 1
match = TclStringFind(OBJ_UNDER_TOS, OBJ_AT_TOS, 0);
#else
ustring1 = Tcl_GetUnicodeFromObj(OBJ_AT_TOS, &length); /* Haystack */
ustring2 = Tcl_GetUnicodeFromObj(OBJ_UNDER_TOS, &length2);/* Needle */
@@ -5927,6 +5737,7 @@ TEBCresume(
}
}
}
#endif
TRACE(("%.20s %.20s => %d\n",
O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match));
@@ -7706,6 +7517,7 @@ TEBCresume(
goto gotError;
}
}
Tcl_IncrRefCount(dictPtr);
if (TclListObjGetElements(interp, OBJ_AT_TOS, &length,
&keyPtrPtr) != TCL_OK) {
TRACE_ERROR(interp);
@@ -7718,6 +7530,7 @@ TEBCresume(
if (Tcl_DictObjGet(interp, dictPtr, keyPtrPtr[i],
&valuePtr) != TCL_OK) {
TRACE_ERROR(interp);
Tcl_DecrRefCount(dictPtr);
goto gotError;
}
varPtr = LOCAL(duiPtr->varIndices[i]);
@@ -7734,10 +7547,12 @@ TEBCresume(
duiPtr->varIndices[i]) == NULL) {
CACHE_STACK_INFO();
TRACE_ERROR(interp);
Tcl_DecrRefCount(dictPtr);
goto gotError;
}
CACHE_STACK_INFO();
}
TclDecrRefCount(dictPtr);
TRACE_APPEND(("OK\n"));
NEXT_INST_F(9, 0, 0);
@@ -9823,7 +9638,7 @@ IllegalExprOperandType(
if (GetNumberFromObj(NULL, opndPtr, &ptr, &type) != TCL_OK) {
int numBytes;
const char *bytes = Tcl_GetStringFromObj(opndPtr, &numBytes);
const char *bytes = TclGetStringFromObj(opndPtr, &numBytes);
if (numBytes == 0) {
description = "empty string";
@@ -10452,7 +10267,7 @@ EvalStatsCmd(
if (entryPtr->objPtr->typePtr == &tclByteCodeType) {
numByteCodeLits++;
}
(void) Tcl_GetStringFromObj(entryPtr->objPtr, &length);
(void) TclGetStringFromObj(entryPtr->objPtr, &length);
refCountSum += entryPtr->refCount;
objBytesIfUnshared += (entryPtr->refCount * sizeof(Tcl_Obj));
strBytesIfUnshared += (entryPtr->refCount * (length+1));
@@ -10674,7 +10489,7 @@ EvalStatsCmd(
Tcl_SetObjResult(interp, objPtr);
} else {
Tcl_Channel outChan;
char *str = Tcl_GetStringFromObj(objv[1], &length);
char *str = TclGetStringFromObj(objv[1], &length);
if (length) {
if (strcmp(str, "stdout") == 0) {
+2 -8
View File
@@ -1079,12 +1079,9 @@ TclFileAttrsCmd(
}
if (Tcl_GetIndexFromObj(interp, objv[0], attributeStrings,
"option", 0, &index) != TCL_OK) {
"option", INDEX_TEMP_TABLE, &index) != TCL_OK) {
goto end;
}
if (attributeStringsAllocated != NULL) {
TclFreeIntRep(objv[0]);
}
if (Tcl_FSFileAttrsGet(interp, index, filePtr,
&objPtr) != TCL_OK) {
goto end;
@@ -1107,12 +1104,9 @@ TclFileAttrsCmd(
for (i = 0; i < objc ; i += 2) {
if (Tcl_GetIndexFromObj(interp, objv[i], attributeStrings,
"option", 0, &index) != TCL_OK) {
"option", INDEX_TEMP_TABLE, &index) != TCL_OK) {
goto end;
}
if (attributeStringsAllocated != NULL) {
TclFreeIntRep(objv[i]);
}
if (i + 1 == objc) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"value for \"%s\" missing", TclGetString(objv[i])));
+18 -17
View File
@@ -387,7 +387,7 @@ TclpGetNativePathType(
{
Tcl_PathType type = TCL_PATH_ABSOLUTE;
int pathLen;
const char *path = Tcl_GetStringFromObj(pathPtr, &pathLen);
const char *path = TclGetStringFromObj(pathPtr, &pathLen);
if (path[0] == '~') {
/*
@@ -578,7 +578,7 @@ Tcl_SplitPath(
size = 1;
for (i = 0; i < *argcPtr; i++) {
Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr);
Tcl_GetStringFromObj(eltPtr, &len);
TclGetStringFromObj(eltPtr, &len);
size += len + 1;
}
@@ -597,7 +597,7 @@ Tcl_SplitPath(
p = (char *) &(*argvPtr)[(*argcPtr) + 1];
for (i = 0; i < *argcPtr; i++) {
Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr);
str = Tcl_GetStringFromObj(eltPtr, &len);
str = TclGetStringFromObj(eltPtr, &len);
memcpy(p, str, (size_t) len+1);
p += len+1;
}
@@ -857,7 +857,7 @@ TclpNativeJoinPath(
const char *p;
const char *start;
start = Tcl_GetStringFromObj(prefix, &length);
start = TclGetStringFromObj(prefix, &length);
/*
* Remove the ./ from tilde prefixed elements, and drive-letter prefixed
@@ -885,7 +885,7 @@ TclpNativeJoinPath(
if (length > 0 && (start[length-1] != '/')) {
Tcl_AppendToObj(prefix, "/", 1);
Tcl_GetStringFromObj(prefix, &length);
TclGetStringFromObj(prefix, &length);
}
needsSep = 0;
@@ -921,7 +921,7 @@ TclpNativeJoinPath(
if ((length > 0) &&
(start[length-1] != '/') && (start[length-1] != ':')) {
Tcl_AppendToObj(prefix, "/", 1);
Tcl_GetStringFromObj(prefix, &length);
TclGetStringFromObj(prefix, &length);
}
needsSep = 0;
@@ -1003,7 +1003,7 @@ Tcl_JoinPath(
* Store the result.
*/
resultStr = Tcl_GetStringFromObj(resultObj, &len);
resultStr = TclGetStringFromObj(resultObj, &len);
Tcl_DStringAppend(resultPtr, resultStr, len);
Tcl_DecrRefCount(resultObj);
@@ -1249,7 +1249,7 @@ Tcl_GlobObjCmd(
for (i = 1; i < objc; i++) {
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
&index) != TCL_OK) {
string = Tcl_GetStringFromObj(objv[i], &length);
string = TclGetStringFromObj(objv[i], &length);
if (string[0] == '-') {
/*
* It looks like the command contains an option so signal an
@@ -1357,7 +1357,7 @@ Tcl_GlobObjCmd(
if (dir == PATH_GENERAL) {
int pathlength;
const char *last;
const char *first = Tcl_GetStringFromObj(pathOrDir,&pathlength);
const char *first = TclGetStringFromObj(pathOrDir,&pathlength);
/*
* Find the last path separator in the path
@@ -1460,7 +1460,7 @@ Tcl_GlobObjCmd(
const char *str;
Tcl_ListObjIndex(interp, typePtr, length, &look);
str = Tcl_GetStringFromObj(look, &len);
str = TclGetStringFromObj(look, &len);
if (strcmp("readonly", str) == 0) {
globTypes->perm |= TCL_GLOB_PERM_RONLY;
} else if (strcmp("hidden", str) == 0) {
@@ -1595,8 +1595,9 @@ Tcl_GlobObjCmd(
} else if (dir == PATH_GENERAL) {
Tcl_DString str;
Tcl_DStringInit(&str);
for (i = 0; i < objc; i++) {
Tcl_DStringInit(&str);
Tcl_DStringSetLength(&str, 0);
if (dir == PATH_GENERAL) {
TclDStringAppendDString(&str, &prefix);
}
@@ -1991,7 +1992,7 @@ TclGlob(
Tcl_Panic("Called TclGlob with TCL_GLOBMODE_TAILS and pathPrefix==NULL");
}
pre = Tcl_GetStringFromObj(pathPrefix, &prefixLen);
pre = TclGetStringFromObj(pathPrefix, &prefixLen);
if (prefixLen > 0
&& (strchr(separators, pre[prefixLen-1]) == NULL)) {
/*
@@ -2009,7 +2010,7 @@ TclGlob(
Tcl_ListObjGetElements(NULL, filenamesObj, &objc, &objv);
for (i = 0; i< objc; i++) {
int len;
const char *oldStr = Tcl_GetStringFromObj(objv[i], &len);
const char *oldStr = TclGetStringFromObj(objv[i], &len);
Tcl_Obj *elem;
if (len == prefixLen) {
@@ -2361,7 +2362,7 @@ DoGlob(
Tcl_Obj *fixme, *newObj;
Tcl_ListObjIndex(NULL, matchesObj, repair, &fixme);
bytes = Tcl_GetStringFromObj(fixme, &numBytes);
bytes = TclGetStringFromObj(fixme, &numBytes);
newObj = Tcl_NewStringObj(bytes+2, numBytes-2);
Tcl_ListObjReplace(NULL, matchesObj, repair, 1,
1, &newObj);
@@ -2399,7 +2400,7 @@ DoGlob(
Tcl_DStringAppend(&append, pattern, p-pattern);
if (pathPtr != NULL) {
(void) Tcl_GetStringFromObj(pathPtr, &length);
(void) TclGetStringFromObj(pathPtr, &length);
} else {
length = 0;
}
@@ -2445,7 +2446,7 @@ DoGlob(
*/
int len;
const char *joined = Tcl_GetStringFromObj(joinedPtr,&len);
const char *joined = TclGetStringFromObj(joinedPtr,&len);
if (strchr(separators, joined[len-1]) == NULL) {
Tcl_AppendToObj(joinedPtr, "/", 1);
@@ -2482,7 +2483,7 @@ DoGlob(
*/
int len;
const char *joined = Tcl_GetStringFromObj(joinedPtr,&len);
const char *joined = TclGetStringFromObj(joinedPtr,&len);
if (strchr(separators, joined[len-1]) == NULL) {
if (Tcl_FSGetPathType(pathPtr) != TCL_PATH_VOLUME_RELATIVE) {
+6 -6
View File
@@ -43,7 +43,7 @@
static Tcl_HashEntry * AllocArrayEntry(Tcl_HashTable *tablePtr, void *keyPtr);
static int CompareArrayKeys(void *keyPtr, Tcl_HashEntry *hPtr);
static unsigned int HashArrayKey(Tcl_HashTable *tablePtr, void *keyPtr);
static TCL_HASH_TYPE HashArrayKey(Tcl_HashTable *tablePtr, void *keyPtr);
/*
* Prototypes for the one word hash key methods. Not actually declared because
@@ -65,7 +65,7 @@ static unsigned int HashOneWordKey(Tcl_HashTable *tablePtr, void *keyPtr);
static Tcl_HashEntry * AllocStringEntry(Tcl_HashTable *tablePtr,
void *keyPtr);
static int CompareStringKeys(void *keyPtr, Tcl_HashEntry *hPtr);
static unsigned int HashStringKey(Tcl_HashTable *tablePtr, void *keyPtr);
static TCL_HASH_TYPE HashStringKey(Tcl_HashTable *tablePtr, void *keyPtr);
/*
* Function prototypes for static functions in this file:
@@ -774,7 +774,7 @@ CompareArrayKeys(
*----------------------------------------------------------------------
*/
static unsigned int
static TCL_HASH_TYPE
HashArrayKey(
Tcl_HashTable *tablePtr, /* Hash table. */
void *keyPtr) /* Key from which to compute hash value. */
@@ -787,7 +787,7 @@ HashArrayKey(
count--, array++) {
result += *array;
}
return result;
return (TCL_HASH_TYPE) result;
}
/*
@@ -870,7 +870,7 @@ CompareStringKeys(
*----------------------------------------------------------------------
*/
static unsigned
static TCL_HASH_TYPE
HashStringKey(
Tcl_HashTable *tablePtr, /* Hash table. */
void *keyPtr) /* Key from which to compute hash value. */
@@ -916,7 +916,7 @@ HashStringKey(
result += (result << 3) + UCHAR(c);
}
}
return result;
return (TCL_HASH_TYPE) result;
}
/*
+73 -86
View File
@@ -313,15 +313,20 @@ static int WillRead(Channel *chanPtr);
&& (strncmp(optionName, (nameString), len) == 0))
/*
* The ChannelObjType type. We actually store the ChannelState structure
* as that lives longest and we want to return the bottomChanPtr when
* requested (consistent with Tcl_GetChannel). The setFromAny and
* updateString can be NULL as they should not be called.
* The ChannelObjType type. Used to store the result of looking up
* a channel name in the context of an interp. Saves the lookup
* result and values needed to check its continued validity.
*/
typedef struct ResolvedChanName {
ChannelState *statePtr; /* The saved lookup result */
Tcl_Interp *interp; /* The interp in which the lookup was done. */
int epoch; /* The epoch of the channel when the lookup
* was done. Use to verify validity. */
int refCount; /* Share this struct among many Tcl_Obj. */
} ResolvedChanName;
static void DupChannelIntRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
static int SetChannelFromAny(Tcl_Interp *interp,
Tcl_Obj *objPtr);
static void FreeChannelIntRep(Tcl_Obj *objPtr);
static const Tcl_ObjType chanObjType = {
@@ -329,18 +334,9 @@ static const Tcl_ObjType chanObjType = {
FreeChannelIntRep, /* freeIntRepProc */
DupChannelIntRep, /* dupIntRepProc */
NULL, /* updateStringProc */
NULL /* setFromAnyProc SetChannelFromAny */
NULL /* setFromAnyProc */
};
#define GET_CHANNELSTATE(objPtr) \
((ChannelState *) (objPtr)->internalRep.twoPtrValue.ptr1)
#define SET_CHANNELSTATE(objPtr, storePtr) \
((objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (storePtr))
#define GET_CHANNELINTERP(objPtr) \
((Tcl_Interp *) (objPtr)->internalRep.twoPtrValue.ptr2)
#define SET_CHANNELINTERP(objPtr, storePtr) \
((objPtr)->internalRep.twoPtrValue.ptr2 = (void *) (storePtr))
#define BUSY_STATE(st, fl) \
((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \
(((st)->csPtrW) && ((fl) & TCL_WRITABLE)))
@@ -1021,7 +1017,7 @@ DeleteChannelTable(
*/
Tcl_DeleteHashEntry(hPtr);
SetFlag(statePtr, CHANNEL_TAINTED);
statePtr->epoch++;
if (statePtr->refCount-- <= 1) {
if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
(void) Tcl_Close(interp, (Tcl_Channel) chanPtr);
@@ -1365,7 +1361,7 @@ DetachChannel(
return TCL_ERROR;
}
Tcl_DeleteHashEntry(hPtr);
SetFlag(statePtr, CHANNEL_TAINTED);
statePtr->epoch++;
/*
* Remove channel handlers that refer to this interpreter, so that
@@ -1498,12 +1494,57 @@ TclGetChannelFromObj(
int flags)
{
ChannelState *statePtr;
ResolvedChanName *resPtr = NULL;
Tcl_Channel chan;
if (SetChannelFromAny(interp, objPtr) != TCL_OK) {
if (interp == NULL) {
return TCL_ERROR;
}
statePtr = GET_CHANNELSTATE(objPtr);
if (objPtr->typePtr == &chanObjType) {
/*
* Confirm validity of saved lookup results.
*/
resPtr = (ResolvedChanName *) objPtr->internalRep.twoPtrValue.ptr1;
statePtr = resPtr->statePtr;
if ((resPtr->interp == interp) /* Same interp context */
/* No epoch change in channel since lookup */
&& (resPtr->epoch == statePtr->epoch)) {
/* Have a valid saved lookup. Jump to end to return it. */
goto valid;
}
}
chan = Tcl_GetChannel(interp, TclGetString(objPtr), NULL);
if (chan == NULL) {
if (resPtr) {
FreeChannelIntRep(objPtr);
}
return TCL_ERROR;
}
if (resPtr && resPtr->refCount == 1) {
/* Re-use the ResolvedCmdName struct */
Tcl_Release((ClientData) resPtr->statePtr);
} else {
TclFreeIntRep(objPtr);
resPtr = (ResolvedChanName *) ckalloc(sizeof(ResolvedChanName));
resPtr->refCount = 1;
objPtr->internalRep.twoPtrValue.ptr1 = (ClientData) resPtr;
objPtr->typePtr = &chanObjType;
}
statePtr = ((Channel *)chan)->state;
resPtr->statePtr = statePtr;
Tcl_Preserve((ClientData) statePtr);
resPtr->interp = interp;
resPtr->epoch = statePtr->epoch;
valid:
*channelPtr = (Tcl_Channel) statePtr->bottomChanPtr;
if (modePtr != NULL) {
@@ -1676,6 +1717,8 @@ Tcl_CreateChannel(
statePtr->chanMsg = NULL;
statePtr->unreportedMsg = NULL;
statePtr->epoch = 0;
/*
* Link the channel into the list of all channels; create an on-exit
* handler if there is not one already, to close off all the channels in
@@ -11121,75 +11164,13 @@ DupChannelIntRep(
register Tcl_Obj *copyPtr) /* Object with internal rep to set. Must not
* currently have an internal rep.*/
{
ChannelState *statePtr = GET_CHANNELSTATE(srcPtr);
ResolvedChanName *resPtr = srcPtr->internalRep.twoPtrValue.ptr1;
SET_CHANNELSTATE(copyPtr, statePtr);
SET_CHANNELINTERP(copyPtr, GET_CHANNELINTERP(srcPtr));
Tcl_Preserve(statePtr);
resPtr->refCount++;
copyPtr->internalRep.twoPtrValue.ptr1 = resPtr;
copyPtr->typePtr = srcPtr->typePtr;
}
/*
*----------------------------------------------------------------------
*
* SetChannelFromAny --
*
* Create an internal representation of type "Channel" for an object.
*
* Results:
* This operation always succeeds and returns TCL_OK.
*
* Side effects:
* Any old internal reputation for objPtr is freed and the internal
* representation is set to "Channel".
*
*----------------------------------------------------------------------
*/
static int
SetChannelFromAny(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
register Tcl_Obj *objPtr) /* The object to convert. */
{
ChannelState *statePtr;
if (interp == NULL) {
return TCL_ERROR;
}
if (objPtr->typePtr == &chanObjType) {
/*
* TODO: TAINT Flag and dup'd channel values?
* The channel is valid until any call to DetachChannel occurs.
* Ensure consistency checks are done.
*/
statePtr = GET_CHANNELSTATE(objPtr);
if (GotFlag(statePtr, CHANNEL_TAINTED|CHANNEL_CLOSED)) {
ResetFlag(statePtr, CHANNEL_TAINTED);
Tcl_Release(statePtr);
objPtr->typePtr = NULL;
} else if (interp != GET_CHANNELINTERP(objPtr)) {
Tcl_Release(statePtr);
objPtr->typePtr = NULL;
}
}
if (objPtr->typePtr != &chanObjType) {
Tcl_Channel chan = Tcl_GetChannel(interp, TclGetString(objPtr), NULL);
if (chan == NULL) {
return TCL_ERROR;
}
TclFreeIntRep(objPtr);
statePtr = ((Channel *) chan)->state;
Tcl_Preserve(statePtr);
SET_CHANNELSTATE(objPtr, statePtr);
SET_CHANNELINTERP(objPtr, interp);
objPtr->typePtr = &chanObjType;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
@@ -11210,8 +11191,14 @@ static void
FreeChannelIntRep(
Tcl_Obj *objPtr) /* Object with internal rep to free. */
{
Tcl_Release(GET_CHANNELSTATE(objPtr));
ResolvedChanName *resPtr = objPtr->internalRep.twoPtrValue.ptr1;
objPtr->typePtr = NULL;
if (--resPtr->refCount) {
return;
}
Tcl_Release(resPtr->statePtr);
ckfree(resPtr);
}
#if 0
+2 -4
View File
@@ -214,6 +214,8 @@ typedef struct ChannelState {
* because it happened in the background. The
* value is the chanMg, if any. #219's
* companion to 'unreportedError'. */
int epoch; /* Used to test validity of stored channelname
* lookup results. */
} ChannelState;
/*
@@ -275,10 +277,6 @@ typedef struct ChannelState {
* usable, but it may not be closed
* again from within the close
* handler. */
#define CHANNEL_TAINTED (1<<20) /* Channel stack structure has changed.
* Used by Channel Tcl_Obj type to
* determine if we have to revalidate
* the channel. */
#define CHANNEL_CLOSEDWRITE (1<<21) /* Channel write side has been closed.
* No further Tcl-level write IO on
* the channel is allowed. */
+4 -4
View File
@@ -1946,7 +1946,7 @@ ReflectGetOption(
goto error;
} else {
int len;
const char *str = Tcl_GetStringFromObj(resObj, &len);
const char *str = TclGetStringFromObj(resObj, &len);
if (len) {
TclDStringAppendLiteral(dsPtr, " ");
@@ -2319,7 +2319,7 @@ InvokeTclMethod(
if (result != TCL_ERROR) {
int cmdLen;
const char *cmdString = Tcl_GetStringFromObj(cmd, &cmdLen);
const char *cmdString = TclGetStringFromObj(cmd, &cmdLen);
Tcl_IncrRefCount(cmd);
Tcl_ResetResult(rcPtr->interp);
@@ -3174,7 +3174,7 @@ ForwardProc(
ForwardSetDynamicError(paramPtr, buf);
} else {
int len;
const char *str = Tcl_GetStringFromObj(resObj, &len);
const char *str = TclGetStringFromObj(resObj, &len);
if (len) {
TclDStringAppendLiteral(paramPtr->getOpt.value, " ");
@@ -3273,7 +3273,7 @@ ForwardSetObjError(
Tcl_Obj *obj)
{
int len;
const char *msgStr = Tcl_GetStringFromObj(obj, &len);
const char *msgStr = TclGetStringFromObj(obj, &len);
len++;
ForwardSetDynamicError(paramPtr, ckalloc(len));
+2 -2
View File
@@ -2043,7 +2043,7 @@ InvokeTclMethod(
if (result != TCL_ERROR) {
Tcl_Obj *cmd = Tcl_NewListObj(cmdc, rtPtr->argv);
int cmdLen;
const char *cmdString = Tcl_GetStringFromObj(cmd, &cmdLen);
const char *cmdString = TclGetStringFromObj(cmd, &cmdLen);
Tcl_IncrRefCount(cmd);
Tcl_ResetResult(rtPtr->interp);
@@ -2807,7 +2807,7 @@ ForwardSetObjError(
Tcl_Obj *obj)
{
int len;
const char *msgStr = Tcl_GetStringFromObj(obj, &len);
const char *msgStr = TclGetStringFromObj(obj, &len);
len++;
ForwardSetDynamicError(paramPtr, ckalloc(len));
+1 -1
View File
@@ -197,7 +197,7 @@ TclCreateSocketAddress(
*/
if (interp != NULL) {
family = Tcl_GetVar(interp, "::tcl::unsupported::socketAF", 0);
family = Tcl_GetVar2(interp, "::tcl::unsupported::socketAF", NULL, 0);
if (family != NULL) {
if (strcmp(family, "inet") == 0) {
hints.ai_family = AF_INET;
+15 -16
View File
@@ -71,8 +71,7 @@ typedef struct ThreadSpecificData {
* Prototypes for functions defined later in this file.
*/
static int EvalFileCallback(ClientData data[],
Tcl_Interp *interp, int result);
static Tcl_NRPostProc EvalFileCallback;
static FilesystemRecord*FsGetFirstFilesystem(void);
static void FsThrExitProc(ClientData cd);
static Tcl_Obj * FsListMounts(Tcl_Obj *pathPtr, const char *pattern);
@@ -545,8 +544,8 @@ TclFSCwdPointerEquals(
int len1, len2;
const char *str1, *str2;
str1 = Tcl_GetStringFromObj(tsdPtr->cwdPathPtr, &len1);
str2 = Tcl_GetStringFromObj(*pathPtrPtr, &len2);
str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1);
str2 = TclGetStringFromObj(*pathPtrPtr, &len2);
if ((len1 == len2) && !memcmp(str1, str2, len1)) {
/*
* They are equal, but different objects. Update so they will be
@@ -689,7 +688,7 @@ FsUpdateCwd(
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
if (cwdObj != NULL) {
str = Tcl_GetStringFromObj(cwdObj, &len);
str = TclGetStringFromObj(cwdObj, &len);
}
Tcl_MutexLock(&cwdMutex);
@@ -1225,8 +1224,8 @@ FsAddMountsToGlobResult(
if (norm != NULL) {
const char *path, *mount;
mount = Tcl_GetStringFromObj(mElt, &mlen);
path = Tcl_GetStringFromObj(norm, &len);
mount = TclGetStringFromObj(mElt, &mlen);
path = TclGetStringFromObj(norm, &len);
if (path[len-1] == '/') {
/*
* Deal with the root of the volume.
@@ -1817,7 +1816,7 @@ Tcl_FSEvalFileEx(
oldScriptFile = iPtr->scriptFile;
iPtr->scriptFile = pathPtr;
Tcl_IncrRefCount(iPtr->scriptFile);
string = Tcl_GetStringFromObj(objPtr, &length);
string = TclGetStringFromObj(objPtr, &length);
/*
* TIP #280 Force the evaluator to open a frame for a sourced file.
@@ -1844,7 +1843,7 @@ Tcl_FSEvalFileEx(
* Record information telling where the error occurred.
*/
const char *pathString = Tcl_GetStringFromObj(pathPtr, &length);
const char *pathString = TclGetStringFromObj(pathPtr, &length);
int limit = 150;
int overflow = (length > limit);
@@ -1995,7 +1994,7 @@ EvalFileCallback(
*/
int length;
const char *pathString = Tcl_GetStringFromObj(pathPtr, &length);
const char *pathString = TclGetStringFromObj(pathPtr, &length);
const int limit = 150;
int overflow = (length > limit);
@@ -2847,8 +2846,8 @@ Tcl_FSGetCwd(
int len1, len2;
const char *str1, *str2;
str1 = Tcl_GetStringFromObj(tsdPtr->cwdPathPtr, &len1);
str2 = Tcl_GetStringFromObj(norm, &len2);
str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1);
str2 = TclGetStringFromObj(norm, &len2);
if ((len1 == len2) && (strcmp(str1, str2) == 0)) {
/*
* If the paths were equal, we can be more efficient and
@@ -4116,7 +4115,7 @@ TclGetPathType(
* caller. */
{
int pathLen;
const char *path = Tcl_GetStringFromObj(pathPtr, &pathLen);
const char *path = TclGetStringFromObj(pathPtr, &pathLen);
Tcl_PathType type;
type = TclFSNonnativePathType(path, pathLen, filesystemPtrPtr,
@@ -4228,7 +4227,7 @@ TclFSNonnativePathType(
numVolumes--;
Tcl_ListObjIndex(NULL, thisFsVolumes, numVolumes, &vol);
strVol = Tcl_GetStringFromObj(vol,&len);
strVol = TclGetStringFromObj(vol,&len);
if (pathLen < len) {
continue;
}
@@ -4575,8 +4574,8 @@ Tcl_FSRemoveDirectory(
Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (normPath != NULL) {
normPathStr = Tcl_GetStringFromObj(normPath, &normLen);
cwdStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen);
normPathStr = TclGetStringFromObj(normPath, &normLen);
cwdStr = TclGetStringFromObj(cwdPtr, &cwdLen);
if ((cwdLen >= normLen) && (strncmp(normPathStr, cwdStr,
(size_t) normLen) == 0)) {
/*
+28 -35
View File
@@ -114,14 +114,13 @@ Tcl_GetIndexFromObj(
int flags, /* 0 or TCL_EXACT */
int *indexPtr) /* Place to store resulting integer index. */
{
/*
* See if there is a valid cached result from a previous lookup (doing the
* check here saves the overhead of calling Tcl_GetIndexFromObjStruct in
* the common case where the result is cached).
*/
if (objPtr->typePtr == &indexType) {
if (!(flags & INDEX_TEMP_TABLE) && objPtr->typePtr == &indexType) {
IndexRep *indexRep = objPtr->internalRep.twoPtrValue.ptr1;
/*
@@ -211,13 +210,8 @@ GetIndexFromObjList(
tablePtr[objc] = NULL;
result = Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr,
sizeof(char *), msg, flags, indexPtr);
sizeof(char *), msg, flags | INDEX_TEMP_TABLE, indexPtr);
/*
* The internal rep must be cleared since tablePtr will go away.
*/
TclFreeIntRep(objPtr);
ckfree(tablePtr);
return result;
@@ -279,7 +273,7 @@ Tcl_GetIndexFromObjStruct(
* See if there is a valid cached result from a previous lookup.
*/
if (objPtr->typePtr == &indexType) {
if (!(flags & INDEX_TEMP_TABLE) && objPtr->typePtr == &indexType) {
indexRep = objPtr->internalRep.twoPtrValue.ptr1;
if (indexRep->tablePtr==tablePtr && indexRep->offset==offset) {
*indexPtr = indexRep->index;
@@ -340,17 +334,19 @@ Tcl_GetIndexFromObjStruct(
* operation.
*/
if (objPtr->typePtr == &indexType) {
indexRep = objPtr->internalRep.twoPtrValue.ptr1;
} else {
TclFreeIntRep(objPtr);
indexRep = ckalloc(sizeof(IndexRep));
objPtr->internalRep.twoPtrValue.ptr1 = indexRep;
objPtr->typePtr = &indexType;
if (!(flags & INDEX_TEMP_TABLE)) {
if (objPtr->typePtr == &indexType) {
indexRep = objPtr->internalRep.twoPtrValue.ptr1;
} else {
TclFreeIntRep(objPtr);
indexRep = ckalloc(sizeof(IndexRep));
objPtr->internalRep.twoPtrValue.ptr1 = indexRep;
objPtr->typePtr = &indexType;
}
indexRep->tablePtr = (void *) tablePtr;
indexRep->offset = offset;
indexRep->index = index;
}
indexRep->tablePtr = (void *) tablePtr;
indexRep->offset = offset;
indexRep->index = index;
*indexPtr = index;
return TCL_OK;
@@ -712,10 +708,10 @@ PrefixAllObjCmd(
return result;
}
resultPtr = Tcl_NewListObj(0, NULL);
string = Tcl_GetStringFromObj(objv[2], &length);
string = TclGetStringFromObj(objv[2], &length);
for (t = 0; t < tableObjc; t++) {
elemString = Tcl_GetStringFromObj(tableObjv[t], &elemLength);
elemString = TclGetStringFromObj(tableObjv[t], &elemLength);
/*
* A prefix cannot match if it is longest.
@@ -768,13 +764,13 @@ PrefixLongestObjCmd(
if (result != TCL_OK) {
return result;
}
string = Tcl_GetStringFromObj(objv[2], &length);
string = TclGetStringFromObj(objv[2], &length);
resultString = NULL;
resultLength = 0;
for (t = 0; t < tableObjc; t++) {
elemString = Tcl_GetStringFromObj(tableObjv[t], &elemLength);
elemString = TclGetStringFromObj(tableObjv[t], &elemLength);
/*
* First check if the prefix string matches the element. A prefix
@@ -924,6 +920,14 @@ Tcl_WrongNumArgs(
int toPrint = iPtr->ensembleRewrite.numRemovedObjs;
Tcl_Obj *const *origObjv = iPtr->ensembleRewrite.sourceObjs;
/*
* Check for spelling fixes, and substitute the fixed values.
*/
if (origObjv[0] == NULL) {
origObjv = (Tcl_Obj *const *)origObjv[2];
}
/*
* We only know how to do rewriting if all the replaced objects are
* actually arguments (in objv) to this function. Otherwise it just
@@ -957,12 +961,6 @@ Tcl_WrongNumArgs(
elementStr = EXPAND_OF(indexRep);
elemLen = strlen(elementStr);
} else if (origObjv[i]->typePtr == &tclEnsembleCmdType) {
register EnsembleCmdRep *ecrPtr =
origObjv[i]->internalRep.twoPtrValue.ptr1;
elementStr = ecrPtr->fullSubcmdName;
elemLen = strlen(elementStr);
} else {
elementStr = TclGetStringFromObj(origObjv[i], &elemLen);
}
@@ -1011,11 +1009,6 @@ Tcl_WrongNumArgs(
register IndexRep *indexRep = objv[i]->internalRep.twoPtrValue.ptr1;
Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), NULL);
} else if (objv[i]->typePtr == &tclEnsembleCmdType) {
register EnsembleCmdRep *ecrPtr =
objv[i]->internalRep.twoPtrValue.ptr1;
Tcl_AppendStringsToObj(objPtr, ecrPtr->fullSubcmdName, NULL);
} else {
/*
* Quote the argument if it contains spaces (Bug 942757).
@@ -1151,7 +1144,7 @@ Tcl_ParseArgsObjv(
curArg = objv[srcIndex];
srcIndex++;
objc--;
str = Tcl_GetStringFromObj(curArg, &length);
str = TclGetStringFromObj(curArg, &length);
if (length > 0) {
c = str[1];
} else {
+1 -1
View File
@@ -1009,7 +1009,7 @@ declare 250 {
# Allow extensions for optimization
declare 251 {
int TclRegisterLiteral(void *envPtr,
char *bytes, int length, int flags)
const char *bytes, int length, int flags)
}
##############################################################################
+58 -30
View File
@@ -25,6 +25,19 @@
#undef ACCEPT_NAN
/*
* In Tcl 8.7, stop supporting special hacks for legacy Itcl 3.
* Itcl 4 doesn't need them. Itcl 3 can be updated to not need them
* using the Tcl(Init|Reset)RewriteEnsemble() routines in all Tcl 8.6+
* releases. Perhaps Tcl 8.7 will add even better public interfaces
* supporting all the re-invocation mechanisms extensions like Itcl 3
* need. As an absolute last resort, folks who must make Itcl 3 work
* unchanged with Tcl 8.7 can remove this line to regain the migration
* support. Tcl 9 will no longer offer even that option.
*/
#define AVOID_HACKS_FOR_ITCL 1
/*
* Common include files needed by most of the Tcl source files are included
* here, so that system-dependent personalizations for the include files only
@@ -48,7 +61,8 @@
#else
#include <string.h>
#endif
#ifdef STDC_HEADERS
#if defined(STDC_HEADERS) || defined(__STDC__) || defined(__C99__FUNC__) \
|| defined(__cplusplus) || defined(_MSC_VER)
#include <stddef.h>
#else
typedef int ptrdiff_t;
@@ -168,6 +182,21 @@ typedef struct Tcl_ResolverInfo {
* at compile time. */
} Tcl_ResolverInfo;
/*
* This flag bit should not interfere with TCL_GLOBAL_ONLY,
* TCL_NAMESPACE_ONLY, or TCL_LEAVE_ERR_MSG; it signals that the variable
* lookup is performed for upvar (or similar) purposes, with slightly
* different rules:
* - Bug #696893 - variable is either proc-local or in the current
* namespace; never follow the second (global) resolution path
* - Bug #631741 - do not use special namespace or interp resolvers
*
* It should also not collide with the (deprecated) TCL_PARSE_PART1 flag
* (Bug #835020)
*/
#define TCL_AVOID_RESOLVERS 0x40000
/*
*----------------------------------------------------------------
* Data structures related to namespaces.
@@ -388,27 +417,6 @@ struct NamespacePathEntry {
#define TCL_CREATE_NS_IF_UNKNOWN 0x800
#define TCL_FIND_ONLY_NS 0x1000
/*
* The data cached in an ensemble subcommand's Tcl_Obj rep (reference in
* twoPtrValue.ptr1 field). This structure is not shared between Tcl_Objs
* referring to the same subcommand, even where one is a duplicate of another.
*/
typedef struct {
Namespace *nsPtr; /* The namespace backing the ensemble which
* this is a subcommand of. */
int epoch; /* Used to confirm when the data in this
* really structure matches up with the
* ensemble. */
Tcl_Command token; /* Reference to the comamnd for which this
* structure is a cache of the resolution. */
char *fullSubcmdName; /* The full (local) name of the subcommand,
* allocated with ckalloc(). */
Tcl_Obj *realPrefixObj; /* Object containing the prefix words of the
* command that implements this ensemble
* subcommand. */
} EnsembleCmdRep;
/*
* The client data for an ensemble command. This consists of the table of
* commands that are actually exported by the namespace, and an epoch counter
@@ -1682,11 +1690,13 @@ typedef struct Command {
* (these last two flags are defined in tcl.h)
*/
#define CMD_IS_DELETED 0x1
#define CMD_TRACE_ACTIVE 0x2
#define CMD_HAS_EXEC_TRACES 0x4
#define CMD_COMPILES_EXPANDED 0x8
#define CMD_IS_DELETED 0x01
#define CMD_TRACE_ACTIVE 0x02
#define CMD_HAS_EXEC_TRACES 0x04
#define CMD_COMPILES_EXPANDED 0x08
#define CMD_REDEF_IN_PROGRESS 0x10
#define CMD_VIA_RESOLVER 0x20
/*
*----------------------------------------------------------------
@@ -2539,6 +2549,15 @@ typedef struct TclFileAttrProcs {
TclSetFileAttrProc *setProc;/* The procedure for setting attrs. */
} TclFileAttrProcs;
/*
* Private flag value which controls Tcl_GetIndexFromObj*() routines
* to instruct them not to cache lookups because the table will not
* live long enough to make it worthwhile. Must not clash with public
* flag value TCL_EXACT.
*/
#define INDEX_TEMP_TABLE 2
/*
* Opaque handle used in pipeline routines to encapsulate platform-dependent
* state.
@@ -2690,7 +2709,6 @@ MODULE_SCOPE const Tcl_ObjType tclListType;
MODULE_SCOPE const Tcl_ObjType tclDictType;
MODULE_SCOPE const Tcl_ObjType tclProcBodyType;
MODULE_SCOPE const Tcl_ObjType tclStringType;
MODULE_SCOPE const Tcl_ObjType tclArraySearchType;
MODULE_SCOPE const Tcl_ObjType tclEnsembleCmdType;
#ifndef TCL_WIDE_INT_IS_LONG
MODULE_SCOPE const Tcl_ObjType tclWideIntType;
@@ -2761,6 +2779,7 @@ MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldmObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldToObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRInvoke;
MODULE_SCOPE Tcl_NRPostProc TclNRReleaseValues;
MODULE_SCOPE void TclSetTailcall(Tcl_Interp *interp, Tcl_Obj *tailcallPtr);
MODULE_SCOPE void TclPushTailcallPoint(Tcl_Interp *interp);
@@ -2871,8 +2890,7 @@ MODULE_SCOPE int TclCheckBadOctal(Tcl_Interp *interp,
MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp,
Tcl_Channel chan);
MODULE_SCOPE Tcl_ObjCmdProc TclChannelNamesCmd;
MODULE_SCOPE int TclClearRootEnsemble(ClientData data[],
Tcl_Interp *interp, int result);
MODULE_SCOPE Tcl_NRPostProc TclClearRootEnsemble;
MODULE_SCOPE ContLineLoc *TclContinuationsEnter(Tcl_Obj *objPtr, int num,
int *loc);
MODULE_SCOPE void TclContinuationsEnterDerived(Tcl_Obj *objPtr,
@@ -2908,6 +2926,8 @@ MODULE_SCOPE char * TclDStringAppendObj(Tcl_DString *dsPtr,
MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr,
Tcl_DString *toAppendPtr);
MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr);
MODULE_SCOPE Tcl_Obj *const * TclFetchEnsembleRoot(Tcl_Interp *interp,
Tcl_Obj *const *objv, int objc, int *objcPtr);
MODULE_SCOPE void TclFinalizeAllocSubsystem(void);
MODULE_SCOPE void TclFinalizeAsync(void);
MODULE_SCOPE void TclFinalizeDoubleConversion(void);
@@ -3110,8 +3130,16 @@ MODULE_SCOPE void TclSetDuplicateObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr);
MODULE_SCOPE void TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr,
Tcl_Obj *newValue, Tcl_Encoding encoding);
MODULE_SCOPE void TclSignalExitThread(Tcl_ThreadId id, int result);
MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp,
Tcl_Obj *const *objv, int objc, int subIdx,
Tcl_Obj *bad, Tcl_Obj *fix);
MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr,
int numBytes);
MODULE_SCOPE int TclStringCatObjv(Tcl_Interp *interp, int inPlace,
int objc, Tcl_Obj *const objv[],
Tcl_Obj **objPtrPtr);
MODULE_SCOPE int TclStringFind(Tcl_Obj *needle, Tcl_Obj *haystack,
unsigned int start);
MODULE_SCOPE int TclStringMatch(const char *str, int strLen,
const char *pattern, int ptnLen, int flags);
MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj,
@@ -3964,7 +3992,7 @@ MODULE_SCOPE int TclObjCallVarTraces(Interp *iPtr, Var *arrayPtr,
MODULE_SCOPE int TclCompareObjKeys(void *keyPtr, Tcl_HashEntry *hPtr);
MODULE_SCOPE void TclFreeObjEntry(Tcl_HashEntry *hPtr);
MODULE_SCOPE unsigned TclHashObjKey(Tcl_HashTable *tablePtr, void *keyPtr);
MODULE_SCOPE TCL_HASH_TYPE TclHashObjKey(Tcl_HashTable *tablePtr, void *keyPtr);
MODULE_SCOPE int TclFullFinalizationRequested(void);
+2 -2
View File
@@ -615,7 +615,7 @@ EXTERN char * TclDoubleDigits(double dv, int ndigits, int flags,
EXTERN void TclSetSlaveCancelFlags(Tcl_Interp *interp, int flags,
int force);
/* 251 */
EXTERN int TclRegisterLiteral(void *envPtr, char *bytes,
EXTERN int TclRegisterLiteral(void *envPtr, const char *bytes,
int length, int flags);
typedef struct TclIntStubs {
@@ -873,7 +873,7 @@ typedef struct TclIntStubs {
int (*tclCopyChannel) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr); /* 248 */
char * (*tclDoubleDigits) (double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 249 */
void (*tclSetSlaveCancelFlags) (Tcl_Interp *interp, int flags, int force); /* 250 */
int (*tclRegisterLiteral) (void *envPtr, char *bytes, int length, int flags); /* 251 */
int (*tclRegisterLiteral) (void *envPtr, const char *bytes, int length, int flags); /* 251 */
} TclIntStubs;
extern const TclIntStubs *tclIntStubsPtr;
+18 -47
View File
@@ -336,7 +336,7 @@ Tcl_Init(
Tcl_Interp *interp) /* Interpreter to initialize. */
{
if (tclPreInitScript != NULL) {
if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
if (Tcl_EvalEx(interp, tclPreInitScript, -1, 0) == TCL_ERROR) {
return TCL_ERROR;
}
}
@@ -382,7 +382,7 @@ Tcl_Init(
* alternate tclInit command before calling Tcl_Init().
*/
return Tcl_Eval(interp,
return Tcl_EvalEx(interp,
"if {[namespace which -command tclInit] eq \"\"} {\n"
" proc tclInit {} {\n"
" global tcl_libPath tcl_library env tclDefaultLibrary\n"
@@ -444,7 +444,7 @@ Tcl_Init(
" error $msg\n"
" }\n"
"}\n"
"tclInit");
"tclInit", -1, 0);
}
/*
@@ -660,14 +660,9 @@ NRInterpCmd(
if (masterInterp == NULL) {
return TCL_ERROR;
}
if (TclGetString(objv[5])[0] == '\0') {
if (objc == 6) {
return AliasDelete(interp, slaveInterp, objv[3]);
}
} else {
return AliasCreate(interp, slaveInterp, masterInterp, objv[3],
objv[5], objc - 6, objv + 6);
}
return AliasCreate(interp, slaveInterp, masterInterp, objv[3],
objv[5], objc - 6, objv + 6);
}
goto aliasArgs;
}
@@ -1795,11 +1790,9 @@ AliasNRCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument vector. */
{
Interp *iPtr = (Interp *) interp;
Alias *aliasPtr = clientData;
int prefc, cmdc, i;
Tcl_Obj **prefv, **cmdv;
int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL);
Tcl_Obj *listPtr;
List *listRep;
int flags = TCL_EVAL_INVOKE;
@@ -1831,21 +1824,7 @@ AliasNRCmd(
* only the source command should show, not the full target prefix.
*/
if (isRootEnsemble) {
iPtr->ensembleRewrite.sourceObjs = objv;
iPtr->ensembleRewrite.numRemovedObjs = 1;
iPtr->ensembleRewrite.numInsertedObjs = prefc;
} else {
iPtr->ensembleRewrite.numInsertedObjs += prefc - 1;
}
/*
* We are sending a 0-refCount obj, do not need a callback: it will be
* cleaned up automatically. But we may need to clear the rootEnsemble
* stuff ...
*/
if (isRootEnsemble) {
if (TclInitRewriteEnsemble(interp, 1, prefc, objv)) {
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
}
TclSkipTailcall(interp);
@@ -1866,7 +1845,7 @@ AliasObjCmd(
Tcl_Obj **prefv, **cmdv;
Tcl_Obj *cmdArr[ALIAS_CMDV_PREALLOC];
Interp *tPtr = (Interp *) targetInterp;
int isRootEnsemble = (tPtr->ensembleRewrite.sourceObjs == NULL);
int isRootEnsemble;
/*
* Append the arguments to the command prefix and invoke the command in
@@ -1896,13 +1875,7 @@ AliasObjCmd(
* only the source command should show, not the full target prefix.
*/
if (isRootEnsemble) {
tPtr->ensembleRewrite.sourceObjs = objv;
tPtr->ensembleRewrite.numRemovedObjs = 1;
tPtr->ensembleRewrite.numInsertedObjs = prefc;
} else {
tPtr->ensembleRewrite.numInsertedObjs += prefc - 1;
}
isRootEnsemble = TclInitRewriteEnsemble((Tcl_Interp *)tPtr, 1, prefc, objv);
/*
* Protect the target interpreter if it isn't the same as the source
@@ -1925,9 +1898,7 @@ AliasObjCmd(
*/
if (isRootEnsemble) {
tPtr->ensembleRewrite.sourceObjs = NULL;
tPtr->ensembleRewrite.numRemovedObjs = 0;
tPtr->ensembleRewrite.numInsertedObjs = 0;
TclResetRewriteEnsemble((Tcl_Interp *)tPtr, 1);
}
/*
@@ -2392,7 +2363,7 @@ SlaveCreate(
SlaveObjCmd, NRSlaveCmd, slaveInterp, SlaveObjCmdDeleteProc);
Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS);
Tcl_SetHashValue(hPtr, slavePtr);
Tcl_SetVar(slaveInterp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Tcl_SetVar2(slaveInterp, "tcl_interactive", NULL, "0", TCL_GLOBAL_ONLY);
/*
* Inherit the recursion limit.
@@ -3219,8 +3190,8 @@ Tcl_MakeSafe(
* Assume these functions all work. [Bug 2895741]
*/
(void) Tcl_Eval(interp,
"namespace eval ::tcl {namespace eval mathfunc {}}");
(void) Tcl_EvalEx(interp,
"namespace eval ::tcl {namespace eval mathfunc {}}", -1, 0);
(void) Tcl_CreateAlias(interp, "::tcl::mathfunc::min", master,
"::tcl::mathfunc::min", 0, NULL);
(void) Tcl_CreateAlias(interp, "::tcl::mathfunc::max", master,
@@ -4526,7 +4497,7 @@ SlaveCommandLimitCmd(
switch ((enum Options) index) {
case OPT_CMD:
scriptObj = objv[i+1];
(void) Tcl_GetStringFromObj(objv[i+1], &scriptLen);
(void) TclGetStringFromObj(scriptObj, &scriptLen);
break;
case OPT_GRAN:
granObj = objv[i+1];
@@ -4543,7 +4514,7 @@ SlaveCommandLimitCmd(
break;
case OPT_VAL:
limitObj = objv[i+1];
(void) Tcl_GetStringFromObj(objv[i+1], &limitLen);
(void) TclGetStringFromObj(objv[i+1], &limitLen);
if (limitLen == 0) {
break;
}
@@ -4735,7 +4706,7 @@ SlaveTimeLimitCmd(
switch ((enum Options) index) {
case OPT_CMD:
scriptObj = objv[i+1];
(void) Tcl_GetStringFromObj(objv[i+1], &scriptLen);
(void) TclGetStringFromObj(objv[i+1], &scriptLen);
break;
case OPT_GRAN:
granObj = objv[i+1];
@@ -4752,7 +4723,7 @@ SlaveTimeLimitCmd(
break;
case OPT_MILLI:
milliObj = objv[i+1];
(void) Tcl_GetStringFromObj(objv[i+1], &milliLen);
(void) TclGetStringFromObj(objv[i+1], &milliLen);
if (milliLen == 0) {
break;
}
@@ -4770,7 +4741,7 @@ SlaveTimeLimitCmd(
break;
case OPT_SEC:
secObj = objv[i+1];
(void) Tcl_GetStringFromObj(objv[i+1], &secLen);
(void) TclGetStringFromObj(objv[i+1], &secLen);
if (secLen == 0) {
break;
}
+1 -1
View File
@@ -526,7 +526,7 @@ LinkTraceProc(
break;
case TCL_LINK_STRING:
value = Tcl_GetStringFromObj(valueObj, &valueLength);
value = TclGetStringFromObj(valueObj, &valueLength);
valueLength++;
pp = (char **) linkPtr->addr;
+7 -7
View File
@@ -897,18 +897,18 @@ Tcl_ListObjReplace(
}
if (count < 0) {
count = 0;
} else if (numElems < first+count || first+count < 0) {
/*
* The 'first+count < 0' condition here guards agains integer
* overflow in determining 'first+count'.
*/
} else if (first > INT_MAX - count /* Handle integer overflow */
|| numElems < first+count) {
count = numElems - first;
}
if (objc > LIST_MAX - (numElems - count)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"max length of a Tcl list (%d elements) exceeded", LIST_MAX));
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"max length of a Tcl list (%d elements) exceeded",
LIST_MAX));
}
return TCL_ERROR;
}
isShared = (listRepPtr->refCount > 1);
+32 -23
View File
@@ -174,7 +174,7 @@ TclDeleteLiteralTable(
Tcl_Obj *
TclCreateLiteral(
Interp *iPtr,
char *bytes, /* The start of the string. Note that this is
const char *bytes, /* The start of the string. Note that this is
* not a NUL-terminated string. */
int length, /* Number of bytes in the string. */
unsigned hash, /* The string's hash. If -1, it will be
@@ -214,7 +214,7 @@ TclCreateLiteral(
if (globalPtrPtr) {
*globalPtrPtr = globalPtr;
}
if (flags & LITERAL_ON_HEAP) {
if ((flags & LITERAL_ON_HEAP)) {
ckfree(bytes);
}
globalPtr->refCount++;
@@ -222,26 +222,40 @@ TclCreateLiteral(
}
}
if (!newPtr) {
if (flags & LITERAL_ON_HEAP) {
if ((flags & LITERAL_ON_HEAP)) {
ckfree(bytes);
}
return NULL;
}
/*
* The literal is new to the interpreter. Add it to the global literal
* table.
* The literal is new to the interpreter.
*/
TclNewObj(objPtr);
Tcl_IncrRefCount(objPtr);
if (flags & LITERAL_ON_HEAP) {
objPtr->bytes = bytes;
if ((flags & LITERAL_ON_HEAP)) {
objPtr->bytes = (char *) bytes;
objPtr->length = length;
} else {
TclInitStringRep(objPtr, bytes, length);
}
/* Should the new literal be shared globally? */
if ((flags & LITERAL_UNSHARED)) {
/*
* No, do *not* add it the global literal table
* Make clear, that no global value is returned
*/
if (globalPtrPtr != NULL) {
*globalPtrPtr = NULL;
}
return objPtr;
}
/*
* Yes, add it to the global literal table.
*/
#ifdef TCL_COMPILE_DEBUG
if (LookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
Tcl_Panic("%s: literal \"%.*s\" found globally but shouldn't be",
@@ -251,6 +265,7 @@ TclCreateLiteral(
globalPtr = ckalloc(sizeof(LiteralEntry));
globalPtr->objPtr = objPtr;
Tcl_IncrRefCount(objPtr);
globalPtr->refCount = 1;
globalPtr->nsPtr = nsPtr;
globalPtr->nextPtr = globalTablePtr->buckets[globalHash];
@@ -360,7 +375,7 @@ int
TclRegisterLiteral(
void *ePtr, /* Points to the CompileEnv in whose object
* array an object is found or created. */
register char *bytes, /* Points to string for which to find or
register const char *bytes, /* Points to string for which to find or
* create an object in CompileEnv's object
* array. */
int length, /* Number of bytes in the string. If < 0, the
@@ -398,7 +413,7 @@ TclRegisterLiteral(
if ((objPtr->length == length) && ((length == 0)
|| ((objPtr->bytes[0] == bytes[0])
&& (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) {
if (flags & LITERAL_ON_HEAP) {
if ((flags & LITERAL_ON_HEAP)) {
ckfree(bytes);
}
objIndex = (localPtr - envPtr->literalArrayPtr);
@@ -417,7 +432,7 @@ TclRegisterLiteral(
* the namespace as the interp's global NS.
*/
if (flags & LITERAL_CMD_NAME) {
if ((flags & LITERAL_CMD_NAME)) {
if ((length >= 2) && (bytes[0] == ':') && (bytes[1] == ':')) {
nsPtr = iPtr->globalNsPtr;
} else {
@@ -431,12 +446,13 @@ TclRegisterLiteral(
* Is it in the interpreter's global literal table? If not, create it.
*/
globalPtr = NULL;
objPtr = TclCreateLiteral(iPtr, bytes, length, hash, &new, nsPtr, flags,
&globalPtr);
objIndex = AddLocalLiteralEntry(envPtr, objPtr, localHash);
#ifdef TCL_COMPILE_DEBUG
if (globalPtr->refCount < 1) {
if (globalPtr != NULL && globalPtr->refCount < 1) {
Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d",
"TclRegisterLiteral", (length>60? 60 : length), bytes,
globalPtr->refCount);
@@ -671,7 +687,7 @@ AddLocalLiteralEntry(
}
if (!found) {
bytes = Tcl_GetStringFromObj(objPtr, &length);
bytes = TclGetStringFromObj(objPtr, &length);
Tcl_Panic("%s: literal \"%.*s\" wasn't found locally",
"AddLocalLiteralEntry", (length>60? 60 : length), bytes);
}
@@ -1025,7 +1041,7 @@ TclInvalidateCmdLiteral(
* invalidate a cmd literal. */
{
Interp *iPtr = (Interp *) interp;
Tcl_Obj *literalObjPtr = TclCreateLiteral(iPtr, (char *) name,
Tcl_Obj *literalObjPtr = TclCreateLiteral(iPtr, name,
strlen(name), -1, NULL, nsPtr, 0, NULL);
if (literalObjPtr != NULL) {
@@ -1147,18 +1163,11 @@ TclVerifyLocalLiteralTable(
localPtr=localPtr->nextPtr) {
count++;
if (localPtr->refCount != -1) {
bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
bytes = TclGetStringFromObj(localPtr->objPtr, &length);
Tcl_Panic("%s: local literal \"%.*s\" had bad refCount %d",
"TclVerifyLocalLiteralTable",
(length>60? 60 : length), bytes, localPtr->refCount);
}
if (LookupLiteralEntry((Tcl_Interp *) envPtr->iPtr,
localPtr->objPtr) == NULL) {
bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
Tcl_Panic("%s: local literal \"%.*s\" is not global",
"TclVerifyLocalLiteralTable",
(length>60? 60 : length), bytes);
}
if (localPtr->objPtr->bytes == NULL) {
Tcl_Panic("%s: literal has NULL string rep",
"TclVerifyLocalLiteralTable");
@@ -1205,7 +1214,7 @@ TclVerifyGlobalLiteralTable(
globalPtr=globalPtr->nextPtr) {
count++;
if (globalPtr->refCount < 1) {
bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
bytes = TclGetStringFromObj(globalPtr->objPtr, &length);
Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d",
"TclVerifyGlobalLiteralTable",
(length>60? 60 : length), bytes, globalPtr->refCount);
+12 -23
View File
@@ -112,7 +112,7 @@ typedef enum {
PROMPT_CONTINUE /* Print prompt for command continuation */
} PromptType;
typedef struct InteractiveState {
typedef struct {
Tcl_Channel input; /* The standard input channel from which lines
* are read. */
int tty; /* Non-zero means standard input is a
@@ -246,7 +246,7 @@ Tcl_SourceRCFile(
const char *fileName;
Tcl_Channel chan;
fileName = Tcl_GetVar(interp, "tcl_rcFileName", TCL_GLOBAL_ONLY);
fileName = Tcl_GetVar2(interp, "tcl_rcFileName", NULL, TCL_GLOBAL_ONLY);
if (fileName != NULL) {
Tcl_Channel c;
const char *fullName;
@@ -266,14 +266,18 @@ Tcl_SourceRCFile(
c = Tcl_OpenFileChannel(NULL, fullName, "r", 0);
if (c != NULL) {
Tcl_Obj *fullNameObj = Tcl_NewStringObj(fullName, -1);
Tcl_Close(NULL, c);
if (Tcl_EvalFile(interp, fullName) != TCL_OK) {
Tcl_IncrRefCount(fullNameObj);
if (Tcl_FSEvalFileEx(interp, fullNameObj, NULL) != TCL_OK) {
chan = Tcl_GetStdChannel(TCL_STDERR);
if (chan) {
Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
Tcl_WriteChars(chan, "\n", 1);
}
}
Tcl_DecrRefCount(fullNameObj);
}
}
Tcl_DStringFree(&temp);
@@ -283,7 +287,7 @@ Tcl_SourceRCFile(
/*----------------------------------------------------------------------
*
* Tcl_Main, Tcl_MainEx --
* Tcl_MainEx --
*
* Main program for tclsh and most other Tcl-based applications.
*
@@ -532,7 +536,7 @@ Tcl_MainEx(
* error messages troubles deeper in, so lop it back off.
*/
Tcl_GetStringFromObj(is.commandPtr, &length);
TclGetStringFromObj(is.commandPtr, &length);
Tcl_SetObjLength(is.commandPtr, --length);
code = Tcl_RecordAndEvalObj(interp, is.commandPtr,
TCL_EVAL_GLOBAL);
@@ -549,7 +553,7 @@ Tcl_MainEx(
} else if (is.tty) {
resultPtr = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(resultPtr);
Tcl_GetStringFromObj(resultPtr, &length);
TclGetStringFromObj(resultPtr, &length);
chan = Tcl_GetStdChannel(TCL_STDOUT);
if ((length > 0) && chan) {
Tcl_WriteObj(chan, resultPtr);
@@ -634,21 +638,6 @@ Tcl_MainEx(
Tcl_Exit(exitCode);
}
#if (TCL_MAJOR_VERSION == 8) && !defined(UNICODE)
#undef Tcl_Main
extern DLLEXPORT void
Tcl_Main(
int argc, /* Number of arguments. */
char **argv, /* Array of argument strings. */
Tcl_AppInitProc *appInitProc)
/* Application-specific initialization
* function to call after most initialization
* but before starting to execute commands. */
{
Tcl_MainEx(argc, argv, appInitProc, Tcl_CreateInterp());
}
#endif /* TCL_MAJOR_VERSION == 8 && !UNICODE */
#ifndef TCL_ASCII_MAIN
@@ -808,7 +797,7 @@ StdinProc(
goto prompt;
}
isPtr->prompt = PROMPT_START;
Tcl_GetStringFromObj(commandPtr, &length);
TclGetStringFromObj(commandPtr, &length);
Tcl_SetObjLength(commandPtr, --length);
/*
@@ -839,7 +828,7 @@ StdinProc(
chan = Tcl_GetStdChannel(TCL_STDOUT);
Tcl_IncrRefCount(resultPtr);
Tcl_GetStringFromObj(resultPtr, &length);
TclGetStringFromObj(resultPtr, &length);
if ((length > 0) && (chan != NULL)) {
Tcl_WriteObj(chan, resultPtr);
Tcl_WriteChars(chan, "\n", 1);
+75 -45
View File
@@ -1105,8 +1105,6 @@ TclTeardownNamespace(
Interp *iPtr = (Interp *) nsPtr->interp;
register Tcl_HashEntry *entryPtr;
Tcl_HashSearch search;
Tcl_Namespace *childNsPtr;
Tcl_Command cmd;
int i;
/*
@@ -1121,16 +1119,31 @@ TclTeardownNamespace(
/*
* Delete all commands in this namespace. Be careful when traversing the
* hash table: when each command is deleted, it removes itself from the
* command table.
*
* Don't optimize to Tcl_NextHashEntry() because of traces.
* command table. Because of traces (and the desire to avoid the quadratic
* problems of just using Tcl_FirstHashEntry over and over, [Bug
* f97d4ee020]) we copy to a temporary array and then delete all those
* commands.
*/
for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
entryPtr != NULL;
entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search)) {
cmd = Tcl_GetHashValue(entryPtr);
Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr, cmd);
while (nsPtr->cmdTable.numEntries > 0) {
int length = nsPtr->cmdTable.numEntries;
Command **cmds = TclStackAlloc((Tcl_Interp *) iPtr,
sizeof(Command *) * length);
i = 0;
for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
entryPtr != NULL;
entryPtr = Tcl_NextHashEntry(&search)) {
cmds[i] = Tcl_GetHashValue(entryPtr);
cmds[i]->refCount++;
i++;
}
for (i = 0 ; i < length ; i++) {
Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr,
(Tcl_Command) cmds[i]);
TclCleanupCommandMacro(cmds[i]);
}
TclStackFree((Tcl_Interp *) iPtr, cmds);
}
Tcl_DeleteHashTable(&nsPtr->cmdTable);
Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
@@ -1175,25 +1188,54 @@ TclTeardownNamespace(
*
* BE CAREFUL: When each child is deleted, it will divorce itself from its
* parent. You can't traverse a hash table properly if its elements are
* being deleted. We use only the Tcl_FirstHashEntry function to be safe.
* being deleted. Because of traces (and the desire to avoid the
* quadratic problems of just using Tcl_FirstHashEntry over and over, [Bug
* f97d4ee020]) we copy to a temporary array and then delete all those
* namespaces.
*
* Don't optimize to Tcl_NextHashEntry() because of traces.
* Important: leave the hash table itself still live.
*/
#ifndef BREAK_NAMESPACE_COMPAT
for (entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
entryPtr != NULL;
entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search)) {
childNsPtr = Tcl_GetHashValue(entryPtr);
Tcl_DeleteNamespace(childNsPtr);
while (nsPtr->childTable.numEntries > 0) {
int length = nsPtr->childTable.numEntries;
Namespace **children = TclStackAlloc((Tcl_Interp *) iPtr,
sizeof(Namespace *) * length);
i = 0;
for (entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
entryPtr != NULL;
entryPtr = Tcl_NextHashEntry(&search)) {
children[i] = Tcl_GetHashValue(entryPtr);
children[i]->refCount++;
i++;
}
for (i = 0 ; i < length ; i++) {
Tcl_DeleteNamespace((Tcl_Namespace *) children[i]);
TclNsDecrRefCount(children[i]);
}
TclStackFree((Tcl_Interp *) iPtr, children);
}
#else
if (nsPtr->childTablePtr != NULL) {
for (entryPtr = Tcl_FirstHashEntry(nsPtr->childTablePtr, &search);
entryPtr != NULL;
entryPtr = Tcl_FirstHashEntry(nsPtr->childTablePtr,&search)) {
childNsPtr = Tcl_GetHashValue(entryPtr);
Tcl_DeleteNamespace(childNsPtr);
while (nsPtr->childTablePtr->numEntries > 0) {
int length = nsPtr->childTablePtr->numEntries;
Namespace **children = TclStackAlloc((Tcl_Interp *) iPtr,
sizeof(Namespace *) * length);
i = 0;
for (entryPtr = Tcl_FirstHashEntry(nsPtr->childTablePtr, &search);
entryPtr != NULL;
entryPtr = Tcl_NextHashEntry(&search)) {
children[i] = Tcl_GetHashValue(entryPtr);
children[i]->refCount++;
i++;
}
for (i = 0 ; i < length ; i++) {
Tcl_DeleteNamespace((Tcl_Namespace *) children[i]);
TclNsDecrRefCount(children[i]);
}
TclStackFree((Tcl_Interp *) iPtr, children);
}
}
#endif
@@ -2524,7 +2566,9 @@ Tcl_FindCommand(
}
if (result == TCL_OK) {
((Command *)cmd)->flags |= CMD_VIA_RESOLVER;
return cmd;
} else if (result != TCL_CONTINUE) {
return NULL;
}
@@ -2616,6 +2660,7 @@ Tcl_FindCommand(
}
if (cmdPtr != NULL) {
cmdPtr->flags &= ~CMD_VIA_RESOLVER;
return (Tcl_Command) cmdPtr;
}
@@ -2841,9 +2886,9 @@ GetNamespaceFromObj(
resNamePtr = objPtr->internalRep.twoPtrValue.ptr1;
nsPtr = resNamePtr->nsPtr;
refNsPtr = resNamePtr->refNsPtr;
if (!(nsPtr->flags & NS_DYING) && (interp == nsPtr->interp) &&
(!refNsPtr || ((interp == refNsPtr->interp) &&
(refNsPtr== (Namespace *) Tcl_GetCurrentNamespace(interp))))){
if (!(nsPtr->flags & NS_DYING) && (interp == nsPtr->interp)
&& (!refNsPtr || (refNsPtr ==
(Namespace *) TclGetCurrentNamespace(interp)))) {
*nsPtrPtr = (Tcl_Namespace *) nsPtr;
return TCL_OK;
}
@@ -3312,14 +3357,7 @@ NRNamespaceEvalCmd(
(void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
namespacePtr, /*isProcCallFrame*/ 0);
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
framePtr->objc = objc;
framePtr->objv = objv;
} else {
framePtr->objc = objc + iPtr->ensembleRewrite.numRemovedObjs
- iPtr->ensembleRewrite.numInsertedObjs;
framePtr->objv = iPtr->ensembleRewrite.sourceObjs;
}
framePtr->objv = TclFetchEnsembleRoot(interp, objv, objc, &framePtr->objc);
if (objc == 3) {
/*
@@ -3726,7 +3764,6 @@ NRNamespaceInscopeCmd(
{
Tcl_Namespace *namespacePtr;
CallFrame *framePtr, **framePtrPtr;
register Interp *iPtr = (Interp *) interp;
int i;
Tcl_Obj *cmdObjPtr;
@@ -3752,14 +3789,7 @@ NRNamespaceInscopeCmd(
(void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
namespacePtr, /*isProcCallFrame*/ 0);
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
framePtr->objc = objc;
framePtr->objv = objv;
} else {
framePtr->objc = objc + iPtr->ensembleRewrite.numRemovedObjs
- iPtr->ensembleRewrite.numInsertedObjs;
framePtr->objv = iPtr->ensembleRewrite.sourceObjs;
}
framePtr->objv = TclFetchEnsembleRoot(interp, objv, objc, &framePtr->objc);
/*
* Execute the command. If there is just one argument, just treat it as a
@@ -4511,8 +4541,8 @@ NamespaceUpvarCmd(
savedNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
iPtr->varFramePtr->nsPtr = (Namespace *) nsPtr;
otherPtr = TclObjLookupVarEx(interp, objv[0], NULL,
(TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access",
/*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
(TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG|TCL_AVOID_RESOLVERS),
"access", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
iPtr->varFramePtr->nsPtr = (Namespace *) savedNsPtr;
if (otherPtr == NULL) {
return TCL_ERROR;
@@ -4752,7 +4782,7 @@ SetNsNameFromAny(
if ((name[0] == ':') && (name[1] == ':')) {
resNamePtr->refNsPtr = NULL;
} else {
resNamePtr->refNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
resNamePtr->refNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
}
resNamePtr->refCount = 1;
TclFreeIntRep(objPtr);
+13 -16
View File
@@ -68,12 +68,9 @@ static int CloneObjectMethod(Tcl_Interp *interp, Object *oPtr,
static void DeletedDefineNamespace(ClientData clientData);
static void DeletedObjdefNamespace(ClientData clientData);
static void DeletedHelpersNamespace(ClientData clientData);
static int FinalizeAlloc(ClientData data[],
Tcl_Interp *interp, int result);
static int FinalizeNext(ClientData data[],
Tcl_Interp *interp, int result);
static int FinalizeObjectCall(ClientData data[],
Tcl_Interp *interp, int result);
static Tcl_NRPostProc FinalizeAlloc;
static Tcl_NRPostProc FinalizeNext;
static Tcl_NRPostProc FinalizeObjectCall;
static int InitFoundation(Tcl_Interp *interp);
static void KillFoundation(ClientData clientData,
Tcl_Interp *interp);
@@ -269,7 +266,7 @@ TclOOInit(
* to be fully provided.
*/
if (Tcl_Eval(interp, initScript) != TCL_OK) {
if (Tcl_EvalEx(interp, initScript, -1, 0) != TCL_OK) {
return TCL_ERROR;
}
@@ -463,7 +460,7 @@ InitFoundation(
if (TclOODefineSlots(fPtr) != TCL_OK) {
return TCL_ERROR;
}
return Tcl_Eval(interp, slotScript);
return Tcl_EvalEx(interp, slotScript, -1, 0);
}
/*
@@ -1687,7 +1684,7 @@ Tcl_NewObjectInstance(
TclOOGetCallContext(oPtr, NULL, CONSTRUCTOR, NULL);
if (contextPtr != NULL) {
int result;
int isRoot, result;
Tcl_InterpState state;
state = Tcl_SaveInterpState(interp, TCL_OK);
@@ -1698,13 +1695,14 @@ Tcl_NewObjectInstance(
* Adjust the ensmble tracking record if necessary. [Bug 3514761]
*/
if (((Interp*) interp)->ensembleRewrite.sourceObjs) {
((Interp*) interp)->ensembleRewrite.numInsertedObjs += skip-1;
((Interp*) interp)->ensembleRewrite.numRemovedObjs += skip-1;
}
isRoot = TclInitRewriteEnsemble(interp, skip, skip, objv);
result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr,
objc, objv);
if (isRoot) {
TclResetRewriteEnsemble(interp, 1);
}
/*
* It's an error if the object was whacked in the constructor.
* Force this if it isn't already an error (don't want to lose
@@ -1827,9 +1825,8 @@ TclNRNewObjectInstance(
* Adjust the ensmble tracking record if necessary. [Bug 3514761]
*/
if (((Interp *) interp)->ensembleRewrite.sourceObjs) {
((Interp *) interp)->ensembleRewrite.numInsertedObjs += skip - 1;
((Interp *) interp)->ensembleRewrite.numRemovedObjs += skip - 1;
if (TclInitRewriteEnsemble(interp, skip, skip, objv)) {
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
}
/*
+3 -6
View File
@@ -70,15 +70,12 @@ static void AddSimpleClassChainToCallContext(Class *classPtr,
Class *const filterDecl);
static int CmpStr(const void *ptr1, const void *ptr2);
static void DupMethodNameRep(Tcl_Obj *srcPtr, Tcl_Obj *dstPtr);
static int FinalizeMethodRefs(ClientData data[],
Tcl_Interp *interp, int result);
static Tcl_NRPostProc FinalizeMethodRefs;
static void FreeMethodNameRep(Tcl_Obj *objPtr);
static inline int IsStillValid(CallChain *callPtr, Object *oPtr,
int flags, int reuseMask);
static int ResetFilterFlags(ClientData data[],
Tcl_Interp *interp, int result);
static int SetFilterFlags(ClientData data[],
Tcl_Interp *interp, int result);
static Tcl_NRPostProc ResetFilterFlags;
static Tcl_NRPostProc SetFilterFlags;
static inline void StashCallChain(Tcl_Obj *objPtr, CallChain *callPtr);
/*
+21 -47
View File
@@ -525,7 +525,7 @@ TclOOUnknownDefinition(
return TCL_ERROR;
}
soughtStr = Tcl_GetStringFromObj(objv[1], &soughtLen);
soughtStr = TclGetStringFromObj(objv[1], &soughtLen);
if (soughtLen == 0) {
goto noMatch;
}
@@ -585,7 +585,7 @@ FindCommand(
Tcl_Namespace *const namespacePtr)
{
int length;
const char *nameStr, *string = Tcl_GetStringFromObj(stringObj, &length);
const char *nameStr, *string = TclGetStringFromObj(stringObj, &length);
register Namespace *const nsPtr = (Namespace *) namespacePtr;
FOREACH_HASH_DECLS;
Tcl_Command cmd, cmd2;
@@ -774,7 +774,7 @@ GenerateErrorInfo(
int length;
Tcl_Obj *realNameObj = Tcl_ObjectDeleted((Tcl_Object) oPtr)
? savedNameObj : TclOOObjectName(interp, oPtr);
const char *objName = Tcl_GetStringFromObj(realNameObj, &length);
const char *objName = TclGetStringFromObj(realNameObj, &length);
int limit = OBJNAME_LENGTH_IN_ERRORINFO_LIMIT;
int overflow = (length > limit);
@@ -847,9 +847,8 @@ TclOODefineObjCmd(
TclDecrRefCount(objNameObj);
} else {
Tcl_Obj *objPtr, *obj2Ptr, **objs;
Interp *iPtr = (Interp *) interp;
Tcl_Command cmd;
int dummy;
int isRoot, dummy;
/*
* More than one argument: fire them through the ensemble processing
@@ -861,18 +860,7 @@ TclOODefineObjCmd(
* the moment. Ugly!
*/
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
iPtr->ensembleRewrite.sourceObjs = objv;
iPtr->ensembleRewrite.numRemovedObjs = 3;
iPtr->ensembleRewrite.numInsertedObjs = 1;
} else {
int ni = iPtr->ensembleRewrite.numInsertedObjs;
if (ni < 3) {
iPtr->ensembleRewrite.numRemovedObjs += 3 - ni;
} else {
iPtr->ensembleRewrite.numInsertedObjs -= 2;
}
}
isRoot = TclInitRewriteEnsemble(interp, 3, 1, objv);
/*
* Build the list of arguments using a Tcl_Obj as a workspace. See
@@ -894,6 +882,9 @@ TclOODefineObjCmd(
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
result = Tcl_EvalObjv(interp, objc-2, objs, TCL_EVAL_INVOKE);
if (isRoot) {
TclResetRewriteEnsemble(interp, 1);
}
Tcl_DecrRefCount(objPtr);
}
DelRef(oPtr);
@@ -927,7 +918,7 @@ TclOOObjDefObjCmd(
Tcl_Obj *const *objv)
{
Foundation *fPtr = TclOOGetFoundation(interp);
int result;
int isRoot, result;
Object *oPtr;
if (objc < 3) {
@@ -962,7 +953,6 @@ TclOOObjDefObjCmd(
TclDecrRefCount(objNameObj);
} else {
Tcl_Obj *objPtr, *obj2Ptr, **objs;
Interp *iPtr = (Interp *) interp;
Tcl_Command cmd;
int dummy;
@@ -976,18 +966,7 @@ TclOOObjDefObjCmd(
* the moment. Ugly!
*/
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
iPtr->ensembleRewrite.sourceObjs = objv;
iPtr->ensembleRewrite.numRemovedObjs = 3;
iPtr->ensembleRewrite.numInsertedObjs = 1;
} else {
int ni = iPtr->ensembleRewrite.numInsertedObjs;
if (ni < 3) {
iPtr->ensembleRewrite.numRemovedObjs += 3 - ni;
} else {
iPtr->ensembleRewrite.numInsertedObjs -= 2;
}
}
isRoot = TclInitRewriteEnsemble(interp, 3, 1, objv);
/*
* Build the list of arguments using a Tcl_Obj as a workspace. See
@@ -1009,6 +988,10 @@ TclOOObjDefObjCmd(
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
result = Tcl_EvalObjv(interp, objc-2, objs, TCL_EVAL_INVOKE);
if (isRoot) {
TclResetRewriteEnsemble(interp, 1);
}
Tcl_DecrRefCount(objPtr);
}
DelRef(oPtr);
@@ -1077,9 +1060,8 @@ TclOODefineSelfObjCmd(
TclDecrRefCount(objNameObj);
} else {
Tcl_Obj *objPtr, *obj2Ptr, **objs;
Interp *iPtr = (Interp *) interp;
Tcl_Command cmd;
int dummy;
int isRoot, dummy;
/*
* More than one argument: fire them through the ensemble processing
@@ -1091,18 +1073,7 @@ TclOODefineSelfObjCmd(
* the moment. Ugly!
*/
if (iPtr->ensembleRewrite.sourceObjs == NULL) {
iPtr->ensembleRewrite.sourceObjs = objv;
iPtr->ensembleRewrite.numRemovedObjs = 2;
iPtr->ensembleRewrite.numInsertedObjs = 1;
} else {
int ni = iPtr->ensembleRewrite.numInsertedObjs;
if (ni < 2) {
iPtr->ensembleRewrite.numRemovedObjs += 2 - ni;
} else {
iPtr->ensembleRewrite.numInsertedObjs -= 1;
}
}
isRoot = TclInitRewriteEnsemble(interp, 2, 1, objv);
/*
* Build the list of arguments using a Tcl_Obj as a workspace. See
@@ -1124,6 +1095,9 @@ TclOODefineSelfObjCmd(
Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
result = Tcl_EvalObjv(interp, objc-1, objs, TCL_EVAL_INVOKE);
if (isRoot) {
TclResetRewriteEnsemble(interp, 1);
}
Tcl_DecrRefCount(objPtr);
}
DelRef(oPtr);
@@ -1265,7 +1239,7 @@ TclOODefineConstructorObjCmd(
}
clsPtr = oPtr->classPtr;
Tcl_GetStringFromObj(objv[2], &bodyLength);
TclGetStringFromObj(objv[2], &bodyLength);
if (bodyLength > 0) {
/*
* Create the method structure.
@@ -1384,7 +1358,7 @@ TclOODefineDestructorObjCmd(
}
clsPtr = oPtr->classPtr;
Tcl_GetStringFromObj(objv[1], &bodyLength);
TclGetStringFromObj(objv[1], &bodyLength);
if (bodyLength > 0) {
/*
* Create the method structure.
+11 -24
View File
@@ -70,10 +70,8 @@ static Tcl_Obj ** InitEnsembleRewrite(Tcl_Interp *interp, int objc,
static int InvokeProcedureMethod(ClientData clientData,
Tcl_Interp *interp, Tcl_ObjectContext context,
int objc, Tcl_Obj *const *objv);
static int FinalizeForwardCall(ClientData data[], Tcl_Interp *interp,
int result);
static int FinalizePMCall(ClientData data[], Tcl_Interp *interp,
int result);
static Tcl_NRPostProc FinalizeForwardCall;
static Tcl_NRPostProc FinalizePMCall;
static int PushMethodCallFrame(Tcl_Interp *interp,
CallContext *contextPtr, ProcedureMethod *pmPtr,
int objc, Tcl_Obj *const *objv,
@@ -1168,7 +1166,7 @@ MethodErrorHandler(
CallContext *contextPtr = ((Interp *) interp)->varFramePtr->clientData;
Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr;
const char *objectName, *kindName, *methodName =
Tcl_GetStringFromObj(mPtr->namePtr, &nameLen);
TclGetStringFromObj(mPtr->namePtr, &nameLen);
Object *declarerPtr;
if (mPtr->declaringObjectPtr != NULL) {
@@ -1458,6 +1456,11 @@ InvokeForwardMethod(
argObjs = InitEnsembleRewrite(interp, objc, objv, skip,
numPrefixes, prefixObjs, &len);
Tcl_NRAddCallback(interp, FinalizeForwardCall, argObjs, NULL, NULL, NULL);
/*
* NOTE: The combination of direct set of iPtr->lookupNsPtr and the use
* of the TCL_EVAL_NOERR flag results in an evaluation configuration
* very much like TCL_EVAL_INVOKE.
*/
((Interp *)interp)->lookupNsPtr
= (Namespace *) contextPtr->oPtr->namespacePtr;
return TclNREvalObjv(interp, len, argObjs, TCL_EVAL_NOERR, NULL);
@@ -1594,12 +1597,9 @@ InitEnsembleRewrite(
int *lengthPtr) /* Where to write the resulting length of the
* array of rewritten arguments. */
{
Interp *iPtr = (Interp *) interp;
int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL);
Tcl_Obj **argObjs;
unsigned len = rewriteLength + objc - toRewrite;
Tcl_Obj **argObjs = TclStackAlloc(interp, sizeof(Tcl_Obj *) * len);
argObjs = TclStackAlloc(interp, sizeof(Tcl_Obj *) * len);
memcpy(argObjs, rewriteObjs, rewriteLength * sizeof(Tcl_Obj *));
memcpy(argObjs + rewriteLength, objv + toRewrite,
sizeof(Tcl_Obj *) * (objc - toRewrite));
@@ -1613,22 +1613,9 @@ InitEnsembleRewrite(
* (and unavoidably).
*/
if (isRootEnsemble) {
iPtr->ensembleRewrite.sourceObjs = objv;
iPtr->ensembleRewrite.numRemovedObjs = toRewrite;
iPtr->ensembleRewrite.numInsertedObjs = rewriteLength;
} else {
int numIns = iPtr->ensembleRewrite.numInsertedObjs;
if (numIns < toRewrite) {
iPtr->ensembleRewrite.numRemovedObjs += toRewrite - numIns;
iPtr->ensembleRewrite.numInsertedObjs += rewriteLength - 1;
} else {
iPtr->ensembleRewrite.numInsertedObjs +=
rewriteLength - toRewrite;
}
if (TclInitRewriteEnsemble(interp, toRewrite, rewriteLength, objv)) {
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
}
*lengthPtr = len;
return argObjs;
}
+80 -92
View File
@@ -402,7 +402,6 @@ TclInitObjSubsystem(void)
Tcl_RegisterObjType(&tclListType);
Tcl_RegisterObjType(&tclDictType);
Tcl_RegisterObjType(&tclByteCodeType);
Tcl_RegisterObjType(&tclArraySearchType);
Tcl_RegisterObjType(&tclCmdNameType);
Tcl_RegisterObjType(&tclRegexpType);
Tcl_RegisterObjType(&tclProcBodyType);
@@ -663,7 +662,7 @@ TclContinuationsEnterDerived(
* better way which doesn't shimmer?)
*/
Tcl_GetStringFromObj(objPtr, &length);
TclGetStringFromObj(objPtr, &length);
end = start + length; /* First char after the word */
/*
@@ -1989,7 +1988,7 @@ TclSetBooleanFromAny(
badBoolean:
if (interp != NULL) {
int length;
const char *str = Tcl_GetStringFromObj(objPtr, &length);
const char *str = TclGetStringFromObj(objPtr, &length);
Tcl_Obj *msg;
TclNewLiteralStringObj(msg, "expected boolean value but got \"");
@@ -4048,7 +4047,7 @@ TclFreeObjEntry(
*----------------------------------------------------------------------
*/
unsigned int
TCL_HASH_TYPE
TclHashObjKey(
Tcl_HashTable *tablePtr, /* Hash table. */
void *keyPtr) /* Key from which to compute hash value. */
@@ -4098,7 +4097,7 @@ TclHashObjKey(
result += (result << 3) + UCHAR(*++string);
}
}
return result;
return (TCL_HASH_TYPE) result;
}
/*
@@ -4152,11 +4151,10 @@ Tcl_GetCommandFromObj(
*/
resPtr = objPtr->internalRep.twoPtrValue.ptr1;
if ((objPtr->typePtr == &tclCmdNameType) && (resPtr != NULL)) {
if (objPtr->typePtr == &tclCmdNameType) {
register Command *cmdPtr = resPtr->cmdPtr;
if ((cmdPtr->cmdEpoch == resPtr->cmdEpoch)
&& !(cmdPtr->flags & CMD_IS_DELETED)
&& (interp == cmdPtr->nsPtr->interp)
&& !(cmdPtr->nsPtr->flags & NS_DYING)) {
register Namespace *refNsPtr = (Namespace *)
@@ -4204,6 +4202,59 @@ Tcl_GetCommandFromObj(
*----------------------------------------------------------------------
*/
static void
SetCmdNameObj(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Command *cmdPtr,
ResolvedCmdName *resPtr)
{
Interp *iPtr = (Interp *) interp;
ResolvedCmdName *fillPtr;
const char *name = TclGetString(objPtr);
if (resPtr) {
fillPtr = resPtr;
} else {
fillPtr = ckalloc(sizeof(ResolvedCmdName));
fillPtr->refCount = 1;
}
fillPtr->cmdPtr = cmdPtr;
cmdPtr->refCount++;
fillPtr->cmdEpoch = cmdPtr->cmdEpoch;
/* NOTE: relying on NULL termination here. */
if ((name[0] == ':') && (name[1] == ':')) {
/*
* Fully qualified names always resolve to same thing. No need
* to record resolution context information.
*/
fillPtr->refNsPtr = NULL;
fillPtr->refNsId = 0; /* Will not be read */
fillPtr->refNsCmdEpoch = 0; /* Will not be read */
} else {
/*
* Record current state of current namespace as the resolution
* context of this command name lookup.
*/
Namespace *currNsPtr = iPtr->varFramePtr->nsPtr;
fillPtr->refNsPtr = currNsPtr;
fillPtr->refNsId = currNsPtr->nsId;
fillPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
}
if (resPtr == NULL) {
TclFreeIntRep(objPtr);
objPtr->internalRep.twoPtrValue.ptr1 = fillPtr;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = &tclCmdNameType;
}
}
void
TclSetCmdNameObj(
Tcl_Interp *interp, /* Points to interpreter containing command
@@ -4213,45 +4264,16 @@ TclSetCmdNameObj(
Command *cmdPtr) /* Points to Command structure that the
* CmdName object should refer to. */
{
Interp *iPtr = (Interp *) interp;
register ResolvedCmdName *resPtr;
register Namespace *currNsPtr;
const char *name;
if (objPtr->typePtr == &tclCmdNameType) {
return;
resPtr = objPtr->internalRep.twoPtrValue.ptr1;
if (resPtr != NULL && resPtr->cmdPtr == cmdPtr) {
return;
}
}
cmdPtr->refCount++;
resPtr = ckalloc(sizeof(ResolvedCmdName));
resPtr->cmdPtr = cmdPtr;
resPtr->cmdEpoch = cmdPtr->cmdEpoch;
resPtr->refCount = 1;
name = TclGetString(objPtr);
if ((*name++ == ':') && (*name == ':')) {
/*
* The name is fully qualified: set the referring namespace to
* NULL.
*/
resPtr->refNsPtr = NULL;
} else {
/*
* Get the current namespace.
*/
currNsPtr = iPtr->varFramePtr->nsPtr;
resPtr->refNsPtr = currNsPtr;
resPtr->refNsId = currNsPtr->nsId;
resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
}
TclFreeIntRep(objPtr);
objPtr->internalRep.twoPtrValue.ptr1 = resPtr;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = &tclCmdNameType;
SetCmdNameObj(interp, objPtr, cmdPtr, NULL);
}
/*
@@ -4282,7 +4304,6 @@ FreeCmdNameInternalRep(
{
register ResolvedCmdName *resPtr = objPtr->internalRep.twoPtrValue.ptr1;
if (resPtr != NULL) {
/*
* Decrement the reference count of the ResolvedCmdName structure. If
* there are no more uses, free the ResolvedCmdName structure.
@@ -4300,7 +4321,6 @@ FreeCmdNameInternalRep(
TclCleanupCommandMacro(cmdPtr);
ckfree(resPtr);
}
}
objPtr->typePtr = NULL;
}
@@ -4333,9 +4353,7 @@ DupCmdNameInternalRep(
copyPtr->internalRep.twoPtrValue.ptr1 = resPtr;
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
if (resPtr != NULL) {
resPtr->refCount++;
}
copyPtr->typePtr = &tclCmdNameType;
}
@@ -4365,10 +4383,8 @@ SetCmdNameFromAny(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
register Tcl_Obj *objPtr) /* The object to convert. */
{
Interp *iPtr = (Interp *) interp;
const char *name;
register Command *cmdPtr;
Namespace *currNsPtr;
register ResolvedCmdName *resPtr;
if (interp == NULL) {
@@ -4388,59 +4404,31 @@ SetCmdNameFromAny(
Tcl_FindCommand(interp, name, /*ns*/ NULL, /*flags*/ 0);
/*
* Free the old internalRep before setting the new one. Do this after
* getting the string rep to allow the conversion code (in particular,
* Tcl_GetStringFromObj) to use that old internalRep.
* Stop shimmering and caching nothing when we found nothing. Just
* report the failure to find the command as an error.
*/
if (cmdPtr) {
cmdPtr->refCount++;
resPtr = objPtr->internalRep.twoPtrValue.ptr1;
if ((objPtr->typePtr == &tclCmdNameType)
&& resPtr && (resPtr->refCount == 1)) {
/*
* Reuse the old ResolvedCmdName struct instead of freeing it
*/
if (cmdPtr == NULL) {
return TCL_ERROR;
}
Command *oldCmdPtr = resPtr->cmdPtr;
resPtr = objPtr->internalRep.twoPtrValue.ptr1;
if ((objPtr->typePtr == &tclCmdNameType) && (resPtr->refCount == 1)) {
/*
* Re-use existing ResolvedCmdName struct when possible.
* Cleanup the old fields that need it.
*/
if (--oldCmdPtr->refCount == 0) {
TclCleanupCommandMacro(oldCmdPtr);
}
} else {
TclFreeIntRep(objPtr);
resPtr = ckalloc(sizeof(ResolvedCmdName));
resPtr->refCount = 1;
objPtr->internalRep.twoPtrValue.ptr1 = resPtr;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = &tclCmdNameType;
}
resPtr->cmdPtr = cmdPtr;
resPtr->cmdEpoch = cmdPtr->cmdEpoch;
if ((*name++ == ':') && (*name == ':')) {
/*
* The name is fully qualified: set the referring namespace to
* NULL.
*/
Command *oldCmdPtr = resPtr->cmdPtr;
resPtr->refNsPtr = NULL;
} else {
/*
* Get the current namespace.
*/
currNsPtr = iPtr->varFramePtr->nsPtr;
resPtr->refNsPtr = currNsPtr;
resPtr->refNsId = currNsPtr->nsId;
resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
if (--oldCmdPtr->refCount == 0) {
TclCleanupCommandMacro(oldCmdPtr);
}
} else {
TclFreeIntRep(objPtr);
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = &tclCmdNameType;
resPtr = NULL;
}
SetCmdNameObj(interp, objPtr, cmdPtr, resPtr);
return TCL_OK;
}
+2 -2
View File
@@ -233,7 +233,7 @@ ConvertZeroEffectToNOP(
TclGetUInt1AtPtr(currentInstPtr + 1));
int numBytes;
(void) Tcl_GetStringFromObj(litPtr, &numBytes);
(void) TclGetStringFromObj(litPtr, &numBytes);
if (numBytes == 0) {
blank = size + InstLength(nextInst);
}
@@ -248,7 +248,7 @@ ConvertZeroEffectToNOP(
TclGetUInt4AtPtr(currentInstPtr + 1));
int numBytes;
(void) Tcl_GetStringFromObj(litPtr, &numBytes);
(void) TclGetStringFromObj(litPtr, &numBytes);
if (numBytes == 0) {
blank = size + InstLength(nextInst);
}
+77 -101
View File
@@ -167,6 +167,8 @@ static int ParseTokens(const char *src, int numBytes, int mask,
int flags, Tcl_Parse *parsePtr);
static int ParseWhiteSpace(const char *src, int numBytes,
int *incompletePtr, char *typePtr);
static int ParseAllWhiteSpace(const char *src, int numBytes,
int *incompletePtr);
/*
*----------------------------------------------------------------------
@@ -298,9 +300,43 @@ Tcl_ParseCommand(
*/
parsePtr->commandStart = src;
type = CHAR_TYPE(*src);
scanned = 1; /* Can't have missing whitepsace before first word. */
while (1) {
int expandWord = 0;
/* Are we at command termination? */
if ((numBytes == 0) || (type & terminators) != 0) {
parsePtr->term = src;
parsePtr->commandSize = src + (numBytes != 0)
- parsePtr->commandStart;
return TCL_OK;
}
/* Are we missing white space after previous word? */
if (scanned == 0) {
if (src[-1] == '"') {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"extra characters after close-quote", -1));
}
parsePtr->errorType = TCL_PARSE_QUOTE_EXTRA;
} else {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"extra characters after close-brace", -1));
}
parsePtr->errorType = TCL_PARSE_BRACE_EXTRA;
}
parsePtr->term = src;
error:
Tcl_FreeParse(parsePtr);
parsePtr->commandSize = parsePtr->end - parsePtr->commandStart;
return TCL_ERROR;
}
/*
* Create the token for the word.
*/
@@ -310,23 +346,6 @@ Tcl_ParseCommand(
tokenPtr = &parsePtr->tokenPtr[wordIndex];
tokenPtr->type = TCL_TOKEN_WORD;
/*
* Skip white space before the word. Also skip a backslash-newline
* sequence: it should be treated just like white space.
*/
scanned = ParseWhiteSpace(src,numBytes, &parsePtr->incomplete, &type);
src += scanned;
numBytes -= scanned;
if (numBytes == 0) {
parsePtr->term = src;
break;
}
if ((type & terminators) != 0) {
parsePtr->term = src;
src++;
break;
}
tokenPtr->start = src;
parsePtr->numTokens++;
parsePtr->numWords++;
@@ -546,52 +565,12 @@ Tcl_ParseCommand(
tokenPtr->type = TCL_TOKEN_SIMPLE_WORD;
}
/*
* Do two additional checks: (a) make sure we're really at the end of
* a word (there might have been garbage left after a quoted or braced
* word), and (b) check for the end of the command.
*/
/* Parse the whitespace between words. */
scanned = ParseWhiteSpace(src,numBytes, &parsePtr->incomplete, &type);
if (scanned) {
src += scanned;
numBytes -= scanned;
continue;
}
if (numBytes == 0) {
parsePtr->term = src;
break;
}
if ((type & terminators) != 0) {
parsePtr->term = src;
src++;
break;
}
if (src[-1] == '"') {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"extra characters after close-quote", -1));
}
parsePtr->errorType = TCL_PARSE_QUOTE_EXTRA;
} else {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"extra characters after close-brace", -1));
}
parsePtr->errorType = TCL_PARSE_BRACE_EXTRA;
}
parsePtr->term = src;
goto error;
src += scanned;
numBytes -= scanned;
}
parsePtr->commandSize = src - parsePtr->commandStart;
return TCL_OK;
error:
Tcl_FreeParse(parsePtr);
parsePtr->commandSize = parsePtr->end - parsePtr->commandStart;
return TCL_ERROR;
}
/*
@@ -733,22 +712,31 @@ ParseWhiteSpace(
*----------------------------------------------------------------------
*/
static int
ParseAllWhiteSpace(
const char *src, /* First character to parse. */
int numBytes, /* Max number of byes to scan */
int *incompletePtr) /* Set true if parse is incomplete. */
{
char type;
const char *p = src;
do {
int scanned = ParseWhiteSpace(p, numBytes, incompletePtr, &type);
p += scanned;
numBytes -= scanned;
} while (numBytes && (*p == '\n') && (p++, --numBytes));
return (p-src);
}
int
TclParseAllWhiteSpace(
const char *src, /* First character to parse. */
int numBytes) /* Max number of byes to scan */
{
int dummy;
char type;
const char *p = src;
do {
int scanned = ParseWhiteSpace(p, numBytes, &dummy, &type);
p += scanned;
numBytes -= scanned;
} while (numBytes && (*p == '\n') && (p++, --numBytes));
return (p-src);
return ParseAllWhiteSpace(src, numBytes, &dummy);
}
/*
@@ -1021,17 +1009,12 @@ ParseComment(
* command. */
{
register const char *p = src;
int incomplete = parsePtr->incomplete;
while (numBytes) {
char type;
int scanned;
do {
scanned = ParseWhiteSpace(p, numBytes,
&parsePtr->incomplete, &type);
p += scanned;
numBytes -= scanned;
} while (numBytes && (*p == '\n') && (p++,numBytes--));
int scanned = ParseAllWhiteSpace(p, numBytes, &incomplete);
p += scanned;
numBytes -= scanned;
if ((numBytes == 0) || (*p != '#')) {
break;
@@ -1040,35 +1023,28 @@ ParseComment(
parsePtr->commentStart = p;
}
p++;
numBytes--;
while (numBytes) {
if (*p == '\\') {
scanned = ParseWhiteSpace(p, numBytes, &parsePtr->incomplete,
&type);
if (scanned) {
p += scanned;
numBytes -= scanned;
} else {
/*
* General backslash substitution in comments isn't part
* of the formal spec, but test parse-15.47 and history
* indicate that it has been the de facto rule. Don't
* change it now.
*/
TclParseBackslash(p, numBytes, &scanned, NULL);
p += scanned;
numBytes -= scanned;
}
} else {
if (*p == '\n') {
p++;
numBytes--;
if (p[-1] == '\n') {
break;
}
if (*p == '\\') {
p++;
numBytes--;
if (numBytes == 0) {
break;
}
}
incomplete = (*p == '\n');
p++;
numBytes--;
}
parsePtr->commentSize = p - parsePtr->commentStart;
}
parsePtr->incomplete = incomplete;
return (p - src);
}
@@ -2244,7 +2220,7 @@ TclSubstTokens(
if (result == 0) {
clPos = 0;
} else {
Tcl_GetStringFromObj(result, &clPos);
TclGetStringFromObj(result, &clPos);
}
if (numCL >= maxNumCL) {
@@ -2520,7 +2496,7 @@ TclObjCommandComplete(
* check. */
{
int length;
const char *script = Tcl_GetStringFromObj(objPtr, &length);
const char *script = TclGetStringFromObj(objPtr, &length);
return CommandComplete(script, length);
}
+33 -29
View File
@@ -231,7 +231,7 @@ TclFSNormalizeAbsolutePath(
retVal = Tcl_NewStringObj(path, dirSep - path);
Tcl_IncrRefCount(retVal);
}
Tcl_GetStringFromObj(retVal, &curLen);
TclGetStringFromObj(retVal, &curLen);
if (curLen == 0) {
Tcl_AppendToObj(retVal, dirSep, 1);
}
@@ -257,7 +257,7 @@ TclFSNormalizeAbsolutePath(
retVal = Tcl_NewStringObj(path, dirSep - path);
Tcl_IncrRefCount(retVal);
}
Tcl_GetStringFromObj(retVal, &curLen);
TclGetStringFromObj(retVal, &curLen);
if (curLen == 0) {
Tcl_AppendToObj(retVal, dirSep, 1);
}
@@ -288,7 +288,7 @@ TclFSNormalizeAbsolutePath(
*/
const char *path =
Tcl_GetStringFromObj(retVal, &curLen);
TclGetStringFromObj(retVal, &curLen);
while (--curLen >= 0) {
if (IsSeparatorOrNull(path[curLen])) {
@@ -303,7 +303,7 @@ TclFSNormalizeAbsolutePath(
Tcl_SetObjLength(retVal, curLen+1);
Tcl_AppendObjToObj(retVal, linkObj);
TclDecrRefCount(linkObj);
linkStr = Tcl_GetStringFromObj(retVal, &curLen);
linkStr = TclGetStringFromObj(retVal, &curLen);
} else {
/*
* Absolute link.
@@ -316,7 +316,7 @@ TclFSNormalizeAbsolutePath(
} else {
retVal = linkObj;
}
linkStr = Tcl_GetStringFromObj(retVal, &curLen);
linkStr = TclGetStringFromObj(retVal, &curLen);
/*
* Convert to forward-slashes on windows.
@@ -333,7 +333,7 @@ TclFSNormalizeAbsolutePath(
}
}
} else {
linkStr = Tcl_GetStringFromObj(retVal, &curLen);
linkStr = TclGetStringFromObj(retVal, &curLen);
}
/*
@@ -404,7 +404,7 @@ TclFSNormalizeAbsolutePath(
if (tclPlatform == TCL_PLATFORM_WINDOWS) {
int len;
const char *path = Tcl_GetStringFromObj(retVal, &len);
const char *path = TclGetStringFromObj(retVal, &len);
if (len == 2 && path[0] != 0 && path[1] == ':') {
if (Tcl_IsShared(retVal)) {
@@ -579,7 +579,7 @@ TclPathPart(
int numBytes;
const char *rest =
Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &numBytes);
TclGetStringFromObj(fsPathPtr->normPathPtr, &numBytes);
if (strchr(rest, '/') != NULL) {
goto standardPath;
@@ -617,7 +617,7 @@ TclPathPart(
int numBytes;
const char *rest =
Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &numBytes);
TclGetStringFromObj(fsPathPtr->normPathPtr, &numBytes);
if (strchr(rest, '/') != NULL) {
goto standardPath;
@@ -646,7 +646,7 @@ TclPathPart(
const char *fileName, *extension;
int length;
fileName = Tcl_GetStringFromObj(fsPathPtr->normPathPtr,
fileName = TclGetStringFromObj(fsPathPtr->normPathPtr,
&length);
extension = TclGetExtension(fileName);
if (extension == NULL) {
@@ -698,7 +698,7 @@ TclPathPart(
int length;
const char *fileName, *extension;
fileName = Tcl_GetStringFromObj(pathPtr, &length);
fileName = TclGetStringFromObj(pathPtr, &length);
extension = TclGetExtension(fileName);
if (extension == NULL) {
Tcl_IncrRefCount(pathPtr);
@@ -869,19 +869,23 @@ TclJoinPath(
* object which can be normalized more efficiently. Currently we only
* use the special case when we have exactly two elements, but we
* could expand that in the future.
*
* Bugfix [a47641a0]. TclNewFSPathObj requires first argument
* to be an absolute path. Added a check for that elt is absolute.
*/
if ((i == (elements-2)) && (i == 0)
&& (elt->typePtr == &tclFsPathType)
&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))) {
Tcl_Obj *tailObj = objv[i+1];
&& (elt->typePtr == &tclFsPathType)
&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))
&& TclGetPathType(elt, NULL, NULL, NULL) == TCL_PATH_ABSOLUTE) {
Tcl_Obj *tailObj = objv[i+1];
type = TclGetPathType(tailObj, NULL, NULL, NULL);
if (type == TCL_PATH_RELATIVE) {
const char *str;
int len;
str = Tcl_GetStringFromObj(tailObj, &len);
str = TclGetStringFromObj(tailObj, &len);
if (len == 0) {
/*
* This happens if we try to handle the root volume '/'.
@@ -943,7 +947,7 @@ TclJoinPath(
}
}
}
strElt = Tcl_GetStringFromObj(elt, &strEltLen);
strElt = TclGetStringFromObj(elt, &strEltLen);
type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
if (type != TCL_PATH_RELATIVE) {
/*
@@ -1030,9 +1034,9 @@ TclJoinPath(
noQuickReturn:
if (res == NULL) {
res = Tcl_NewObj();
ptr = Tcl_GetStringFromObj(res, &length);
ptr = TclGetStringFromObj(res, &length);
} else {
ptr = Tcl_GetStringFromObj(res, &length);
ptr = TclGetStringFromObj(res, &length);
}
/*
@@ -1077,7 +1081,7 @@ TclJoinPath(
if (length > 0 && ptr[length -1] != '/') {
Tcl_AppendToObj(res, &separator, 1);
Tcl_GetStringFromObj(res, &length);
TclGetStringFromObj(res, &length);
}
Tcl_SetObjLength(res, length + (int) strlen(strElt));
@@ -1372,7 +1376,7 @@ AppendPath(
* intrep produce the same results; that is, bugward compatibility. If
* we need to fix that bug here, it needs fixing in TclJoinPath() too.
*/
bytes = Tcl_GetStringFromObj(tail, &numBytes);
bytes = TclGetStringFromObj(tail, &numBytes);
if (numBytes == 0) {
Tcl_AppendToObj(copy, "/", 1);
} else {
@@ -1431,7 +1435,7 @@ TclFSMakePathRelative(
* too little below, leading to wrong answers returned by glob.
*/
tempStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen);
tempStr = TclGetStringFromObj(cwdPtr, &cwdLen);
/*
* Should we perhaps use 'Tcl_FSPathSeparator'? But then what about the
@@ -1451,7 +1455,7 @@ TclFSMakePathRelative(
}
break;
}
tempStr = Tcl_GetStringFromObj(pathPtr, &len);
tempStr = TclGetStringFromObj(pathPtr, &len);
return Tcl_NewStringObj(tempStr + cwdLen, len - cwdLen);
}
@@ -1715,7 +1719,7 @@ Tcl_FSGetTranslatedStringPath(
if (transPtr != NULL) {
int len;
const char *orig = Tcl_GetStringFromObj(transPtr, &len);
const char *orig = TclGetStringFromObj(transPtr, &len);
char *result = ckalloc(len+1);
memcpy(result, orig, (size_t) len+1);
@@ -1776,7 +1780,7 @@ Tcl_FSGetNormalizedPath(
UpdateStringOfFsPath(pathPtr);
}
Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &tailLen);
TclGetStringFromObj(fsPathPtr->normPathPtr, &tailLen);
if (tailLen) {
copy = AppendPath(dir, fsPathPtr->normPathPtr);
} else {
@@ -1789,7 +1793,7 @@ Tcl_FSGetNormalizedPath(
* We now own a reference on both 'dir' and 'copy'
*/
(void) Tcl_GetStringFromObj(dir, &cwdLen);
(void) TclGetStringFromObj(dir, &cwdLen);
cwdLen += (Tcl_GetString(copy)[cwdLen] == '/');
/* Normalize the combined string. */
@@ -1883,7 +1887,7 @@ Tcl_FSGetNormalizedPath(
copy = AppendPath(fsPathPtr->cwdPtr, pathPtr);
(void) Tcl_GetStringFromObj(fsPathPtr->cwdPtr, &cwdLen);
(void) TclGetStringFromObj(fsPathPtr->cwdPtr, &cwdLen);
cwdLen += (Tcl_GetString(copy)[cwdLen] == '/');
/*
@@ -2333,7 +2337,7 @@ SetFsPathFromAny(
* cmdAH.test exercise most of the code).
*/
name = Tcl_GetStringFromObj(pathPtr, &len);
name = TclGetStringFromObj(pathPtr, &len);
/*
* Handle tilde substitutions, if needed.
@@ -2602,7 +2606,7 @@ UpdateStringOfFsPath(
copy = AppendPath(fsPathPtr->cwdPtr, fsPathPtr->normPathPtr);
pathPtr->bytes = Tcl_GetStringFromObj(copy, &cwdLen);
pathPtr->bytes = TclGetStringFromObj(copy, &cwdLen);
pathPtr->length = cwdLen;
copy->bytes = tclEmptyStringRep;
copy->length = 0;
@@ -2663,7 +2667,7 @@ TclNativePathInFilesystem(
int len;
(void) Tcl_GetStringFromObj(pathPtr, &len);
(void) TclGetStringFromObj(pathPtr, &len);
if (len == 0) {
/*
* We reject the empty path "".
+5 -5
View File
@@ -842,7 +842,7 @@ Tcl_PackageObjCmd(
} else {
pkgPtr = FindPackage(interp, argv2);
}
argv3 = Tcl_GetStringFromObj(objv[3], &length);
argv3 = TclGetStringFromObj(objv[3], &length);
for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL;
prevPtr = availPtr, availPtr = availPtr->nextPtr) {
@@ -883,7 +883,7 @@ Tcl_PackageObjCmd(
prevPtr->nextPtr = availPtr;
}
}
argv4 = Tcl_GetStringFromObj(objv[4], &length);
argv4 = TclGetStringFromObj(objv[4], &length);
DupBlock(availPtr->script, argv4, (unsigned) length + 1);
break;
}
@@ -1034,7 +1034,7 @@ Tcl_PackageObjCmd(
if (iPtr->packageUnknown != NULL) {
ckfree(iPtr->packageUnknown);
}
argv2 = Tcl_GetStringFromObj(objv[2], &length);
argv2 = TclGetStringFromObj(objv[2], &length);
if (argv2[0] == 0) {
iPtr->packageUnknown = NULL;
} else {
@@ -1682,7 +1682,7 @@ AddRequirementsToResult(
int i, length;
for (i = 0; i < reqc; i++) {
const char *v = Tcl_GetStringFromObj(reqv[i], &length);
const char *v = TclGetStringFromObj(reqv[i], &length);
if ((length & 0x1) && (v[length/2] == '-')
&& (strncmp(v, v+((length+1)/2), length/2) == 0)) {
@@ -1895,7 +1895,7 @@ Tcl_PkgInitStubsCheck(
{
const char *actualVersion = Tcl_PkgPresent(interp, "Tcl", version, 0);
if (exact && actualVersion) {
if ((exact&1) && actualVersion) {
const char *p = version;
int count = 0;
+10 -47
View File
@@ -22,7 +22,6 @@
*/
typedef struct {
int isRootEnsemble;
Command cmd;
ExtraFrameInfo efi;
} ApplyExtraData;
@@ -344,7 +343,7 @@ Tcl_ProcObjCmd(
* The argument list is just "args"; check the body
*/
procBody = Tcl_GetStringFromObj(objv[3], &numBytes);
procBody = TclGetStringFromObj(objv[3], &numBytes);
if (TclParseAllWhiteSpace(procBody, numBytes) < numBytes) {
goto done;
}
@@ -870,7 +869,7 @@ TclObjGetFrame(
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad level \"%s\"", name));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "STACKLEVEL", NULL);
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL", name, NULL);
return -1;
}
@@ -1088,12 +1087,10 @@ ProcWrongNumArgs(
if (framePtr->isProcCallFrame & FRAME_IS_LAMBDA) {
desiredObjs[0] = Tcl_NewStringObj("lambdaExpr", -1);
} else {
((Interp *) interp)->ensembleRewrite.numInsertedObjs -= skip - 1;
#ifdef AVOID_HACKS_FOR_ITCL
desiredObjs[0] = framePtr->objv[skip-1];
#else
desiredObjs[0] = Tcl_NewListObj(skip, framePtr->objv);
desiredObjs[0] = Tcl_NewListObj(1, framePtr->objv + skip - 1);
#endif /* AVOID_HACKS_FOR_ITCL */
}
Tcl_IncrRefCount(desiredObjs[0]);
@@ -1528,6 +1525,10 @@ InitArgsAndLocals(
*/
incorrectArgs:
if ((skip != 1) &&
TclInitRewriteEnsemble(interp, skip-1, 0, framePtr->objv)) {
TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
}
memset(varPtr, 0,
((framePtr->compiledLocals + localCt)-varPtr) * sizeof(Var));
return ProcWrongNumArgs(interp, skip);
@@ -2082,7 +2083,7 @@ MakeProcError(
* messages and trace information. */
{
int overflow, limit = 60, nameLen;
const char *procName = Tcl_GetStringFromObj(procNameObj, &nameLen);
const char *procName = TclGetStringFromObj(procNameObj, &nameLen);
overflow = (nameLen > limit);
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
@@ -2634,7 +2635,7 @@ TclNRApplyObjCmd(
Interp *iPtr = (Interp *) interp;
Proc *procPtr = NULL;
Tcl_Obj *lambdaPtr, *nsObjPtr;
int result, isRootEnsemble;
int result;
Tcl_Namespace *nsPtr;
ApplyExtraData *extraPtr;
@@ -2653,30 +2654,6 @@ TclNRApplyObjCmd(
procPtr = lambdaPtr->internalRep.twoPtrValue.ptr1;
}
#define JOE_EXTENSION 0
/*
* Note: this code is NOT FUNCTIONAL due to the NR implementation; DO NOT
* ENABLE! Leaving here as reminder to (a) TIP the suggestion, and (b) adapt
* the code. (MS)
*/
#if JOE_EXTENSION
else {
/*
* Joe English's suggestion to allow cmdNames to function as lambdas.
*/
Tcl_Obj *elemPtr;
int numElem;
if ((lambdaPtr->typePtr == &tclCmdNameType) ||
(TclListObjGetElements(interp, lambdaPtr, &numElem,
&elemPtr) == TCL_OK && numElem == 1)) {
return Tcl_EvalObjv(interp, objc-1, objv+1, 0);
}
}
#endif
if ((procPtr == NULL) || (procPtr->iPtr != iPtr)) {
result = SetLambdaFromAny(interp, lambdaPtr);
if (result != TCL_OK) {
@@ -2717,16 +2694,6 @@ TclNRApplyObjCmd(
extraPtr->efi.fields[0].clientData = lambdaPtr;
extraPtr->cmd.clientData = &extraPtr->efi;
isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL);
if (isRootEnsemble) {
iPtr->ensembleRewrite.sourceObjs = objv;
iPtr->ensembleRewrite.numRemovedObjs = 1;
iPtr->ensembleRewrite.numInsertedObjs = 0;
} else {
iPtr->ensembleRewrite.numInsertedObjs -= 1;
}
extraPtr->isRootEnsemble = isRootEnsemble;
result = TclPushProcCallFrame(procPtr, interp, objc, objv, 1);
if (result == TCL_OK) {
TclNRAddCallback(interp, ApplyNR2, extraPtr, NULL, NULL, NULL);
@@ -2743,10 +2710,6 @@ ApplyNR2(
{
ApplyExtraData *extraPtr = data[0];
if (extraPtr->isRootEnsemble) {
((Interp *) interp)->ensembleRewrite.sourceObjs = NULL;
}
TclStackFree(interp, extraPtr);
return result;
}
@@ -2777,7 +2740,7 @@ MakeLambdaError(
* messages and trace information. */
{
int overflow, limit = 60, nameLen;
const char *procName = Tcl_GetStringFromObj(procNameObj, &nameLen);
const char *procName = TclGetStringFromObj(procNameObj, &nameLen);
overflow = (nameLen > limit);
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+9
View File
@@ -396,6 +396,9 @@ static Tcl_WideUInt Nokia770Twiddle(Tcl_WideUInt w);
* - TCL_PARSE_SCAN_PREFIXES: ignore the prefixes 0b and 0o that are
* not part of the [scan] command's vocabulary. Use only in
* combination with TCL_PARSE_INTEGER_ONLY.
* - TCL_PARSE_BINARY_ONLY: parse only in the binary format, whether
* or not a prefix is present that would lead to binary parsing.
* Use only in combination with TCL_PARSE_INTEGER_ONLY.
* - TCL_PARSE_OCTAL_ONLY: parse only in the octal format, whether
* or not a prefix is present that would lead to octal parsing.
* Use only in combination with TCL_PARSE_INTEGER_ONLY.
@@ -627,6 +630,9 @@ TclParseNumber(
acceptPoint = p;
acceptLen = len;
if (c == 'x' || c == 'X') {
if (flags & (TCL_PARSE_OCTAL_ONLY|TCL_PARSE_BINARY_ONLY)) {
goto endgame;
}
state = ZERO_X;
break;
}
@@ -637,6 +643,9 @@ TclParseNumber(
goto zeroo;
}
if (c == 'b' || c == 'B') {
if (flags & TCL_PARSE_OCTAL_ONLY) {
goto endgame;
}
state = ZERO_B;
break;
}
+348 -1
View File
@@ -408,6 +408,15 @@ Tcl_GetCharLength(
String *stringPtr;
int numChars;
/*
* Quick, no-shimmer return for short string reps.
*/
if ((objPtr->bytes) && (objPtr->length < 2)) {
/* 0 bytes -> 0 chars; 1 byte -> 1 char */
return objPtr->length;
}
/*
* Optimize the case where we're really dealing with a bytearray object
* without string representation; we don't need to convert to a string to
@@ -1173,6 +1182,8 @@ Tcl_AppendUnicodeToObj(
* Side effects:
* The string rep of appendObjPtr is appended to the string
* representation of objPtr.
* IMPORTANT: This routine does not and MUST NOT shimmer appendObjPtr.
* Callers are counting on that.
*
*----------------------------------------------------------------------
*/
@@ -2285,7 +2296,7 @@ Tcl_AppendFormatToObj(
}
}
Tcl_GetStringFromObj(segment, &segmentNumBytes);
TclGetStringFromObj(segment, &segmentNumBytes);
if (segmentNumBytes > limit) {
if (allocSegment) {
Tcl_DecrRefCount(segment);
@@ -2598,6 +2609,332 @@ TclGetStringStorage(
*sizePtr = stringPtr->allocated;
return objPtr->bytes;
}
/*
*---------------------------------------------------------------------------
*
* TclStringCatObjv --
*
* Performs the [string cat] function.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* Writes to *objPtrPtr the address of Tcl_Obj that is concatenation
* of all objc values in objv.
*
*---------------------------------------------------------------------------
*/
int
TclStringCatObjv(
Tcl_Interp *interp,
int inPlace,
int objc,
Tcl_Obj * const objv[],
Tcl_Obj **objPtrPtr)
{
Tcl_Obj *objPtr, *objResultPtr, * const *ov;
int oc, length = 0, binary = 1, first = 0;
int allowUniChar = 1, requestUniChar = 0;
/* assert (objc >= 2) */
/*
* Analyze to determine what representation result should be.
* GOALS: Avoid shimmering & string rep generation.
* Produce pure bytearray when possible.
* Error on overflow.
*/
ov = objv, oc = objc;
while (oc-- && (binary || allowUniChar)) {
objPtr = *ov++;
if (objPtr->bytes) {
/* Value has a string rep. */
if (objPtr->length) {
/*
* Non-empty string rep. Not a pure bytearray, so we
* won't create a pure bytearray
*/
binary = 0;
if ((objPtr->typePtr) && (objPtr->typePtr != &tclStringType)) {
/* Prevent shimmer of non-string types. */
allowUniChar = 0;
}
}
} else {
/* assert (objPtr->typePtr != NULL) -- stork! */
if (TclIsPureByteArray(objPtr)) {
allowUniChar = 0;
} else {
binary = 0;
if (objPtr->typePtr == &tclStringType) {
/* Have a pure Unicode value; ask to preserve it */
requestUniChar = 1;
} else {
/* Have another type; prevent shimmer */
allowUniChar = 0;
}
}
}
}
if (binary) {
/* Result will be pure byte array. Pre-size it */
ov = objv; oc = objc;
while (oc-- && (length >= 0)) {
objPtr = *ov++;
if (objPtr->bytes == NULL) {
int numBytes;
Tcl_GetByteArrayFromObj(objPtr, &numBytes);
if (length == 0) {
first = objc - oc - 1;
}
length += numBytes;
}
}
} else if (allowUniChar && requestUniChar) {
/* Result will be pure Tcl_UniChar array. Pre-size it. */
ov = objv; oc = objc;
while (oc-- && (length >= 0)) {
objPtr = *ov++;
if ((objPtr->bytes == NULL) || (objPtr->length)) {
int numChars;
Tcl_GetUnicodeFromObj(objPtr, &numChars);
if (length == 0) {
first = objc - oc - 1;
}
length += numChars;
}
}
} else {
/* Result will be concat of string reps. Pre-size it. */
ov = objv; oc = objc;
while (oc-- && (length >= 0)) {
int numBytes;
objPtr = *ov++;
Tcl_GetStringFromObj(objPtr, &numBytes);
if ((length == 0) && numBytes) {
first = objc - oc - 1;
}
length += numBytes;
}
}
if (length < 0) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"max size for a Tcl value (%d bytes) exceeded", INT_MAX));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
}
return TCL_ERROR;
}
if (length == 0) {
/* Total length of zero means every value has length zero */
*objPtrPtr = objv[0];
return TCL_OK;
}
objv += first; objc -= first;
if (binary) {
/* Efficiently produce a pure byte array result */
unsigned char *dst;
if (inPlace && !Tcl_IsShared(*objv)) {
int start;
objResultPtr = *objv++; objc--;
Tcl_GetByteArrayFromObj(objResultPtr, &start);
dst = Tcl_SetByteArrayLength(objResultPtr, length) + start;
} else {
objResultPtr = Tcl_NewByteArrayObj(NULL, length);
dst = Tcl_SetByteArrayLength(objResultPtr, length);
}
while (objc--) {
Tcl_Obj *objPtr = *objv++;
if (objPtr->bytes == NULL) {
int more;
unsigned char *src = Tcl_GetByteArrayFromObj(objPtr, &more);
memcpy(dst, src, (size_t) more);
dst += more;
}
}
} else if (allowUniChar && requestUniChar) {
/* Efficiently produce a pure Tcl_UniChar array result */
Tcl_UniChar *dst;
if (inPlace && !Tcl_IsShared(*objv)) {
int start;
objResultPtr = *objv++; objc--;
/* Ugly interface! Force resize of the unicode array. */
Tcl_GetUnicodeFromObj(objResultPtr, &start);
Tcl_InvalidateStringRep(objResultPtr);
Tcl_SetObjLength(objResultPtr, length);
dst = Tcl_GetUnicode(objResultPtr) + start;
} else {
Tcl_UniChar ch = 0;
/* Ugly interface! No scheme to init array size. */
objResultPtr = Tcl_NewUnicodeObj(&ch, 0);
Tcl_SetObjLength(objResultPtr, length);
dst = Tcl_GetUnicode(objResultPtr);
}
while (objc--) {
Tcl_Obj *objPtr = *objv++;
if ((objPtr->bytes == NULL) || (objPtr->length)) {
int more;
Tcl_UniChar *src = Tcl_GetUnicodeFromObj(objPtr, &more);
memcpy(dst, src, more * sizeof(Tcl_UniChar));
dst += more;
}
}
} else {
/* Efficiently concatenate string reps */
char *dst;
if (inPlace && !Tcl_IsShared(*objv)) {
int start;
objResultPtr = *objv++; objc--;
Tcl_GetStringFromObj(objResultPtr, &start);
Tcl_SetObjLength(objResultPtr, length);
dst = Tcl_GetString(objResultPtr) + start;
if (length > start) {
TclFreeIntRep(objResultPtr);
}
} else {
objResultPtr = Tcl_NewObj();
Tcl_SetObjLength(objResultPtr, length);
dst = Tcl_GetString(objResultPtr);
}
while (objc--) {
Tcl_Obj *objPtr = *objv++;
if ((objPtr->bytes == NULL) || (objPtr->length)) {
int more;
char *src = Tcl_GetStringFromObj(objPtr, &more);
memcpy(dst, src, (size_t) more);
dst += more;
}
}
}
*objPtrPtr = objResultPtr;
return TCL_OK;
}
/*
*---------------------------------------------------------------------------
*
* TclStringFind --
*
* Implements the [string first] operation.
*
* Results:
* If needle is found as a substring of haystack, the index of the
* first instance of such a find is returned. If needle is not present
* as a substring of haystack, -1 is returned.
*
* Side effects:
* needle and haystack may have their Tcl_ObjType changed.
*
*---------------------------------------------------------------------------
*/
int
TclStringFind(
Tcl_Obj *needle,
Tcl_Obj *haystack,
unsigned int start)
{
int lh, ln = Tcl_GetCharLength(needle);
if (ln == 0) {
/*
* We don't find empty substrings. Bizarre!
*
* TODO: When we one day make this a true substring
* finder, change this to "return 0"
*/
return -1;
}
if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) {
unsigned char *end, *try, *bh;
unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln);
bh = Tcl_GetByteArrayFromObj(haystack, &lh);
end = bh + lh;
try = bh + start;
while (try + ln <= end) {
try = memchr(try, bn[0], end - try);
if (try == NULL) {
return -1;
}
if (0 == memcmp(try+1, bn+1, ln-1)) {
return (try - bh);
}
try++;
}
return -1;
}
lh = Tcl_GetCharLength(haystack);
if (haystack->bytes && (lh == haystack->length)) {
/* haystack is all single-byte chars */
if (needle->bytes && (ln == needle->length)) {
/* needle is also all single-byte chars */
char *found = strstr(haystack->bytes + start, needle->bytes);
if (found) {
return (found - haystack->bytes);
} else {
return -1;
}
} else {
/*
* Cannot find substring with a multi-byte char inside
* a string with no multi-byte chars.
*/
return -1;
}
} else {
Tcl_UniChar *try, *end, *uh;
Tcl_UniChar *un = Tcl_GetUnicodeFromObj(needle, &ln);
uh = Tcl_GetUnicodeFromObj(haystack, &lh);
end = uh + lh;
try = uh + start;
while (try + ln <= end) {
if ((*try == *un)
&& (0 == memcmp(try+1, un+1, (ln-1)*sizeof(Tcl_UniChar)))) {
return (try - uh);
}
try++;
}
return -1;
}
}
/*
*---------------------------------------------------------------------------
*
@@ -2948,6 +3285,16 @@ UpdateStringOfString(
{
String *stringPtr = GET_STRING(objPtr);
/*
* This routine is only called when we need to generate the
* string rep objPtr->bytes because it does not exist -- it is NULL.
* In that circumstance, any lingering claim about the size of
* memory pointed to by that NULL pointer is clearly bogus, and
* needs a reset.
*/
stringPtr->allocated = 0;
if (stringPtr->numChars == 0) {
TclInitStringRep(objPtr, tclEmptyStringRep, 0);
} else {
+1 -1
View File
@@ -46,7 +46,7 @@
* tcl.h, but do not do that unless you are sure what you're doing!
*/
typedef struct String {
typedef struct {
int numChars; /* The number of chars in the string. -1 means
* this value has not been calculated. >= 0
* means that there is a valid Unicode rep, or
+9 -11
View File
@@ -24,13 +24,10 @@ const TclIntStubs *tclIntStubsPtr = NULL;
const TclIntPlatStubs *tclIntPlatStubsPtr = NULL;
/*
* Use our own isDigit to avoid linking to libc on windows
* Use our own ISDIGIT to avoid linking to libc on windows
*/
static int isDigit(const int c)
{
return (c >= '0' && c <= '9');
}
#define ISDIGIT(c) (((unsigned)((c)-'0')) <= 9)
/*
*----------------------------------------------------------------------
@@ -54,7 +51,8 @@ MODULE_SCOPE const char *
Tcl_InitStubs(
Tcl_Interp *interp,
const char *version,
int exact)
int exact,
int magic)
{
Interp *iPtr = (Interp *) interp;
const char *actualVersion = NULL;
@@ -67,8 +65,8 @@ Tcl_InitStubs(
* times. [Bug 615304]
*/
if (!stubsPtr || (stubsPtr->magic != TCL_STUB_MAGIC)) {
iPtr->result = "interpreter uses an incompatible stubs mechanism";
if (!stubsPtr || (stubsPtr->magic != (((exact&0xff00) >= 0x900) ? magic : TCL_STUB_MAGIC))) {
iPtr->result = (char *)"interpreter uses an incompatible stubs mechanism";
iPtr->freeProc = TCL_STATIC;
return NULL;
}
@@ -77,12 +75,12 @@ Tcl_InitStubs(
if (actualVersion == NULL) {
return NULL;
}
if (exact) {
if (exact&1) {
const char *p = version;
int count = 0;
while (*p) {
count += !isDigit(*p++);
count += !ISDIGIT(*p++);
}
if (count == 1) {
const char *q = actualVersion;
@@ -91,7 +89,7 @@ Tcl_InitStubs(
while (*p && (*p == *q)) {
p++; q++;
}
if (*p || isDigit(*q)) {
if (*p || ISDIGIT(*q)) {
/* Construct error message */
stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL);
return NULL;
+97 -40
View File
@@ -42,16 +42,8 @@
* Declare external functions used in Windows tests.
*/
/*
* TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the
* Tcltest_Init declaration is in the source file itself, which is only
* accessed when we are building a library.
*/
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT
EXTERN int Tcltest_Init(Tcl_Interp *interp);
EXTERN int Tcltest_SafeInit(Tcl_Interp *interp);
DLLEXPORT int Tcltest_Init(Tcl_Interp *interp);
DLLEXPORT int Tcltest_SafeInit(Tcl_Interp *interp);
/*
* Dynamic string shared by TestdcallCmd and DelCallbackProc; used to collect
@@ -416,8 +408,7 @@ static int TestHashSystemHashCmd(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
static int NREUnwind_callback(ClientData data[], Tcl_Interp *interp,
int result);
static Tcl_NRPostProc NREUnwind_callback;
static int TestNREUnwind(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
@@ -1294,7 +1285,7 @@ TestcmdtraceCmd(
cmdTrace = Tcl_CreateObjTrace(interp, 50000,
TCL_ALLOW_INLINE_COMPILATION, ObjTraceProc,
(ClientData) &deleteCalled, ObjTraceDeleteProc);
result = Tcl_Eval(interp, argv[2]);
result = Tcl_EvalEx(interp, argv[2], -1, 0);
Tcl_DeleteTrace(interp, cmdTrace);
if (!deleteCalled) {
Tcl_SetResult(interp, "Delete wasn't called", TCL_STATIC);
@@ -1308,7 +1299,7 @@ TestcmdtraceCmd(
Tcl_DStringInit(&buffer);
t1 = Tcl_CreateTrace(interp, 1, CmdTraceProc, &buffer);
t2 = Tcl_CreateTrace(interp, 50000, CmdTraceProc, &buffer);
result = Tcl_Eval(interp, argv[2]);
result = Tcl_EvalEx(interp, argv[2], -1, 0);
if (result == TCL_OK) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
@@ -1637,7 +1628,7 @@ DelDeleteProc(
{
DelCmd *dPtr = clientData;
Tcl_Eval(dPtr->interp, dPtr->deleteCmd);
Tcl_EvalEx(dPtr->interp, dPtr->deleteCmd, -1, 0);
Tcl_ResetResult(dPtr->interp);
ckfree(dPtr->deleteCmd);
ckfree(dPtr);
@@ -3972,7 +3963,7 @@ TestregexpObjCmd(
varName = Tcl_GetString(objv[2]);
TclRegExpRangeUniChar(regExpr, -1, &start, &end);
sprintf(resinfo, "%d %d", start, end-1);
value = Tcl_SetVar(interp, varName, resinfo, 0);
value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0);
if (value == NULL) {
Tcl_AppendResult(interp, "couldn't set variable \"",
varName, "\"", NULL);
@@ -3986,7 +3977,7 @@ TestregexpObjCmd(
Tcl_RegExpGetInfo(regExpr, &info);
varName = Tcl_GetString(objv[2]);
sprintf(resinfo, "%ld", info.extendStart);
value = Tcl_SetVar(interp, varName, resinfo, 0);
value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0);
if (value == NULL) {
Tcl_AppendResult(interp, "couldn't set variable \"",
varName, "\"", NULL);
@@ -4329,7 +4320,7 @@ StaticInitProc(
Tcl_Interp *interp) /* Interpreter in which package is supposedly
* being loaded. */
{
Tcl_SetVar(interp, "x", "loaded", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "x", NULL, "loaded", TCL_GLOBAL_ONLY);
return TCL_OK;
}
@@ -4413,7 +4404,7 @@ TestupvarCmd(
} else if (strcmp(argv[4], "namespace") == 0) {
flags = TCL_NAMESPACE_ONLY;
}
return Tcl_UpVar(interp, argv[1], argv[2], argv[3], flags);
return Tcl_UpVar2(interp, argv[1], argv[2], NULL, argv[3], flags);
} else {
if (strcmp(argv[5], "global") == 0) {
flags = TCL_GLOBAL_ONLY;
@@ -4907,10 +4898,10 @@ GetTimesObjCmd(
timePer/100000);
/* Tcl_SetVar 100000 times */
fprintf(stderr, "Tcl_SetVar of \"12345\" 100000 times\n");
fprintf(stderr, "Tcl_SetVar2 of \"12345\" 100000 times\n");
Tcl_GetTime(&start);
for (i = 0; i < 100000; i++) {
s = Tcl_SetVar(interp, "a", "12345", TCL_LEAVE_ERR_MSG);
s = Tcl_SetVar2(interp, "a", NULL, "12345", TCL_LEAVE_ERR_MSG);
if (s == NULL) {
return TCL_ERROR;
}
@@ -4924,7 +4915,7 @@ GetTimesObjCmd(
fprintf(stderr, "Tcl_GetVar of a==\"12345\" 100000 times\n");
Tcl_GetTime(&start);
for (i = 0; i < 100000; i++) {
s = Tcl_GetVar(interp, "a", TCL_LEAVE_ERR_MSG);
s = Tcl_GetVar2(interp, "a", NULL, TCL_LEAVE_ERR_MSG);
if (s == NULL) {
return TCL_ERROR;
}
@@ -5194,7 +5185,7 @@ TestsaveresultCmd(
if (((enum options) index) == RESULT_OBJECT) {
result = Tcl_EvalObjEx(interp, objv[2], 0);
} else {
result = Tcl_Eval(interp, Tcl_GetString(objv[2]));
result = Tcl_EvalEx(interp, Tcl_GetString(objv[2]), -1, 0);
}
if (discard) {
@@ -6297,7 +6288,7 @@ TestReport(
savedResult = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(savedResult);
Tcl_SetObjResult(interp, Tcl_NewObj());
Tcl_Eval(interp, Tcl_DStringValue(&ds));
Tcl_EvalEx(interp, Tcl_DStringValue(&ds), -1, 0);
Tcl_DStringFree(&ds);
Tcl_ResetResult(interp);
Tcl_SetObjResult(interp, savedResult);
@@ -7335,23 +7326,82 @@ InterpCmdResolver(
CallFrame *varFramePtr = iPtr->varFramePtr;
Proc *procPtr = (varFramePtr->isProcCallFrame & FRAME_IS_PROC) ?
varFramePtr->procPtr : NULL;
Namespace *ns2NsPtr = (Namespace *)
Tcl_FindNamespace(interp, "::ns2", NULL, 0);
Namespace *callerNsPtr = varFramePtr->nsPtr;
Tcl_Command resolvedCmdPtr = NULL;
if (procPtr && (procPtr->cmdPtr->nsPtr == iPtr->globalNsPtr
|| (ns2NsPtr && procPtr->cmdPtr->nsPtr == ns2NsPtr))) {
const char *callingCmdName =
/*
* Just do something special on a cmd literal "z" in two cases:
* A) when the caller is a proc "x", and the proc is either in "::" or in "::ns2".
* B) the caller's namespace is "ctx1" or "ctx2"
*/
if ( (name[0] == 'z') && (name[1] == '\0') ) {
Namespace *ns2NsPtr = (Namespace *) Tcl_FindNamespace(interp, "::ns2", NULL, 0);
if (procPtr != NULL
&& ((procPtr->cmdPtr->nsPtr == iPtr->globalNsPtr)
|| (ns2NsPtr != NULL && procPtr->cmdPtr->nsPtr == ns2NsPtr)
)
) {
/*
* Case A)
*
* - The context, in which this resolver becomes active, is
* determined by the name of the caller proc, which has to be
* named "x".
*
* - To determine the name of the caller proc, the proc is taken
* from the topmost stack frame.
*
* - Note that the context is NOT provided during byte-code
* compilation (e.g. in TclProcCompileProc)
*
* When these conditions hold, this function resolves the
* passed-in cmd literal into a cmd "y", which is taken from the
* the global namespace (for simplicity).
*/
const char *callingCmdName =
Tcl_GetCommandName(interp, (Tcl_Command) procPtr->cmdPtr);
if ((callingCmdName[0] == 'x') && (callingCmdName[1] == '\0')
&& (name[0] == 'z') && (name[1] == '\0')) {
Tcl_Command sourceCmdPtr = Tcl_FindCommand(interp, "y", NULL,
TCL_GLOBAL_ONLY);
if (sourceCmdPtr != NULL) {
*rPtr = sourceCmdPtr;
return TCL_OK;
if ( callingCmdName[0] == 'x' && callingCmdName[1] == '\0' ) {
resolvedCmdPtr = Tcl_FindCommand(interp, "y", NULL, TCL_GLOBAL_ONLY);
}
} else if (callerNsPtr != NULL) {
/*
* Case B)
*
* - The context, in which this resolver becomes active, is
* determined by the name of the parent namespace, which has
* to be named "ctx1" or "ctx2".
*
* - To determine the name of the parent namesace, it is taken
* from the 2nd highest stack frame.
*
* - Note that the context can be provided during byte-code
* compilation (e.g. in TclProcCompileProc)
*
* When these conditions hold, this function resolves the
* passed-in cmd literal into a cmd "y" or "Y" depending on the
* context. The resolved procs are taken from the the global
* namespace (for simplicity).
*/
CallFrame *parentFramePtr = varFramePtr->callerPtr;
char *context = parentFramePtr != NULL ? parentFramePtr->nsPtr->name : "(NULL)";
if (strcmp(context, "ctx1") == 0 && (name[0] == 'z') && (name[1] == '\0')) {
resolvedCmdPtr = Tcl_FindCommand(interp, "y", NULL, TCL_GLOBAL_ONLY);
/* fprintf(stderr, "... y ==> %p\n", resolvedCmdPtr);*/
} else if (strcmp(context, "ctx2") == 0 && (name[0] == 'z') && (name[1] == '\0')) {
resolvedCmdPtr = Tcl_FindCommand(interp, "Y", NULL, TCL_GLOBAL_ONLY);
/*fprintf(stderr, "... Y ==> %p\n", resolvedCmdPtr);*/
}
}
if (resolvedCmdPtr != NULL) {
*rPtr = resolvedCmdPtr;
return TCL_OK;
}
}
return TCL_CONTINUE;
@@ -7485,9 +7535,16 @@ TestInterpResolverCmd(
int idx;
#define RESOLVER_KEY "testInterpResolver"
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "up|down");
return TCL_ERROR;
if ((objc < 2) || (objc > 3)) {
Tcl_WrongNumArgs(interp, 1, objv, "up|down ?interp?");
return TCL_ERROR;
}
if (objc == 3) {
interp = Tcl_GetSlave(interp, Tcl_GetString(objv[2]));
if (interp == NULL) {
Tcl_AppendResult(interp, "provided interpreter not found", NULL);
return TCL_ERROR;
}
}
if (Tcl_GetIndexFromObj(interp, objv[1], table, "operation", TCL_EXACT,
&idx) != TCL_OK) {
+4 -24
View File
@@ -19,6 +19,7 @@
#endif
#include "tclInt.h"
#include "tommath.h"
#include "tclStringRep.h"
/*
@@ -46,13 +47,6 @@ static int TestobjCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
static int TeststringobjCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
typedef struct TestString {
int numChars;
int allocated;
int maxChars;
Tcl_UniChar unicode[2];
} TestString;
#define VARPTR_KEY "TCLOBJTEST_VARPTR"
#define NUMBER_OF_OBJECT_VARS 20
@@ -583,23 +577,9 @@ TestindexobjCmd(
}
argv[objc-4] = NULL;
/*
* Tcl_GetIndexFromObj assumes that the table is statically-allocated so
* that its address is different for each index object. If we accidently
* allocate a table at the same address as that cached in the index
* object, clear out the object's cached state.
*/
if (objv[3]->typePtr != NULL
&& !strcmp("index", objv[3]->typePtr->name)) {
indexRep = objv[3]->internalRep.twoPtrValue.ptr1;
if (indexRep->tablePtr == (void *) argv) {
TclFreeIntRep(objv[3]);
}
}
result = Tcl_GetIndexFromObj((setError? interp : NULL), objv[3],
argv, "token", (allowAbbrev? 0 : TCL_EXACT), &index);
argv, "token", INDEX_TEMP_TABLE|(allowAbbrev? 0 : TCL_EXACT),
&index);
ckfree(argv);
if (result == TCL_OK) {
Tcl_SetIntObj(Tcl_GetObjResult(interp), index);
@@ -1141,7 +1121,7 @@ TeststringobjCmd(
int varIndex, option, i, length;
#define MAX_STRINGS 11
const char *index, *string, *strings[MAX_STRINGS+1];
TestString *strPtr;
String *strPtr;
Tcl_Obj **varPtr;
static const char *const options[] = {
"append", "appendstrings", "get", "get2", "length", "length2",
+3 -3
View File
@@ -1106,9 +1106,9 @@ TclFinalizeThreadAlloc(void)
*
* TclFinalizeThreadAllocThread --
*
* This procedure is used to destroy single thread private resources used
* in this file.
* Called in TclpFinalizeThreadData when a thread exits (Tcl_FinalizeThread).
* This procedure is used to destroy single thread private resources
* defined in this file. Called either during Tcl_FinalizeThread() or
* Tcl_Finalize().
*
* Results:
* None.
+3 -3
View File
@@ -657,7 +657,7 @@ ThreadErrorProc(
sprintf(buf, "%" TCL_LL_MODIFIER "d", (Tcl_WideInt)(size_t)Tcl_GetCurrentThread());
errorInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
errorInfo = Tcl_GetVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
if (errorProcString == NULL) {
errChannel = Tcl_GetStdChannel(TCL_STDERR);
Tcl_WriteChars(errChannel, "Error from thread ", -1);
@@ -1032,8 +1032,8 @@ ThreadEventProc(
code = Tcl_EvalEx(interp, threadEventPtr->script,-1,TCL_EVAL_GLOBAL);
Tcl_DeleteThreadExitHandler(ThreadFreeProc, threadEventPtr->script);
if (code != TCL_OK) {
errorCode = Tcl_GetVar(interp, "errorCode", TCL_GLOBAL_ONLY);
errorInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
errorCode = Tcl_GetVar2(interp, "errorCode", NULL, TCL_GLOBAL_ONLY);
errorInfo = Tcl_GetVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
} else {
errorCode = errorInfo = NULL;
}
+3 -3
View File
@@ -91,7 +91,7 @@ typedef struct IdleHandler {
* The structure defined below is used in this file only.
*/
typedef struct ThreadSpecificData {
typedef struct {
TimerHandler *firstTimerHandlerPtr; /* First event in queue. */
int lastTimerId; /* Timer identifier of most recently created
* timer. */
@@ -900,10 +900,10 @@ Tcl_AfterObjCmd(
} else {
commandPtr = Tcl_ConcatObj(objc-2, objv+2);;
}
command = Tcl_GetStringFromObj(commandPtr, &length);
command = TclGetStringFromObj(commandPtr, &length);
for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;
afterPtr = afterPtr->nextPtr) {
tempCommand = Tcl_GetStringFromObj(afterPtr->commandPtr,
tempCommand = TclGetStringFromObj(afterPtr->commandPtr,
&tempLength);
if ((length == tempLength)
&& !memcmp(command, tempCommand, (unsigned) length)) {
+5 -5
View File
@@ -143,7 +143,7 @@ static int TraceVarEx(Tcl_Interp *interp, const char *part1,
* trace procs
*/
typedef struct StringTraceData {
typedef struct {
ClientData clientData; /* Client data from Tcl_CreateTrace */
Tcl_CmdTraceProc *proc; /* Trace function from Tcl_CreateTrace */
} StringTraceData;
@@ -278,7 +278,7 @@ Tcl_TraceObjCmd(
opsList = Tcl_NewObj();
Tcl_IncrRefCount(opsList);
flagOps = Tcl_GetStringFromObj(objv[3], &numFlags);
flagOps = TclGetStringFromObj(objv[3], &numFlags);
if (numFlags == 0) {
Tcl_DecrRefCount(opsList);
goto badVarOps;
@@ -462,7 +462,7 @@ TraceExecutionObjCmd(
break;
}
}
command = Tcl_GetStringFromObj(objv[5], &commandLength);
command = TclGetStringFromObj(objv[5], &commandLength);
length = (size_t) commandLength;
if ((enum traceOptions) optionIndex == TRACE_ADD) {
TraceCommandInfo *tcmdPtr = ckalloc(
@@ -701,7 +701,7 @@ TraceCommandObjCmd(
}
}
command = Tcl_GetStringFromObj(objv[5], &commandLength);
command = TclGetStringFromObj(objv[5], &commandLength);
length = (size_t) commandLength;
if ((enum traceOptions) optionIndex == TRACE_ADD) {
TraceCommandInfo *tcmdPtr = ckalloc(
@@ -904,7 +904,7 @@ TraceVariableObjCmd(
break;
}
}
command = Tcl_GetStringFromObj(objv[5], &commandLength);
command = TclGetStringFromObj(objv[5], &commandLength);
length = (size_t) commandLength;
if ((enum traceOptions) optionIndex == TRACE_ADD) {
CombinedTraceVarInfo *ctvarPtr = ckalloc(
+934 -883
View File
File diff suppressed because it is too large Load Diff
+23 -43
View File
@@ -73,16 +73,7 @@ static const unsigned char totalBytes[256] = {
#else
1,1,1,1,1,1,1,1,
#endif
#if TCL_UTF_MAX > 4
5,5,5,5,
#else
1,1,1,1,
#endif
#if TCL_UTF_MAX > 5
6,6,6,6
#else
1,1,1,1
#endif
1,1,1,1,1,1,1,1
};
/*
@@ -105,14 +96,14 @@ int
TclUtfCount(
int ch) /* The Tcl_UniChar whose size is returned. */
{
if ((ch > 0) && (ch < UNICODE_SELF)) {
if ((unsigned)(ch - 1) < (UNICODE_SELF - 1)) {
return 1;
}
if (ch <= 0x7FF) {
return 2;
}
#if TCL_UTF_MAX > 3
if ((ch > 0xFFFF) && (ch <= 0x10FFFF)) {
if (((unsigned)(ch - 0x10000) <= 0xfffff)) {
return 4;
}
#endif
@@ -146,7 +137,7 @@ Tcl_UniCharToUtf(
* large enough to hold the UTF-8 character
* (at most TCL_UTF_MAX bytes). */
{
if ((ch > 0) && (ch < UNICODE_SELF)) {
if ((unsigned)(ch - 1) < (UNICODE_SELF - 1)) {
buf[0] = (char) ch;
return 1;
}
@@ -174,11 +165,7 @@ Tcl_UniCharToUtf(
}
}
#endif
three:
buf[2] = (char) ((ch | 0x80) & 0xBF);
buf[1] = (char) (((ch >> 6) | 0x80) & 0xBF);
buf[0] = (char) ((ch >> 12) | 0xE0);
return 3;
goto three;
}
#if TCL_UTF_MAX > 3
@@ -193,7 +180,11 @@ Tcl_UniCharToUtf(
}
ch = 0xFFFD;
goto three;
three:
buf[2] = (char) ((ch | 0x80) & 0xBF);
buf[1] = (char) (((ch >> 6) | 0x80) & 0xBF);
buf[0] = (char) ((ch >> 12) | 0xE0);
return 3;
}
/*
@@ -308,9 +299,6 @@ Tcl_UtfToUniChar(
* A two-byte-character lead-byte not followed by trail-byte
* represents itself.
*/
*chPtr = (Tcl_UniChar) byte;
return 1;
} else if (byte < 0xF0) {
if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80)) {
/*
@@ -326,31 +314,23 @@ Tcl_UtfToUniChar(
* A three-byte-character lead-byte not followed by two trail-bytes
* represents itself.
*/
*chPtr = (Tcl_UniChar) byte;
return 1;
}
#if TCL_UTF_MAX > 3
{
int ch, total, trail;
else if (byte < 0xF8) {
if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80) && ((src[3] & 0xC0) == 0x80)) {
/*
* Four-byte-character lead byte followed by three trail bytes.
*/
total = totalBytes[byte];
trail = total - 1;
if (trail > 0) {
ch = byte & (0x3F >> trail);
do {
src++;
if ((*src & 0xC0) != 0x80) {
*chPtr = byte;
return 1;
}
ch <<= 6;
ch |= (*src & 0x3F);
trail--;
} while (trail > 0);
*chPtr = ch;
return total;
*chPtr = (Tcl_UniChar) (((byte & 0x0E) << 18) | ((src[1] & 0x3F) << 12)
| ((src[2] & 0x3F) << 6) | (src[3] & 0x3F));
return 4;
}
/*
* A three-byte-character lead-byte not followed by two trail-bytes
* represents itself.
*/
}
#endif
+27 -3
View File
@@ -1968,7 +1968,7 @@ Tcl_ConcatObj(
if (TclListObjIsCanonical(objPtr)) {
continue;
}
Tcl_GetStringFromObj(objPtr, &length);
TclGetStringFromObj(objPtr, &length);
if (length > 0) {
break;
}
@@ -2634,7 +2634,19 @@ Tcl_DStringAppend(
memcpy(newString, dsPtr->string, (size_t) dsPtr->length);
dsPtr->string = newString;
} else {
int offset = -1;
/* See [16896d49fd] */
if (bytes >= dsPtr->string
&& bytes <= dsPtr->string + dsPtr->length) {
offset = bytes - dsPtr->string;
}
dsPtr->string = ckrealloc(dsPtr->string, dsPtr->spaceAvl);
if (offset >= 0) {
bytes = dsPtr->string + offset;
}
}
}
@@ -2665,7 +2677,7 @@ TclDStringAppendObj(
Tcl_Obj *objPtr)
{
int length;
char *bytes = Tcl_GetStringFromObj(objPtr, &length);
char *bytes = TclGetStringFromObj(objPtr, &length);
return Tcl_DStringAppend(dsPtr, bytes, length);
}
@@ -2725,7 +2737,19 @@ Tcl_DStringAppendElement(
memcpy(newString, dsPtr->string, (size_t) dsPtr->length);
dsPtr->string = newString;
} else {
int offset = -1;
/* See [16896d49fd] */
if (element >= dsPtr->string
&& element <= dsPtr->string + dsPtr->length) {
offset = element - dsPtr->string;
}
dsPtr->string = ckrealloc(dsPtr->string, dsPtr->spaceAvl);
if (offset >= 0) {
element = dsPtr->string + offset;
}
}
dst = dsPtr->string + dsPtr->length;
}
@@ -3976,7 +4000,7 @@ TclSetProcessGlobalValue(
} else {
Tcl_CreateExitHandler(FreeProcessGlobalValue, pgvPtr);
}
bytes = Tcl_GetStringFromObj(newValue, &pgvPtr->numBytes);
bytes = TclGetStringFromObj(newValue, &pgvPtr->numBytes);
pgvPtr->value = ckalloc(pgvPtr->numBytes + 1);
memcpy(pgvPtr->value, bytes, (unsigned) pgvPtr->numBytes + 1);
if (pgvPtr->encoding) {
+147 -369
View File
@@ -149,6 +149,7 @@ static const char *isArrayElement =
*/
typedef struct ArraySearch {
Tcl_Obj *name; /* Name of this search */
int id; /* Integer id used to distinguish among
* multiple concurrent searches for the same
* array. */
@@ -188,8 +189,7 @@ static ArraySearch * ParseSearchId(Tcl_Interp *interp, const Var *varPtr,
static void UnsetVarStruct(Var *varPtr, Var *arrayPtr,
Interp *iPtr, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, int flags, int index);
static int SetArraySearchObj(Tcl_Interp *interp,
Tcl_Obj *objPtr);
static Var * VerifyArray(Tcl_Interp *interp, Tcl_Obj *varNameObj);
/*
* Functions defined in this file that may be exported in the future for use
@@ -214,10 +214,6 @@ static Tcl_DupInternalRepProc DupParsedVarName;
* or NULL if it is this same obj
* twoPtrValue.ptr2: index into locals table
*
* nsVarName - INTERNALREP DEFINITION:
* twoPtrValue.ptr1: pointer to the namespace containing the reference
* twoPtrValue.ptr2: pointer to the corresponding Var
*
* parsedVarName - INTERNALREP DEFINITION:
* twoPtrValue.ptr1: pointer to the array name Tcl_Obj, or NULL if it is a
* scalar variable
@@ -235,22 +231,6 @@ static const Tcl_ObjType tclParsedVarNameType = {
FreeParsedVarName, DupParsedVarName, NULL, NULL
};
/*
* Type of Tcl_Objs used to speed up array searches.
*
* INTERNALREP DEFINITION:
* twoPtrValue.ptr1: searchIdNumber (cast to pointer)
* twoPtrValue.ptr2: variableNameStartInString (cast to pointer)
*
* Note that the value stored in ptr2 is the offset into the string of the
* start of the variable name and not the address of the variable name itself,
* as this can be safely copied.
*/
const Tcl_ObjType tclArraySearchType = {
"array search",
NULL, NULL, NULL, SetArraySearchObj
};
Var *
TclVarHashCreateVar(
@@ -521,16 +501,13 @@ TclObjLookupVarEx(
* is set to NULL. */
{
Interp *iPtr = (Interp *) interp;
CallFrame *varFramePtr = iPtr->varFramePtr;
register Var *varPtr; /* Points to the variable's in-frame Var
* structure. */
const char *part1;
int index, len1, len2;
int parsed = 0;
Tcl_Obj *objPtr;
const Tcl_ObjType *typePtr = part1Ptr->typePtr;
const char *errMsg = NULL;
CallFrame *varFramePtr = iPtr->varFramePtr;
const char *part2 = part2Ptr? TclGetString(part2Ptr):NULL;
int index, parsed = 0;
const Tcl_ObjType *typePtr = part1Ptr->typePtr;
*arrayPtrPtr = NULL;
if (typePtr == &localVarNameType) {
@@ -546,7 +523,7 @@ TclObjLookupVarEx(
*/
Tcl_Obj *namePtr = part1Ptr->internalRep.twoPtrValue.ptr1;
Tcl_Obj *checkNamePtr = localName(iPtr->varFramePtr, localIndex);
Tcl_Obj *checkNamePtr = localName(varFramePtr, localIndex);
if ((!namePtr && (checkNamePtr == part1Ptr)) ||
(namePtr && (checkNamePtr == namePtr))) {
@@ -577,11 +554,7 @@ TclObjLookupVarEx(
}
return NULL;
}
if ((part2Ptr = part1Ptr->internalRep.twoPtrValue.ptr2)) {
if (createPart2) {
Tcl_IncrRefCount(part2Ptr);
}
}
part2Ptr = part1Ptr->internalRep.twoPtrValue.ptr2;
part1Ptr = part1Ptr->internalRep.twoPtrValue.ptr1;
typePtr = part1Ptr->typePtr;
if (typePtr == &localVarNameType) {
@@ -590,18 +563,23 @@ TclObjLookupVarEx(
}
parsed = 1;
}
part1 = TclGetStringFromObj(part1Ptr, &len1);
if (!parsed && len1 && (*(part1 + len1 - 1) == ')')) {
if (!parsed) {
/*
* part1Ptr is possibly an unparsed array element.
*/
register int i;
int len;
const char *part1 = TclGetStringFromObj(part1Ptr, &len);
if (len > 1 && (part1[len - 1] == ')')) {
const char *part2 = strchr(part1, '(');
if (part2) {
Tcl_Obj *arrayPtr;
len2 = -1;
for (i = 0; i < len1; i++) {
if (*(part1 + i) == '(') {
if (part2Ptr != NULL) {
if (flags & TCL_LEAVE_ERR_MSG) {
TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg,
@@ -612,47 +590,19 @@ TclObjLookupVarEx(
return NULL;
}
/*
* part1Ptr points to an array element; first copy the element
* name to a new string part2.
*/
arrayPtr = Tcl_NewStringObj(part1, (part2 - part1));
part2Ptr = Tcl_NewStringObj(part2 + 1, len - (part2 - part1) - 2);
part2 = part1 + i + 1;
len2 = len1 - i - 2;
len1 = i;
TclFreeIntRep(part1Ptr);
part2Ptr = Tcl_NewStringObj(part2, len2);
if (createPart2) {
Tcl_IncrRefCount(part2Ptr);
}
Tcl_IncrRefCount(arrayPtr);
part1Ptr->internalRep.twoPtrValue.ptr1 = arrayPtr;
Tcl_IncrRefCount(part2Ptr);
part1Ptr->internalRep.twoPtrValue.ptr2 = part2Ptr;
part1Ptr->typePtr = &tclParsedVarNameType;
/*
* Free the internal rep of the original part1Ptr, now renamed
* objPtr, and set it to tclParsedVarNameType.
*/
objPtr = part1Ptr;
TclFreeIntRep(objPtr);
objPtr->typePtr = &tclParsedVarNameType;
/*
* Define a new string object to hold the new part1Ptr, i.e.,
* the array name. Set the internal rep of objPtr, reset
* typePtr and part1 to contain the references to the array
* name.
*/
TclNewStringObj(part1Ptr, part1, len1);
Tcl_IncrRefCount(part1Ptr);
objPtr->internalRep.twoPtrValue.ptr1 = part1Ptr;
Tcl_IncrRefCount(part2Ptr);
objPtr->internalRep.twoPtrValue.ptr2 = part2Ptr;
typePtr = part1Ptr->typePtr;
part1 = TclGetString(part1Ptr);
break;
}
part1Ptr = arrayPtr;
}
}
}
@@ -662,8 +612,6 @@ TclObjLookupVarEx(
* the cached types if possible.
*/
TclFreeIntRep(part1Ptr);
varPtr = TclLookupSimpleVar(interp, part1Ptr, flags, createPart1,
&errMsg, &index);
if (varPtr == NULL) {
@@ -679,11 +627,12 @@ TclObjLookupVarEx(
* Cache the newly found variable if possible.
*/
TclFreeIntRep(part1Ptr);
if (index >= 0) {
/*
* An indexed local variable.
*/
Tcl_Obj *cachedNamePtr = localName(iPtr->varFramePtr, index);
Tcl_Obj *cachedNamePtr = localName(varFramePtr, index);
part1Ptr->typePtr = &localVarNameType;
if (part1Ptr != cachedNamePtr) {
@@ -724,21 +673,6 @@ TclObjLookupVarEx(
return varPtr;
}
/*
* This flag bit should not interfere with TCL_GLOBAL_ONLY,
* TCL_NAMESPACE_ONLY, or TCL_LEAVE_ERR_MSG; it signals that the variable
* lookup is performed for upvar (or similar) purposes, with slightly
* different rules:
* - Bug #696893 - variable is either proc-local or in the current
* namespace; never follow the second (global) resolution path
* - Bug #631741 - do not use special namespace or interp resolvers
*
* It should also not collide with the (deprecated) TCL_PARSE_PART1 flag
* (Bug #835020)
*/
#define AVOID_RESOLVERS 0x40000
/*
*----------------------------------------------------------------------
*
@@ -788,8 +722,8 @@ TclLookupSimpleVar(
Tcl_Obj *varNamePtr, /* This is a simple variable name that could
* represent a scalar or an array. */
int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
* AVOID_RESOLVERS and TCL_LEAVE_ERR_MSG bits
* matter. */
* TCL_AVOID_RESOLVERS and TCL_LEAVE_ERR_MSG
* bits matter. */
const int create, /* If 1, create hash table entry for varname,
* if it doesn't already exist. If 0, return
* error if it doesn't exist. */
@@ -829,7 +763,7 @@ TclLookupSimpleVar(
*/
if ((cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL)
&& !(flags & AVOID_RESOLVERS)) {
&& !(flags & TCL_AVOID_RESOLVERS)) {
resPtr = iPtr->resolverPtr;
if (cxtNsPtr->varResProc) {
result = cxtNsPtr->varResProc(interp, varName,
@@ -882,7 +816,7 @@ TclLookupSimpleVar(
*indexPtr = -1;
flags = (flags | TCL_GLOBAL_ONLY) & ~TCL_NAMESPACE_ONLY;
} else {
if (flags & AVOID_RESOLVERS) {
if (flags & TCL_AVOID_RESOLVERS) {
flags = (flags | TCL_NAMESPACE_ONLY);
}
if (flags & TCL_NAMESPACE_ONLY) {
@@ -897,7 +831,7 @@ TclLookupSimpleVar(
varPtr = (Var *) ObjFindNamespaceVar(interp, varNamePtr,
(Tcl_Namespace *) cxtNsPtr,
(flags | AVOID_RESOLVERS) & ~TCL_LEAVE_ERR_MSG);
(flags | TCL_AVOID_RESOLVERS) & ~TCL_LEAVE_ERR_MSG);
if (varPtr == NULL) {
Tcl_Obj *tailPtr;
@@ -2913,34 +2847,22 @@ TclArraySet(
*/
/* ARGSUSED */
static int
ArrayStartSearchCmd(
ClientData clientData,
static Var *
VerifyArray(
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
Tcl_Obj *varNameObj)
{
Interp *iPtr = (Interp *) interp;
Var *varPtr, *arrayPtr;
Tcl_HashEntry *hPtr;
Tcl_Obj *varNameObj;
int isNew;
ArraySearch *searchPtr;
const char *varName;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "arrayName");
return TCL_ERROR;
}
varNameObj = objv[1];
const char *varName = TclGetString(varNameObj);
Var *arrayPtr;
/*
* Locate the array variable.
*/
varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0,
Var *varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0,
/*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
varName = TclGetString(varNameObj);
/*
* Special array trace used to keep the env array in sync for array names,
@@ -2952,7 +2874,7 @@ ArrayStartSearchCmd(
if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL,
(TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY|
TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) {
return TCL_ERROR;
return NULL;
}
}
@@ -2962,11 +2884,36 @@ ArrayStartSearchCmd(
* traces.
*/
if ((varPtr == NULL) || !TclIsVarArray(varPtr)
|| TclIsVarUndefined(varPtr)) {
if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" isn't an array", varName));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", varName, NULL);
return NULL;
}
return varPtr;
}
static int
ArrayStartSearchCmd(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
Interp *iPtr = (Interp *) interp;
Var *varPtr;
Tcl_HashEntry *hPtr;
int isNew;
ArraySearch *searchPtr;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "arrayName");
return TCL_ERROR;
}
varPtr = VerifyArray(interp, objv[1]);
if (varPtr == NULL) {
return TCL_ERROR;
}
@@ -2988,8 +2935,9 @@ ArrayStartSearchCmd(
searchPtr->nextEntry = VarHashFirstEntry(varPtr->value.tablePtr,
&searchPtr->search);
Tcl_SetHashValue(hPtr, searchPtr);
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("s-%d-%s", searchPtr->id, varName));
searchPtr->name = Tcl_ObjPrintf("s-%d-%s", searchPtr->id, TclGetString(objv[1]));
Tcl_IncrRefCount(searchPtr->name);
Tcl_SetObjResult(interp, searchPtr->name);
return TCL_OK;
}
@@ -3019,7 +2967,7 @@ ArrayAnyMoreCmd(
Tcl_Obj *const objv[])
{
Interp *iPtr = (Interp *) interp;
Var *varPtr, *arrayPtr;
Var *varPtr;
Tcl_Obj *varNameObj, *searchObj;
int gotValue;
ArraySearch *searchPtr;
@@ -3031,39 +2979,8 @@ ArrayAnyMoreCmd(
varNameObj = objv[1];
searchObj = objv[2];
/*
* Locate the array variable.
*/
varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0,
/*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
/*
* Special array trace used to keep the env array in sync for array names,
* array get, etc.
*/
if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY)
&& (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) {
if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL,
(TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY|
TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) {
return TCL_ERROR;
}
}
/*
* Verify that it is indeed an array variable. This test comes after the
* traces - the variable may actually become an array as an effect of said
* traces.
*/
if ((varPtr == NULL) || !TclIsVarArray(varPtr)
|| TclIsVarUndefined(varPtr)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" isn't an array", TclGetString(varNameObj)));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY",
TclGetString(varNameObj), NULL);
varPtr = VerifyArray(interp, varNameObj);
if (varPtr == NULL) {
return TCL_ERROR;
}
@@ -3125,8 +3042,7 @@ ArrayNextElementCmd(
int objc,
Tcl_Obj *const objv[])
{
Interp *iPtr = (Interp *) interp;
Var *varPtr, *arrayPtr;
Var *varPtr;
Tcl_Obj *varNameObj, *searchObj;
ArraySearch *searchPtr;
@@ -3137,39 +3053,8 @@ ArrayNextElementCmd(
varNameObj = objv[1];
searchObj = objv[2];
/*
* Locate the array variable.
*/
varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0,
/*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
/*
* Special array trace used to keep the env array in sync for array names,
* array get, etc.
*/
if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY)
&& (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) {
if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL,
(TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY|
TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) {
return TCL_ERROR;
}
}
/*
* Verify that it is indeed an array variable. This test comes after the
* traces - the variable may actually become an array as an effect of said
* traces.
*/
if ((varPtr == NULL) || !TclIsVarArray(varPtr)
|| TclIsVarUndefined(varPtr)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" isn't an array", TclGetString(varNameObj)));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY",
TclGetString(varNameObj), NULL);
varPtr = VerifyArray(interp, varNameObj);
if (varPtr == NULL) {
return TCL_ERROR;
}
@@ -3235,7 +3120,7 @@ ArrayDoneSearchCmd(
Tcl_Obj *const objv[])
{
Interp *iPtr = (Interp *) interp;
Var *varPtr, *arrayPtr;
Var *varPtr;
Tcl_HashEntry *hPtr;
Tcl_Obj *varNameObj, *searchObj;
ArraySearch *searchPtr, *prevPtr;
@@ -3247,39 +3132,8 @@ ArrayDoneSearchCmd(
varNameObj = objv[1];
searchObj = objv[2];
/*
* Locate the array variable.
*/
varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0,
/*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
/*
* Special array trace used to keep the env array in sync for array names,
* array get, etc.
*/
if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY)
&& (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) {
if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL,
(TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY|
TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) {
return TCL_ERROR;
}
}
/*
* Verify that it is indeed an array variable. This test comes after the
* traces - the variable may actually become an array as an effect of said
* traces.
*/
if ((varPtr == NULL) || !TclIsVarArray(varPtr)
|| TclIsVarUndefined(varPtr)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" isn't an array", TclGetString(varNameObj)));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY",
TclGetString(varNameObj), NULL);
varPtr = VerifyArray(interp, varNameObj);
if (varPtr == NULL) {
return TCL_ERROR;
}
@@ -3313,6 +3167,7 @@ ArrayDoneSearchCmd(
}
}
}
Tcl_DecrRefCount(searchPtr->name);
ckfree(searchPtr);
return TCL_OK;
}
@@ -4379,15 +4234,15 @@ TclPtrObjMakeUpvar(
/*
* Lookup and eventually create the new variable. Set the flag bit
* AVOID_RESOLVERS to indicate the special resolution rules for upvar
* purposes:
* TCL_AVOID_RESOLVERS to indicate the special resolution rules for
* upvar purposes:
* - Bug #696893 - variable is either proc-local or in the current
* namespace; never follow the second (global) resolution path.
* - Bug #631741 - do not use special namespace or interp resolvers.
*/
varPtr = TclLookupSimpleVar(interp, myNamePtr,
myFlags|AVOID_RESOLVERS, /* create */ 1, &errMsg, &index);
myFlags|TCL_AVOID_RESOLVERS, /* create */ 1, &errMsg, &index);
if (varPtr == NULL) {
TclObjVarErrMsg(interp, myNamePtr, NULL, "create", errMsg, -1);
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME",
@@ -4921,7 +4776,8 @@ Tcl_UpvarObjCmd(
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad level \"%s\"", TclGetString(levelObj)));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "LEVEL", NULL);
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL",
TclGetString(levelObj), NULL);
return TCL_ERROR;
}
@@ -4948,75 +4804,6 @@ Tcl_UpvarObjCmd(
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* SetArraySearchObj --
*
* This function converts the given tcl object into one that has the
* "array search" internal type.
*
* Results:
* TCL_OK if the conversion succeeded, and TCL_ERROR if it failed (when
* an error message will be placed in the interpreter's result.)
*
* Side effects:
* Updates the internal type and representation of the object to make
* this an array-search object. See the tclArraySearchType declaration
* above for details of the internal representation.
*
*----------------------------------------------------------------------
*/
static int
SetArraySearchObj(
Tcl_Interp *interp,
Tcl_Obj *objPtr)
{
const char *string;
char *end; /* Can't be const due to strtoul defn. */
int id;
size_t offset;
/*
* Get the string representation. Make it up-to-date if necessary.
*/
string = TclGetString(objPtr);
/*
* Parse the id into the three parts separated by dashes.
*/
if ((string[0] != 's') || (string[1] != '-')) {
goto syntax;
}
id = strtoul(string+2, &end, 10);
if ((end == (string+2)) || (*end != '-')) {
goto syntax;
}
/*
* Can't perform value check in this context, so place reference to place
* in string to use for the check in the object instead.
*/
end++;
offset = end - string;
TclFreeIntRep(objPtr);
objPtr->typePtr = &tclArraySearchType;
objPtr->internalRep.twoPtrValue.ptr1 = INT2PTR(id);
objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(offset);
return TCL_OK;
syntax:
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"illegal search identifier \"%s\"", string));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAYSEARCH", string, NULL);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
@@ -5030,10 +4817,6 @@ SetArraySearchObj(
* or NULL if there isn't one. If NULL is returned, the interp's result
* contains an error message.
*
* Side effects:
* The tcl object might have its internal type and representation
* modified.
*
*----------------------------------------------------------------------
*/
@@ -5049,65 +4832,43 @@ ParseSearchId(
* name. */
{
Interp *iPtr = (Interp *) interp;
register const char *string;
register size_t offset;
int id;
ArraySearch *searchPtr;
const char *varName = TclGetString(varNamePtr);
/*
* Parse the id.
*/
if ((handleObj->typePtr != &tclArraySearchType)
&& (SetArraySearchObj(interp, handleObj) != TCL_OK)) {
return NULL;
}
/*
* Extract the information out of the Tcl_Obj.
*/
id = PTR2INT(handleObj->internalRep.twoPtrValue.ptr1);
string = TclGetString(handleObj);
offset = PTR2INT(handleObj->internalRep.twoPtrValue.ptr2);
/*
* This test cannot be placed inside the Tcl_Obj machinery, since it is
* dependent on the variable context.
*/
if (strcmp(string+offset, varName) != 0) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"search identifier \"%s\" isn't for variable \"%s\"",
string, varName));
goto badLookup;
}
/*
* Search through the list of active searches on the interpreter to see if
* the desired one exists.
*
* Note that we cannot store the searchPtr directly in the Tcl_Obj as that
* would run into trouble when DeleteSearches() was called so we must scan
* this list every time.
*/
const char *handle = TclGetString(handleObj);
char *end;
if (varPtr->flags & VAR_SEARCH_ACTIVE) {
Tcl_HashEntry *hPtr =
Tcl_FindHashEntry(&iPtr->varSearches, varPtr);
/* First look for same (Tcl_Obj *) */
for (searchPtr = Tcl_GetHashValue(hPtr); searchPtr != NULL;
searchPtr = searchPtr->nextPtr) {
if (searchPtr->id == id) {
if (searchPtr->name == handleObj) {
return searchPtr;
}
}
/* Fallback: do string compares. */
for (searchPtr = Tcl_GetHashValue(hPtr); searchPtr != NULL;
searchPtr = searchPtr->nextPtr) {
if (strcmp(TclGetString(searchPtr->name), handle) == 0) {
return searchPtr;
}
}
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't find search \"%s\"", string));
badLookup:
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAYSEARCH", string, NULL);
if ((handle[0] != 's') || (handle[1] != '-')
|| (strtoul(handle + 2, &end, 10), end == (handle + 2))
|| (*end != '-')) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"illegal search identifier \"%s\"", handle));
} else if (strcmp(end + 1, TclGetString(varNamePtr)) != 0) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"search identifier \"%s\" isn't for variable \"%s\"",
handle, TclGetString(varNamePtr)));
} else {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't find search \"%s\"", handle));
}
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAYSEARCH", handle, NULL);
return NULL;
}
@@ -5142,6 +4903,7 @@ DeleteSearches(
for (searchPtr = Tcl_GetHashValue(sPtr); searchPtr != NULL;
searchPtr = nextPtr) {
nextPtr = searchPtr->nextPtr;
Tcl_DecrRefCount(searchPtr->name);
ckfree(searchPtr);
}
arrayVarPtr->flags &= ~VAR_SEARCH_ACTIVE;
@@ -5194,13 +4956,16 @@ TclDeleteNamespaceVars(
VarHashRefCount(varPtr)++; /* Make sure we get to remove from
* hash. */
Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, objPtr);
UnsetVarStruct(varPtr, NULL, iPtr, /* part1 */ objPtr, NULL, flags,
-1);
Tcl_DecrRefCount(objPtr); /* Free no longer needed obj */
UnsetVarStruct(varPtr, NULL, iPtr, /* part1 */ objPtr,
NULL, flags, -1);
/*
* Remove the variable from the table and force it undefined in case
* an unset trace brought it back from the dead.
* We just unset the variable. However, an unset trace might
* have re-set it, or might have re-established traces on it.
* This namespace and its vartable are going away unconditionally,
* so we cannot let such things linger. That would be a leak.
*
* First we destroy all traces. ...
*/
if (TclIsVarTraced(varPtr)) {
@@ -5224,6 +4989,17 @@ TclDeleteNamespaceVars(
}
}
}
/*
* ...and then, if the variable still holds a value, we unset it
* again. This time with no traces left, we're sure it goes away.
*/
if (!TclIsVarUndefined(varPtr)) {
UnsetVarStruct(varPtr, NULL, iPtr, /* part1 */ objPtr,
NULL, flags, -1);
}
Tcl_DecrRefCount(objPtr); /* free no longer needed obj */
VarHashRefCount(varPtr)--;
VarHashDeleteEntry(varPtr);
}
@@ -5614,11 +5390,12 @@ Tcl_FindNamespaceVar(
* Otherwise, points to namespace in which to
* resolve name. If NULL, look up name in the
* current namespace. */
int flags) /* An OR'd combination of: AVOID_RESOLVERS,
* TCL_GLOBAL_ONLY (look up name only in
* global namespace), TCL_NAMESPACE_ONLY (look
* up only in contextNsPtr, or the current
* namespace if contextNsPtr is NULL), and
int flags) /* An OR'd combination of:
* TCL_AVOID_RESOLVERS, TCL_GLOBAL_ONLY (look
* up name only in global namespace),
* TCL_NAMESPACE_ONLY (look up only in
* contextNsPtr, or the current namespace if
* contextNsPtr is NULL), and
* TCL_LEAVE_ERR_MSG. If both TCL_GLOBAL_ONLY
* and TCL_NAMESPACE_ONLY are given,
* TCL_GLOBAL_ONLY is ignored. */
@@ -5644,11 +5421,12 @@ ObjFindNamespaceVar(
* Otherwise, points to namespace in which to
* resolve name. If NULL, look up name in the
* current namespace. */
int flags) /* An OR'd combination of: AVOID_RESOLVERS,
* TCL_GLOBAL_ONLY (look up name only in
* global namespace), TCL_NAMESPACE_ONLY (look
* up only in contextNsPtr, or the current
* namespace if contextNsPtr is NULL), and
int flags) /* An OR'd combination of:
* TCL_AVOID_RESOLVERS, TCL_GLOBAL_ONLY (look
* up name only in global namespace),
* TCL_NAMESPACE_ONLY (look up only in
* contextNsPtr, or the current namespace if
* contextNsPtr is NULL), and
* TCL_LEAVE_ERR_MSG. If both TCL_GLOBAL_ONLY
* and TCL_NAMESPACE_ONLY are given,
* TCL_GLOBAL_ONLY is ignored. */
@@ -5678,7 +5456,7 @@ ObjFindNamespaceVar(
cxtNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
}
if (!(flags & AVOID_RESOLVERS) &&
if (!(flags & TCL_AVOID_RESOLVERS) &&
(cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL)) {
resPtr = iPtr->resolverPtr;
+134 -97
View File
@@ -177,6 +177,8 @@ static Tcl_ObjCmdProc ZlibStreamPutCmd;
static void ConvertError(Tcl_Interp *interp, int code,
uLong adler);
static Tcl_Obj * ConvertErrorToList(int code, uLong adler);
static inline int Deflate(z_streamp strm, void *bufferPtr,
int bufferSize, int flush, int *writtenPtr);
static void ExtractHeader(gz_header *headerPtr, Tcl_Obj *dictObj);
static int GenerateHeader(Tcl_Interp *interp, Tcl_Obj *dictObj,
GzipHeader *headerPtr, int *extraSizePtr);
@@ -438,7 +440,7 @@ GenerateHeader(
if (GetValue(interp, dictObj, "comment", &value) != TCL_OK) {
goto error;
} else if (value != NULL) {
valueStr = Tcl_GetStringFromObj(value, &len);
valueStr = TclGetStringFromObj(value, &len);
Tcl_UtfToExternal(NULL, latin1enc, valueStr, len, 0, NULL,
headerPtr->nativeCommentBuf, MAX_COMMENT_LEN-1, NULL, &len,
NULL);
@@ -459,7 +461,7 @@ GenerateHeader(
if (GetValue(interp, dictObj, "filename", &value) != TCL_OK) {
goto error;
} else if (value != NULL) {
valueStr = Tcl_GetStringFromObj(value, &len);
valueStr = TclGetStringFromObj(value, &len);
Tcl_UtfToExternal(NULL, latin1enc, valueStr, len, 0, NULL,
headerPtr->nativeFilenameBuf, MAXPATHLEN-1, NULL, &len, NULL);
headerPtr->nativeFilenameBuf[len] = '\0';
@@ -578,6 +580,10 @@ ExtractHeader(
}
}
/*
* Disentangle the worst of how the zlib API is used.
*/
static int
SetInflateDictionary(
z_streamp strm,
@@ -605,6 +611,38 @@ SetDeflateDictionary(
}
return Z_OK;
}
static inline int
Deflate(
z_streamp strm,
void *bufferPtr,
int bufferSize,
int flush,
int *writtenPtr)
{
int e;
strm->next_out = (Bytef *) bufferPtr;
strm->avail_out = (unsigned) bufferSize;
e = deflate(strm, flush);
if (writtenPtr != NULL) {
*writtenPtr = bufferSize - strm->avail_out;
}
return e;
}
static inline void
AppendByteArray(
Tcl_Obj *listObj,
void *buffer,
int size)
{
if (size > 0) {
Tcl_Obj *baObj = Tcl_NewByteArrayObj((unsigned char *) buffer, size);
Tcl_ListObjAppendElement(NULL, listObj, baObj);
}
}
/*
*----------------------------------------------------------------------
@@ -1139,6 +1177,8 @@ Tcl_ZlibStreamSetCompressionDictionary(
*----------------------------------------------------------------------
*/
#define BUFFER_SIZE_LIMIT 0xFFFF
int
Tcl_ZlibStreamPut(
Tcl_ZlibStream zshandle, /* As obtained from Tcl_ZlibStreamInit */
@@ -1148,8 +1188,7 @@ Tcl_ZlibStreamPut(
{
ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;
char *dataTmp = NULL;
int e, size, outSize;
Tcl_Obj *obj;
int e, size, outSize, toStore;
if (zshPtr->streamEnd) {
if (zshPtr->interp) {
@@ -1175,26 +1214,45 @@ Tcl_ZlibStreamPut(
if (HaveDictToSet(zshPtr)) {
e = SetDeflateDictionary(&zshPtr->stream, zshPtr->compDictObj);
if (e != Z_OK) {
if (zshPtr->interp) {
ConvertError(zshPtr->interp, e, zshPtr->stream.adler);
}
ConvertError(zshPtr->interp, e, zshPtr->stream.adler);
return TCL_ERROR;
}
DictWasSet(zshPtr);
}
/*
* Deflatebound doesn't seem to take various header sizes into
* account, so we add 100 extra bytes.
* deflateBound() doesn't seem to take various header sizes into
* account, so we add 100 extra bytes. However, we can also loop
* around again so we also set an upper bound on the output buffer
* size.
*/
outSize = deflateBound(&zshPtr->stream, zshPtr->stream.avail_in)+100;
zshPtr->stream.avail_out = outSize;
dataTmp = ckalloc(zshPtr->stream.avail_out);
zshPtr->stream.next_out = (Bytef *) dataTmp;
outSize = deflateBound(&zshPtr->stream, size) + 100;
if (outSize > BUFFER_SIZE_LIMIT) {
outSize = BUFFER_SIZE_LIMIT;
}
dataTmp = ckalloc(outSize);
while (1) {
e = Deflate(&zshPtr->stream, dataTmp, outSize, flush, &toStore);
/*
* Test if we've filled the buffer up and have to ask deflate() to
* give us some more. Note that the condition for needing to
* repeat a buffer transfer when the result is Z_OK is whether
* there is no more space in the buffer we provided; the zlib
* library does not necessarily return a different code in that
* case. [Bug b26e38a3e4] [Tk Bug 10f2e7872b]
*/
if ((e != Z_BUF_ERROR) && (e != Z_OK || toStore < outSize)) {
if ((e == Z_OK) || (flush == Z_FINISH && e == Z_STREAM_END)) {
break;
}
ConvertError(zshPtr->interp, e, zshPtr->stream.adler);
return TCL_ERROR;
}
e = deflate(&zshPtr->stream, flush);
while (e == Z_BUF_ERROR || (flush == Z_FINISH && e == Z_OK)) {
/*
* Output buffer too small to hold the data being generated or we
* are doing the end-of-stream flush (which can spit out masses of
@@ -1202,45 +1260,21 @@ Tcl_ZlibStreamPut(
* saving the old generated data to the outData list.
*/
obj = Tcl_NewByteArrayObj((unsigned char *) dataTmp, outSize);
Tcl_ListObjAppendElement(NULL, zshPtr->outData, obj);
AppendByteArray(zshPtr->outData, dataTmp, outSize);
if (outSize < 0xFFFF) {
outSize = 0xFFFF; /* There may be *lots* of data left to
* output... */
if (outSize < BUFFER_SIZE_LIMIT) {
outSize = BUFFER_SIZE_LIMIT;
/* There may be *lots* of data left to output... */
dataTmp = ckrealloc(dataTmp, outSize);
}
zshPtr->stream.avail_out = outSize;
zshPtr->stream.next_out = (Bytef *) dataTmp;
e = deflate(&zshPtr->stream, flush);
}
if (e != Z_OK && !(flush==Z_FINISH && e==Z_STREAM_END)) {
if (zshPtr->interp) {
ConvertError(zshPtr->interp, e, zshPtr->stream.adler);
}
return TCL_ERROR;
}
/*
* And append the final data block.
* And append the final data block to the outData list.
*/
if (outSize - zshPtr->stream.avail_out > 0) {
obj = Tcl_NewByteArrayObj((unsigned char *) dataTmp,
outSize - zshPtr->stream.avail_out);
/*
* Now append the compressed data to the outData list.
*/
Tcl_ListObjAppendElement(NULL, zshPtr->outData, obj);
}
if (dataTmp) {
ckfree(dataTmp);
}
AppendByteArray(zshPtr->outData, dataTmp, toStore);
ckfree(dataTmp);
} else {
/*
* This is easy. Just append to the inData list.
@@ -1356,9 +1390,7 @@ Tcl_ZlibStreamGet(
if (IsRawStream(zshPtr) && HaveDictToSet(zshPtr)) {
e = SetInflateDictionary(&zshPtr->stream, zshPtr->compDictObj);
if (e != Z_OK) {
if (zshPtr->interp) {
ConvertError(zshPtr->interp, e, zshPtr->stream.adler);
}
ConvertError(zshPtr->interp, e, zshPtr->stream.adler);
return TCL_ERROR;
}
DictWasSet(zshPtr);
@@ -2864,7 +2896,7 @@ ZlibTransformClose(
Tcl_Interp *interp)
{
ZlibChannelData *cd = instanceData;
int e, result = TCL_OK;
int e, written, result = TCL_OK;
/*
* Delete the support timer.
@@ -2879,9 +2911,18 @@ ZlibTransformClose(
if (cd->mode == TCL_ZLIB_STREAM_DEFLATE) {
cd->outStream.avail_in = 0;
do {
cd->outStream.next_out = (Bytef *) cd->outBuffer;
cd->outStream.avail_out = (unsigned) cd->outAllocated;
e = deflate(&cd->outStream, Z_FINISH);
e = Deflate(&cd->outStream, cd->outBuffer, cd->outAllocated,
Z_FINISH, &written);
/*
* Can't be sure that deflate() won't declare the buffer to be
* full (with Z_BUF_ERROR) so handle that case.
*/
if (e == Z_BUF_ERROR) {
e = Z_OK;
written = cd->outAllocated;
}
if (e != Z_OK && e != Z_STREAM_END) {
/* TODO: is this the right way to do errors on close? */
if (!TclInThreadExit()) {
@@ -2890,25 +2931,22 @@ ZlibTransformClose(
result = TCL_ERROR;
break;
}
if (cd->outStream.avail_out != (unsigned) cd->outAllocated) {
if (Tcl_WriteRaw(cd->parent, cd->outBuffer,
cd->outAllocated - cd->outStream.avail_out) < 0) {
/* TODO: is this the right way to do errors on close?
* Note: when close is called from FinalizeIOSubsystem
* then interp may be NULL */
if (!TclInThreadExit() && interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"error while finalizing file: %s",
Tcl_PosixError(interp)));
}
result = TCL_ERROR;
break;
if (written && Tcl_WriteRaw(cd->parent, cd->outBuffer, written) < 0) {
/* TODO: is this the right way to do errors on close?
* Note: when close is called from FinalizeIOSubsystem then
* interp may be NULL */
if (!TclInThreadExit() && interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"error while finalizing file: %s",
Tcl_PosixError(interp)));
}
result = TCL_ERROR;
break;
}
} while (e != Z_STREAM_END);
e = deflateEnd(&cd->outStream);
(void) deflateEnd(&cd->outStream);
} else {
e = inflateEnd(&cd->inStream);
(void) inflateEnd(&cd->inStream);
}
/*
@@ -3078,13 +3116,21 @@ ZlibTransformOutput(
cd->outStream.next_in = (Bytef *) buf;
cd->outStream.avail_in = toWrite;
do {
cd->outStream.next_out = (Bytef *) cd->outBuffer;
cd->outStream.avail_out = cd->outAllocated;
e = Deflate(&cd->outStream, cd->outBuffer, cd->outAllocated,
Z_NO_FLUSH, &produced);
e = deflate(&cd->outStream, Z_NO_FLUSH);
produced = cd->outAllocated - cd->outStream.avail_out;
if ((e == Z_OK && produced > 0) || e == Z_BUF_ERROR) {
/*
* deflate() indicates that it is out of space by returning
* Z_BUF_ERROR *or* by simply returning Z_OK with no remaining
* space; in either case, we must write the whole buffer out and
* retry to compress what is left.
*/
if (e == Z_OK && produced > 0) {
if (e == Z_BUF_ERROR) {
produced = cd->outAllocated;
e = Z_OK;
}
if (Tcl_WriteRaw(cd->parent, cd->outBuffer, produced) < 0) {
*errorCodePtr = Tcl_GetErrno();
return -1;
@@ -3131,10 +3177,8 @@ ZlibTransformFlush(
* Get the bytes to go out of the compression engine.
*/
cd->outStream.next_out = (Bytef *) cd->outBuffer;
cd->outStream.avail_out = cd->outAllocated;
e = deflate(&cd->outStream, flushType);
e = Deflate(&cd->outStream, cd->outBuffer, cd->outAllocated,
flushType, &len);
if (e != Z_OK && e != Z_BUF_ERROR) {
ConvertError(interp, e, cd->outStream.adler);
return TCL_ERROR;
@@ -3144,7 +3188,6 @@ ZlibTransformFlush(
* Write the bytes we've received to the next layer.
*/
len = cd->outStream.next_out - (Bytef *) cd->outBuffer;
if (len > 0 && Tcl_WriteRaw(cd->parent, cd->outBuffer, len) < 0) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"problem flushing channel: %s",
@@ -3344,10 +3387,13 @@ ZlibTransformGetOption(
Tcl_DStringAppendElement(dsPtr, "");
}
} else {
int len;
const char *str = Tcl_GetStringFromObj(cd->compDictObj, &len);
if (cd->compDictObj) {
int len;
const char *str = TclGetStringFromObj(cd->compDictObj, &len);
Tcl_DStringAppend(dsPtr, str, len);
Tcl_DStringAppend(dsPtr, str, len);
}
return TCL_OK;
}
}
@@ -3549,7 +3595,6 @@ ZlibStackChannelTransform(
ZlibChannelData *cd = ckalloc(sizeof(ZlibChannelData));
Tcl_Channel chan;
int wbits = 0;
int e;
if (mode != TCL_ZLIB_STREAM_DEFLATE && mode != TCL_ZLIB_STREAM_INFLATE) {
Tcl_Panic("unknown mode: %d", mode);
@@ -3603,43 +3648,35 @@ ZlibStackChannelTransform(
*/
if (mode == TCL_ZLIB_STREAM_INFLATE) {
e = inflateInit2(&cd->inStream, wbits);
if (e != Z_OK) {
if (inflateInit2(&cd->inStream, wbits) != Z_OK) {
goto error;
}
cd->inAllocated = DEFAULT_BUFFER_SIZE;
cd->inBuffer = ckalloc(cd->inAllocated);
if (cd->flags & IN_HEADER) {
e = inflateGetHeader(&cd->inStream, &cd->inHeader.header);
if (e != Z_OK) {
if (inflateGetHeader(&cd->inStream, &cd->inHeader.header) != Z_OK) {
goto error;
}
}
if (cd->format == TCL_ZLIB_FORMAT_RAW && cd->compDictObj) {
e = SetInflateDictionary(&cd->inStream, cd->compDictObj);
if (e != Z_OK) {
if (SetInflateDictionary(&cd->inStream, cd->compDictObj) != Z_OK) {
goto error;
}
TclDecrRefCount(cd->compDictObj);
cd->compDictObj = NULL;
}
} else {
e = deflateInit2(&cd->outStream, level, Z_DEFLATED, wbits,
MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
if (e != Z_OK) {
if (deflateInit2(&cd->outStream, level, Z_DEFLATED, wbits,
MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
goto error;
}
cd->outAllocated = DEFAULT_BUFFER_SIZE;
cd->outBuffer = ckalloc(cd->outAllocated);
if (cd->flags & OUT_HEADER) {
e = deflateSetHeader(&cd->outStream, &cd->outHeader.header);
if (e != Z_OK) {
if (deflateSetHeader(&cd->outStream, &cd->outHeader.header) != Z_OK) {
goto error;
}
}
if (cd->compDictObj) {
e = SetDeflateDictionary(&cd->outStream, cd->compDictObj);
if (e != Z_OK) {
if (SetDeflateDictionary(&cd->outStream, cd->compDictObj) != Z_OK) {
goto error;
}
}
+3 -8
View File
@@ -122,11 +122,9 @@ proc tcl_findLibrary {basename version patch initScript enVarName varName} {
# uniquify $dirs in order
array set seen {}
foreach i $dirs {
# Take note that the [file normalize] below has been noted to cause
# difficulties for the freewrap utility. See Bug 1072136. Until
# freewrap resolves the matter, one might work around the problem by
# disabling that branch.
# Make sure $i is unique under normalization. Avoid repeated [source].
if {[interp issafe]} {
# Safe interps have no [file normalize].
set norm $i
} else {
set norm [file normalize $i]
@@ -135,10 +133,7 @@ proc tcl_findLibrary {basename version patch initScript enVarName varName} {
continue
}
set seen($norm) {}
lappend uniqdirs $i
}
set dirs $uniqdirs
foreach i $dirs {
set the_library $i
set file [file join $i $initScript]
+24
View File
@@ -56,6 +56,30 @@ proc ::history {args} {
tailcall apply {arglist {tailcall history {*}$arglist} ::tcl} $args
}
# (unnamed) --
#
# Callback when [::history] is destroyed. Destroys the implementation.
#
# Parameters:
# oldName what the command was called.
# newName what the command is now called (an empty string).
# op the operation (= delete).
#
# Results:
# none
#
# Side Effects:
# The implementation of the [::history] command ceases to exist.
trace add command ::history delete [list apply {{oldName newName op} {
variable history
unset -nocomplain history
foreach c [info procs ::tcl::Hist*] {
rename $c {}
}
rename ::tcl::history {}
} ::tcl}]
# tcl::HistAdd --
#
# Add an item to the history, and optionally eval it at the global scope
+35 -3
View File
@@ -8,10 +8,10 @@
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
package require Tcl 8.6
package require Tcl 8.6-
# Keep this in sync with pkgIndex.tcl and with the install directories in
# Makefiles
package provide http 2.8.9
package provide http 2.8.10
namespace eval http {
# Allow resourcing to not clobber existing data
@@ -1047,7 +1047,7 @@ proc http::Event {sock token} {
fconfigure $sock -translation binary
if {
$state(-binary) || ![string match -nocase text* $state(type)]
$state(-binary) || [IsBinaryContentType $state(type)]
} {
# Turn off conversions for non-text data
set state(binary) 1
@@ -1183,6 +1183,38 @@ proc http::Event {sock token} {
}
}
# http::IsBinaryContentType --
#
# Determine if the content-type means that we should definitely transfer
# the data as binary. [Bug 838e99a76d]
#
# Arguments
# type The content-type of the data.
#
# Results:
# Boolean, true if we definitely should be binary.
proc http::IsBinaryContentType {type} {
lassign [split [string tolower $type] "/;"] major minor
if {$major eq "text"} {
return false
}
# There's a bunch of XML-as-application-format things about. See RFC 3023
# and so on.
if {$major eq "application"} {
set minor [string trimright $minor]
if {$minor in {"xml" "xml-external-parsed-entity" "xml-dtd"}} {
return false
}
}
# Not just application/foobar+xml but also image/svg+xml, so let us not
# restrict things for now...
if {[string match "*+xml" $minor]} {
return false
}
return true
}
# http::getTextLine --
#
# Get one line with the stream in blocking crlf mode
+2 -2
View File
@@ -1,2 +1,2 @@
if {![package vsatisfies [package provide Tcl] 8.6]} {return}
package ifneeded http 2.8.9 [list tclPkgSetup $dir http 2.8.9 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}]
if {![package vsatisfies [package provide Tcl] 8.6-]} {return}
package ifneeded http 2.8.10 [list tclPkgSetup $dir http 2.8.10 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}]
+1 -1
View File
@@ -11,7 +11,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
package require Tcl 8.5
package require Tcl 8.5-
# When the version number changes, be sure to update the pkgIndex.tcl file,
# and the installation directory in the Makefiles.
package provide msgcat 1.6.0
+2 -2
View File
@@ -1,9 +1,9 @@
if {([info commands ::tcl::pkgconfig] eq "")
|| ([info sharedlibextension] ne ".dll")} return
if {[::tcl::pkgconfig get debug]} {
package ifneeded registry 1.3.1 \
package ifneeded registry 1.3.2 \
[list load [file join $dir tclreg13g.dll] registry]
} else {
package ifneeded registry 1.3.1 \
package ifneeded registry 1.3.2 \
[list load [file join $dir tclreg13.dll] registry]
}
+1 -1
View File
@@ -9,4 +9,4 @@
# full path name of this file's directory.
if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded tcltest 2.3.8 [list source [file join $dir tcltest.tcl]]
package ifneeded tcltest 2.4.0 [list source [file join $dir tcltest.tcl]]
+33 -7
View File
@@ -16,13 +16,13 @@
# Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
# All rights reserved.
package require Tcl 8.5 ;# -verbose line uses [info frame]
package require Tcl 8.5- ;# -verbose line uses [info frame]
namespace eval tcltest {
# When the version number changes, be sure to update the pkgIndex.tcl file,
# and the install directory in the Makefiles. When the minor version
# changes (new feature) be sure to update the man page as well.
variable Version 2.3.8
variable Version 2.4.0
# Compatibility support for dumb variables defined in tcltest 1
# Do not use these. Call [package provide Tcl] and [info patchlevel]
@@ -611,16 +611,27 @@ namespace eval tcltest {
proc AcceptVerbose { level } {
set level [AcceptList $level]
set levelMap {
l list
p pass
b body
s skip
t start
e error
l line
m msec
u usec
}
set levelRegexp "^([join [dict values $levelMap] |])\$"
if {[llength $level] == 1} {
if {![regexp {^(pass|body|skip|start|error|line)$} $level]} {
if {![regexp $levelRegexp $level]} {
# translate single characters abbreviations to expanded list
set level [string map {p pass b body s skip t start e error l line} \
[split $level {}]]
set level [string map $levelMap [split $level {}]]
}
}
set valid [list]
foreach v $level {
if {[regexp {^(pass|body|skip|start|error|line)$} $v]} {
if {[regexp $levelRegexp $v]} {
lappend valid $v
}
}
@@ -1972,6 +1983,11 @@ proc tcltest::test {name description args} {
# Only run the test body if the setup was successful
if {!$setupFailure} {
# Register startup time
if {[IsVerbose msec] || [IsVerbose usec]} {
set timeStart [clock microseconds]
}
# Verbose notification of $body start
if {[IsVerbose start]} {
puts [outputChannel] "---- $name start"
@@ -2076,6 +2092,16 @@ proc tcltest::test {name description args} {
}
}
if {[IsVerbose msec] || [IsVerbose usec]} {
set t [expr {[clock microseconds] - $timeStart}]
if {[IsVerbose usec]} {
puts [outputChannel] "++++ $name took $t μs"
}
if {[IsVerbose msec]} {
puts [outputChannel] "++++ $name took [expr {round($t/1000.)}] ms"
}
}
# if we didn't experience any failures, then we passed
variable numTests
if {!($setupFailure || $cleanupFailure || $coreFailure
@@ -2683,7 +2709,7 @@ proc tcltest::GetMatchingDirectories {rootdir} {
DebugPuts 1 "No test directories remain after applying match\
and skip patterns!"
}
return $matchDirs
return [lsort $matchDirs]
}
# tcltest::runAllTests --
+1 -1
View File
@@ -1,7 +1,7 @@
# created by tools/tclZIC.tcl - do not edit
set TZData(:America/Cambridge_Bay) {
{-9223372036854775808 0 0 zzz}
{-9223372036854775808 0 0 -00}
{-1577923200 -25200 0 MST}
{-880210800 -21600 1 MWT}
{-769395600 -21600 1 MPT}
+1 -1
View File
@@ -1,7 +1,7 @@
# created by tools/tclZIC.tcl - do not edit
set TZData(:America/Inuvik) {
{-9223372036854775808 0 0 zzz}
{-9223372036854775808 0 0 -00}
{-536457600 -28800 0 PST}
{-147888000 -21600 1 PDDT}
{-131558400 -28800 0 PST}
+1 -1
View File
@@ -1,7 +1,7 @@
# created by tools/tclZIC.tcl - do not edit
set TZData(:America/Iqaluit) {
{-9223372036854775808 0 0 zzz}
{-9223372036854775808 0 0 -00}
{-865296000 -14400 0 EWT}
{-769395600 -14400 1 EPT}
{-765396000 -18000 0 EST}
+18 -18
View File
@@ -11,41 +11,41 @@ set TZData(:America/Los_Angeles) {
{-769395600 -25200 1 PPT}
{-765385200 -28800 0 PST}
{-757353600 -28800 0 PST}
{-687967200 -25200 1 PDT}
{-687967140 -25200 1 PDT}
{-662655600 -28800 0 PST}
{-620834400 -25200 1 PDT}
{-620838000 -25200 1 PDT}
{-608137200 -28800 0 PST}
{-589384800 -25200 1 PDT}
{-589388400 -25200 1 PDT}
{-576082800 -28800 0 PST}
{-557935200 -25200 1 PDT}
{-557938800 -25200 1 PDT}
{-544633200 -28800 0 PST}
{-526485600 -25200 1 PDT}
{-526489200 -25200 1 PDT}
{-513183600 -28800 0 PST}
{-495036000 -25200 1 PDT}
{-495039600 -25200 1 PDT}
{-481734000 -28800 0 PST}
{-463586400 -25200 1 PDT}
{-463590000 -25200 1 PDT}
{-450284400 -28800 0 PST}
{-431532000 -25200 1 PDT}
{-431535600 -25200 1 PDT}
{-418230000 -28800 0 PST}
{-400082400 -25200 1 PDT}
{-400086000 -25200 1 PDT}
{-386780400 -28800 0 PST}
{-368632800 -25200 1 PDT}
{-368636400 -25200 1 PDT}
{-355330800 -28800 0 PST}
{-337183200 -25200 1 PDT}
{-337186800 -25200 1 PDT}
{-323881200 -28800 0 PST}
{-305733600 -25200 1 PDT}
{-305737200 -25200 1 PDT}
{-292431600 -28800 0 PST}
{-273679200 -25200 1 PDT}
{-273682800 -25200 1 PDT}
{-260982000 -28800 0 PST}
{-242229600 -25200 1 PDT}
{-242233200 -25200 1 PDT}
{-226508400 -28800 0 PST}
{-210780000 -25200 1 PDT}
{-210783600 -25200 1 PDT}
{-195058800 -28800 0 PST}
{-179330400 -25200 1 PDT}
{-179334000 -25200 1 PDT}
{-163609200 -28800 0 PST}
{-147880800 -25200 1 PDT}
{-147884400 -25200 1 PDT}
{-131554800 -28800 0 PST}
{-116431200 -25200 1 PDT}
{-116434800 -25200 1 PDT}
{-100105200 -28800 0 PST}
{-94665600 -28800 0 PST}
{-84376800 -25200 1 PDT}
+1 -1
View File
@@ -1,7 +1,7 @@
# created by tools/tclZIC.tcl - do not edit
set TZData(:America/Pangnirtung) {
{-9223372036854775808 0 0 zzz}
{-9223372036854775808 0 0 -00}
{-1546300800 -14400 0 AST}
{-880221600 -10800 1 AWT}
{-769395600 -10800 1 APT}
+1 -1
View File
@@ -1,7 +1,7 @@
# created by tools/tclZIC.tcl - do not edit
set TZData(:America/Rankin_Inlet) {
{-9223372036854775808 0 0 zzz}
{-9223372036854775808 0 0 -00}
{-410227200 -21600 0 CST}
{-147895200 -14400 1 CDDT}
{-131565600 -21600 0 CST}
+1 -1
View File
@@ -1,7 +1,7 @@
# created by tools/tclZIC.tcl - do not edit
set TZData(:America/Resolute) {
{-9223372036854775808 0 0 zzz}
{-9223372036854775808 0 0 -00}
{-704937600 -21600 0 CST}
{-147895200 -14400 1 CDDT}
{-131565600 -21600 0 CST}
+7 -7
View File
@@ -14,19 +14,19 @@ set TZData(:America/Tijuana) {
{-686073600 -25200 1 PDT}
{-661539600 -28800 0 PST}
{-504892800 -28800 0 PST}
{-495036000 -25200 1 PDT}
{-495039600 -25200 1 PDT}
{-481734000 -28800 0 PST}
{-463586400 -25200 1 PDT}
{-463590000 -25200 1 PDT}
{-450284400 -28800 0 PST}
{-431532000 -25200 1 PDT}
{-431535600 -25200 1 PDT}
{-418230000 -28800 0 PST}
{-400082400 -25200 1 PDT}
{-400086000 -25200 1 PDT}
{-386780400 -28800 0 PST}
{-368632800 -25200 1 PDT}
{-368636400 -25200 1 PDT}
{-355330800 -28800 0 PST}
{-337183200 -25200 1 PDT}
{-337186800 -25200 1 PDT}
{-323881200 -28800 0 PST}
{-305733600 -25200 1 PDT}
{-305737200 -25200 1 PDT}
{-292431600 -28800 0 PST}
{-283968000 -28800 0 PST}
{189331200 -28800 0 PST}

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