Compare commits

...
Author SHA1 Message Date
jan.nijtmans 7248e185c4 Fix TCL_MEM_DEBUG build 2025-09-07 19:30:53 +00:00
jan.nijtmans 439d6c8c82 update doc 2025-09-05 09:12:52 +00:00
jan.nijtmans 8427c0c455 Introduce Tcl_AttemptGetCharLength() 2025-09-05 07:08:59 +00:00
jan.nijtmans 88f46ca664 Rebase to trunk 2025-09-04 15:01:00 +00:00
jan.nijtmans d5eccf9907 Use TclAttemptGetString() in "string repeat". Fix Tcl_AttemptNewStringObj in debug mode 2025-09-04 14:57:01 +00:00
jan.nijtmans 64287131fc Microsoft compilers don't have mode_t 2025-09-04 09:42:42 +00:00
jan.nijtmans d6f93ff450 Fix some -Wconversion warnings 2025-09-04 09:33:13 +00:00
jan.nijtmans 961684edff more Minor indent fixes 2025-09-04 08:59:08 +00:00
dkf 6b52ee1bdf Minor indent fixes 2025-09-04 08:24:38 +00:00
dkf 22de896416 Fix a minor typo in a comment 2025-09-04 08:09:58 +00:00
jan.nijtmans fddae29c41 In no-deprecate mode, don't run tests involving sqlite3. TCL_HASH_TYPE is an internal type, which shouldn't be used by extensions. 2025-09-02 13:13:31 +00:00
jan.nijtmans a27c0164cf Merge 9.0 2025-09-02 07:18:29 +00:00
jan.nijtmans 648ab28529 Update to burnett01/rsync-deployments@7.1.0 2025-09-02 07:17:37 +00:00
jan.nijtmans a251837534 Update UNICODE_OUT_OF_RANGE to handle all planes. Remove unneeded UNICODE_OUT_OF_RANGE() usage 2025-09-01 11:03:24 +00:00
dkf f924c7b244 Merge 9.0 2025-09-01 08:31:25 +00:00
dkf 82895be625 Add code comments, move a function to a better file to own it. 2025-09-01 08:19:50 +00:00
jan.nijtmans ee7950cf32 Merge 9.0 2025-09-01 07:26:29 +00:00
jan.nijtmans de01419022 Fix [85fc8bca03]: Pointer arithmetic with NULL in buildInfoObjCmd(). Update changes.md 2025-09-01 07:24:27 +00:00
apnadkarni d45e087497 Merge 9.0 - Mount zipfs early - see [87b69745be] 2025-09-01 04:58:34 +00:00
apnadkarni 69ab106ada Mount zipfs early - see [87b69745be] 2025-09-01 03:52:45 +00:00
jan.nijtmans 4c575021c7 Final verdict, without test expectation changes 2025-08-31 20:13:49 +00:00
jan.nijtmans 3a9e04c001 Oops, 21 bits, not 17 bits 2025-08-31 20:03:32 +00:00
jan.nijtmans 880c78393c Final verdict, without test expectation changes 2025-08-31 19:14:42 +00:00
jan.nijtmans e6b77e0b06 Merge 9.1 2025-08-31 17:47:54 +00:00
jan.nijtmans 7effd2e72c Merge 9.0. Fix TIP #726 implementation, so all functions give the same answer as Tcl 9.0 for out-of-bound characters 2025-08-31 17:16:26 +00:00
jan.nijtmans 385adbd9bd Add testcases for out-of-range Unicode characters 2025-08-31 16:38:23 +00:00
dkf 96b15ff9f6 Bump the patchlevel of TclOO 2025-08-31 06:14:11 +00:00
dkf 4dab6d3efb Bump the patchlevel of TclOO 2025-08-31 06:13:13 +00:00
dkf fc0255af91 merge core-9-0-branch 2025-08-30 21:20:01 +00:00
dkf d9d4467ee7 Make things that ought to be constants be so. 2025-08-30 20:36:31 +00:00
dkf 4443c3177b Put the baseline cloning (oo::object-><cloned>) of objects in C. 2025-08-30 15:13:31 +00:00
dkf f4d4331782 Backport of oo::object-><cloned> in C. 2025-08-30 15:11:38 +00:00
dkf b3960702d2 Backport of oo::object-><cloned> in C. 2025-08-30 15:10:23 +00:00
jan.nijtmans 2ac9cdcd73 Sorry Ashok, but I object to changing a right-shift (as it originally was) to a left-shift. Will explain by mail. 2025-08-30 14:36:15 +00:00
dkf 6cc00def7f Put the baseline cloning of objects in C. I'd been putting off doing this for over a decade, as it was always going to be a lot of work despite all the inefficiency... 2025-08-30 14:16:57 +00:00
apnadkarni 568aff25e3 TIP 726 2025-08-30 08:45:59 +00:00
jan.nijtmans 435c078290 More review: Eliminate UNICODE_OUT_OF_RANGE and use right-shifts 2025-08-29 13:24:17 +00:00
apnadkarni 93dd0ea623 Fix bogus assert in unicode normalization 2025-08-29 08:56:18 +00:00
apnadkarni 5406225cc1 Update changes.md 2025-08-29 02:59:15 +00:00
apnadkarni 0fad3893a7 Merge main 2025-08-29 02:58:33 +00:00
dkf 49201a46ad merge core-9-0-branch 2025-08-28 15:07:12 +00:00
dkf 71018d9954 More backported initialisation acceleration of TclOO 2025-08-28 14:56:47 +00:00
dkf 188c4a20f4 Modify code and comments for 9.0 style 2025-08-28 14:54:14 +00:00
dkf 2439cb752a Move more machinery into C from the TclOO init script 2025-08-28 14:23:48 +00:00
dkf feb0337f75 Tinkering, making code simpler or easier to maintain 2025-08-28 14:20:33 +00:00
dkf 08c1b1b2c6 Complete the moving of the definition of slots entirely into C 2025-08-28 14:19:13 +00:00
dkf bd73d3bc98 Move more machinery into C from the TclOO init script 2025-08-28 14:02:03 +00:00
dkf 30d34a3e70 Tweak comments 2025-08-28 13:49:30 +00:00
dkf 9ac7d18c6d Move oo::class::<cloned> into C 2025-08-28 13:41:47 +00:00
dkf fa8c01a36d Move remaining bits of property system into C; only cloning methods now left 2025-08-28 12:17:27 +00:00
dkf d0e53f4558 merge trunk 2025-08-28 10:39:41 +00:00
apnadkarni 2c5e56832a Merge 9.0 - Eliminate TCL_BROKEN_MAINARGS 2025-08-28 08:42:46 +00:00
apnadkarni 5f54d6e35c Eliminate TCL_BROKEN_MAINARGS 2025-08-28 08:32:19 +00:00
apnadkarni 14e507ab0f Fix unsigned char* to char* conversion warning 2025-08-28 07:52:49 +00:00
apnadkarni 69726197d8 Merge main 2025-08-28 07:18:16 +00:00
jan.nijtmans d3daca383d 2 review remarks: _CRT_glob is still necessary. And please use autoconf 2.72.
Tx for the fix - Ashok
2025-08-28 06:21:00 +00:00
apnadkarni 652558eef5 Merge 9.0 2025-08-28 06:06:37 +00:00
apnadkarni 434e26477d Get rid of obsolete TCL_BROKEN_MAINARGS 2025-08-28 03:26:11 +00:00
jan.nijtmans e2f0af2714 Fix double Tcl_Alloc define. Tweak allocation lengths reporting 2025-08-27 21:51:42 +00:00
jan.nijtmans a20eb8bc6a Rebase to latest trunk 2025-08-27 15:38:43 +00:00
jan.nijtmans bf2c7d3f0a Merge 9.0 2025-08-27 11:58:50 +00:00
jan.nijtmans 4dce301da4 Follow-up to [66cd465323]: For Tcl 9.0+, building on 32-bit MacOS is no longer supported 2025-08-27 11:57:47 +00:00
jan.nijtmans 9f4d273655 Follow-up to [66cd465323]: For Tcl 9.0+, building on 32-bit MacOS is no longer supported 2025-08-27 11:22:17 +00:00
jan.nijtmans 7de3da420f 32-bit MacOS builds are no longer supported, starting with Tcl 9.0. 2025-08-27 09:37:29 +00:00
apnadkarni 986775b761 Mount ALL zipfs archives before ANY library searches 2025-08-27 05:57:12 +00:00
apnadkarni b5dd9ceaab Create new branch named "apn-early-zipfs-mounts" 2025-08-27 05:41:45 +00:00
dkf b3722a8c03 merge trunk 2025-08-26 13:38:30 +00:00
jan.nijtmans af55dc01d8 Merge 9.0 2025-08-26 08:14:32 +00:00
sebres 029911a413 merge 9.0 2025-08-25 23:17:15 +00:00
sebres 4478afff2a fixes too earlier search for tcl-library (TclZipfsLocateTclLibrary shall be invoked after zipfs mount). 2025-08-25 22:55:02 +00:00
sebres 5860f82135 amend to [0433b67adc] (ticket [87b69745be]): don't return with OK (swallow the error) if encoding cannot be loaded, and current system encoding is NULL for whatever reason 2025-08-25 16:42:09 +00:00
jan.nijtmans ac8205c8ee Merge 9.0 2025-08-25 15:34:57 +00:00
jan.nijtmans a4b27124be [66cd465323] Platform package simplifications for MacOS >= 11. Platform => 1.1.0 2025-08-25 15:32:36 +00:00
dkf 5c6745ec03 Move the oo::configurable constructor into C 2025-08-25 15:23:25 +00:00
jan.nijtmans 3b26998f18 [66cd465323] Platform package simplifications for MacOS >= 11. Platform => 1.1.0 2025-08-25 15:08:09 +00:00
jan.nijtmans 2ecb2c5da4 Remove some more references to non-existing Tcl version 8.7 2025-08-25 11:49:51 +00:00
jan.nijtmans d284f9118b Remove some more references to non-existing Tcl version 8.7 2025-08-25 11:42:28 +00:00
jan.nijtmans b33dac7519 Merge trunk 2025-08-25 11:16:05 +00:00
jan.nijtmans 42725da7ba Merge 9.0 2025-08-25 11:13:06 +00:00
dkf f3cd1bab12 Move more of configurable's machinery into C 2025-08-25 10:59:22 +00:00
jan.nijtmans a95bde4890 Fix testcase oo-1.21 2025-08-25 09:37:02 +00:00
jan.nijtmans 71a5f30a95 Merge 8.6 2025-08-25 09:17:19 +00:00
jan.nijtmans 535d9351df Fix handling of i386-x86_64 in platform extension. Add testcases for this (and other) situation 2025-08-25 08:51:05 +00:00
dkf 2109289587 Fix bugs 2025-08-25 08:43:14 +00:00
dkf e31b21beff Move extra classes into C; mostly there, but not yet working 2025-08-25 08:30:32 +00:00
dkf d50475d2e7 Start of making the singleton class implemented in C 2025-08-24 11:47:45 +00:00
dkf 7f743eb32b Tinkering, making code simpler or easier to maintain 2025-08-24 10:40:58 +00:00
dkf 0321a464b9 Complete the moving of the definition of slots entirely into C 2025-08-24 06:52:11 +00:00
dkf 232912fd60 merge core-9-0-branch (sync after backport) 2025-08-23 08:23:41 +00:00
dkf 940919e356 Backported accelerations to TclOO's startup code 2025-08-23 08:00:12 +00:00
dkf a9af7dc696 corrections (createhashentry is different in 9.1) and cleanup (I like command tables) 2025-08-23 07:57:28 +00:00
jan.nijtmans 0a6c6bf801 Merge-mark 2025-08-22 20:27:01 +00:00
dkf 14b58a3e20 Make code style be a bit closer to the one used in 9.0 2025-08-22 19:36:33 +00:00
dkf 102d340fa6 Tweak to [configurable] to not call [next] twice (backport) 2025-08-22 19:30:49 +00:00
dkf 05ad3060a8 Combine UpdateClassDelegatesAfterClone into its caller. (backport) 2025-08-22 19:29:51 +00:00
dkf 538ca551b7 Move another definition (classmethod) into C. (backport) 2025-08-22 19:28:48 +00:00
jan.nijtmans 7e4c95c24e Fix memory debugging info 2025-08-22 19:25:13 +00:00
dkf 10b1362daa Move [link] into C. (backport) 2025-08-22 19:22:05 +00:00
dkf 0a21b6eed5 Convert MixinClassDelegates to an internal function entirely in C (backport) 2025-08-22 19:14:27 +00:00
dkf 61e2cc66b9 Move a bit of internal machinery (backport) 2025-08-22 17:36:48 +00:00
dkf 8bced55797 Move another command into C: classvariable (backport) 2025-08-22 17:35:43 +00:00
dkf cd0fea5763 Slightly faster way to write the init script (backport) 2025-08-22 17:31:50 +00:00
dkf 1154dfa4f0 Rewrite slots in C to get a performance boost. (backport) 2025-08-22 17:31:18 +00:00
dkf a93fc66525 Speed up TclOO init; no directing via unknown method handler for slots of classes we define ourselves (backport) 2025-08-22 17:18:32 +00:00
dkf a83fb66df9 Slightly chisel down the execution time of the oo init script (backport) 2025-08-22 17:17:22 +00:00
dkf ff93032670 Accelerate definition of [oo::define initialise]. (backport) 2025-08-22 17:15:48 +00:00
dkf 63e9714b2e Start making TclOO faster to initialise (backport) 2025-08-22 15:02:51 +00:00
dkf cca1a031f7 Fix memory debugging info 2025-08-22 14:52:30 +00:00
dkf 800194c7f4 Tweak to [configurable] to not call [next] twice 2025-08-22 14:23:56 +00:00
dkf eb58711740 Combine UpdateClassDelegatesAfterClone into its caller. 2025-08-22 13:43:50 +00:00
jan.nijtmans dace399671 Add testcases for platform macos26-x86_64 and macos26-arm 2025-08-22 13:06:31 +00:00
jan.nijtmans 65b29252af Fix handling of i386-x86_64 2025-08-22 12:50:28 +00:00
dkf 6a89806ee6 Move [link] into C. 2025-08-22 11:45:24 +00:00
jan.nijtmans 165eea24c0 Merge 9.0 2025-08-22 11:29:34 +00:00
dkf 1e47aa3a2e Move another definition (classmethod) into C. 2025-08-22 07:50:00 +00:00
dkf 03c0cbaafd Convert MixinClassDelegates to an internal function entirely in C 2025-08-22 07:19:52 +00:00
dkf 03dd129a16 Fix memory debugging info 2025-08-22 07:16:45 +00:00
dgp 7093dc16ae Make logical -> bitwise correction corresponding to recent change in Tcl 9. 2025-08-21 16:21:10 +00:00
jan.nijtmans 4864c57e4d Eliminate clang compiler warning: use of logical '&&' with constant operand 2025-08-21 15:53:11 +00:00
jan.nijtmans 4ee7135c5a Line no longer needed 2025-08-21 14:15:40 +00:00
jan.nijtmans 905f8b73d7 Add testcases 2025-08-21 14:00:13 +00:00
jan.nijtmans 17a2efee72 Keep all macos < 11 handling as it was 2025-08-20 21:53:34 +00:00
dkf f80e08da71 Move a bit of internal machinery 2025-08-20 12:22:28 +00:00
dkf 10f3bcbb8d Move another command into C: classvariable 2025-08-20 10:11:04 +00:00
jan.nijtmans c7706471ad Bug-fixing 2025-08-19 21:48:16 +00:00
dkf c418b4db02 Slightly faster way to write the init script 2025-08-19 15:45:53 +00:00
jan.nijtmans 562da42399 Experimental simplification for platform on MacOS 2025-08-19 15:05:34 +00:00
dkf 88928b4fff Rewrite slots in C to get a performance boost. [effa2e2346] 2025-08-19 14:49:15 +00:00
dkf e125854648 Add some documentation comments 2025-08-19 14:46:11 +00:00
dkf dde7348f86 Add remoaining slot ops 2025-08-19 14:15:18 +00:00
dkf 2d4422bbba Saner C implementation of slot methods; add unknown handler to C side 2025-08-19 13:51:54 +00:00
jan.nijtmans 01f1143ddf Merge 9.0 2025-08-19 12:45:39 +00:00
jan.nijtmans 0aad2eded0 support for MacOS Tahoe, platform => 1.0.20 2025-08-19 12:44:36 +00:00
jan.nijtmans fa96d47dfc support for MacOS Tahoe, platform => 1.0.20 2025-08-19 12:36:22 +00:00
dkf 0dcd38a24d merge trunk 2025-08-19 10:59:14 +00:00
dkf 9582b7a005 Speed up TclOO init; no directing via unknown method handler for slots of classes we define ourselves 2025-08-19 09:00:02 +00:00
dkf 4a3783d6df Working on rewriting the slot implementation in C; not quite correct yet 2025-08-19 08:57:06 +00:00
jan.nijtmans 88f4b5757c Minor corrections, handle Tcl 9 platform reductions 2025-08-18 21:49:35 +00:00
jan.nijtmans 97e33af67f Oops, shouldn't use string compare here 2025-08-18 14:18:53 +00:00
jan.nijtmans a43258ca27 Let's not break it with Tcl 8.5 2025-08-18 14:08:34 +00:00
jan.nijtmans b166c166e7 Assume that - one day - MacOS 26.5 will be there 2025-08-18 13:56:44 +00:00
jan.nijtmans f963e96259 Update changes 2025-08-18 13:27:23 +00:00
jan.nijtmans aa6bf4e80b platform version => 1.0.20 2025-08-18 13:23:27 +00:00
jan.nijtmans fef64f5de5 Update "platform" for MacOS-26 (Tahoe). See [https://core.tcl-lang.org/tk/tktview/a91b242d43|a91b242d43] 2025-08-18 13:20:32 +00:00
jan.nijtmans ac81afab4f Fixed inconsistent indenting, introduced [0433b67adc|here]. See also [87b69745be] 2025-08-18 11:49:57 +00:00
dkf 111470b8a2 Slightly chisel down the execution time of the oo init script, 2025-08-18 11:39:40 +00:00
dkf 67c8c51001 Accelerate definition of [oo::define initialise]. [effa2e2346] 2025-08-18 08:56:11 +00:00
jan.nijtmans 4b52c0611f Merge 9.0 2025-08-18 08:32:47 +00:00
jan.nijtmans 8796676d52 Better not use the old octal notation (even though it still works) 2025-08-18 08:28:13 +00:00
dkf 3095406395 Start making TclOO faster to initialise [effa2e2346] 2025-08-17 21:22:29 +00:00
jan.nijtmans 8133abce26 Merge-mark 2025-08-16 22:00:45 +00:00
jan.nijtmans 66ce9bc185 Version => 8.6.18 2025-08-16 17:17:19 +00:00
jan.nijtmans db1368a130 Merge 9.0 2025-08-15 21:25:29 +00:00
jan.nijtmans 5f00348134 Merge 8.6 2025-08-15 21:19:13 +00:00
dgp 8061873d98 Merge release 2025-08-15 19:15:53 +00:00
apnadkarni 0548037236 Merge 9.0 - Fix [87b69745be] - move zipfs encoding initialization outside of interp creation. Avoid unnecessary file system epoch bump. 2025-08-14 13:44:47 +00:00
apnadkarni 6048f838e3 Fix [87b69745be] - move zipfs encoding initialization outside of interp creation. Avoid unnecessary file system epoch bump. 2025-08-14 13:32:20 +00:00
jan.nijtmans 2fd7fd7369 Merge 9.0 2025-08-13 21:10:28 +00:00
jan.nijtmans 2e55b5dd3a When compiling for Tcl 8.6, make Tcl 9-specific API unavailable. 2025-08-13 21:03:13 +00:00
dgp b522ab7c2a merge 8.6 2025-08-13 17:18:11 +00:00
jan.nijtmans 234032f005 Remove more references to version 8.7 2025-08-13 16:43:39 +00:00
apnadkarni 5c18029325 Merge core-9-0-branch 2025-08-13 13:52:45 +00:00
jan.nijtmans 2d7d8d6fd1 Merge 9.0 2025-08-13 10:57:00 +00:00
jan.nijtmans 4b6e6f5c2c Remove another check for TCL_MINOR_VERSION < 7 2025-08-13 10:38:41 +00:00
jan.nijtmans b099f09ec9 Version => 9.1a1 2025-08-13 09:42:53 +00:00
jan.nijtmans f2fa51ec73 Update changes.md 2025-08-13 08:57:05 +00:00
jan.nijtmans d282dddcfd Merge 9.0 2025-08-13 08:55:38 +00:00
jan.nijtmans e24b8208b0 Fix [31d4fa115b]: Tweak install permissions 2025-08-13 08:54:40 +00:00
jan.nijtmans 0056593b61 Merge 9.0 2025-08-12 22:05:07 +00:00
jan.nijtmans 71e90a29ad Merge 8.6 2025-08-12 22:00:05 +00:00
jan.nijtmans 20a3d4112f Fix [992f94d847]: avoid misaligned pointers in macOS file attribute functions 2025-08-12 21:51:30 +00:00
jan.nijtmans 4ba51a6b66 Merge 8.6 2025-08-12 14:43:59 +00:00
jan.nijtmans bb662c4f7a Update dde => 1.4.5. Don't worry about Tcl 8.7 any more 2025-08-12 14:25:16 +00:00
jan.nijtmans e82486aa49 remove tclUniData.c and uniParse.tcl: not used any more 2025-08-12 13:44:57 +00:00
jan.nijtmans 9ef1e66fba Fix doc: impotent font change 2025-08-12 13:09:40 +00:00
jan.nijtmans d702f1dcba Proposed fix for [31d4fa115b]: Tweak install permissions 2025-08-12 10:23:07 +00:00
jan.nijtmans c31f8caa4d Alternative proposed fix for [992f94d847]: avoid misaligned pointers in macOS file attribute functions 2025-08-12 10:03:34 +00:00
jan.nijtmans 5178c9fe83 Merge 9.0 2025-08-12 09:28:21 +00:00
jan.nijtmans a0b91a68d7 Merge 8.6 2025-08-12 08:57:28 +00:00
jan.nijtmans 4f6b05865f Update actions/checkout@v4 to actions/checkout@v5 2025-08-12 08:49:41 +00:00
jan.nijtmans 0e0db3eebb Backport some code formatting from 9.0. Fix sentinels 2025-08-12 08:46:15 +00:00
dkf 609c82da5e Factor out a common pattern to aid comprehensibility 2025-08-06 09:30:14 +00:00
apnadkarni e1d9fc8bc1 Only update file system epoch if system encoding changes 2025-08-06 02:17:47 +00:00
apnadkarni eb1fba12e2 Reintroduce TclpSetInitialEncoding for --disable-zipfs case 2025-08-06 02:06:11 +00:00
dgp 3912efe30f Bump to tcltest 2.5.10. Code has changed since 2.5.9 release. 2025-08-04 17:34:00 +00:00
sebres fadad8447c merge 9.0 (fix for [5137b4387019d0e1]) 2025-08-04 16:05:01 +00:00
dkf 3858e79861 Correction to semantics of jumpTableNum: value argument must fit in wide int, and non-integer is an error 2025-08-04 16:03:04 +00:00
sebres 4893e98712 fixes [5137b4387019d0e1]: ensure cache of base is correct for :localtime (system TZ) if TZ-env changing, especially if there is no registry;
clock.test: several tests rewritten as locale, timezone, environment (TZ, TCL_TZ) and also registry independent, also improved several setups/cleanups and usage of test-own registry - there are also no test failures by `-singleproc 1` anymore in clock.test;
2025-08-04 15:56:28 +00:00
sebres 70efeebc57 more tests to cover issue [5137b4387019d0e1] - ensure cache of base is correct for :localtime (system TZ) if TZ-env changing (if there is no registry) 2025-08-04 15:40:20 +00:00
dgp 3cf7de3328 unused variable warning 2025-08-04 13:32:52 +00:00
apnadkarni 8b2e59a8c8 Tweak test failing on macos to report macos result 2025-08-04 09:45:38 +00:00
dkf 1ae6a7c4d3 The encoding fallback logic in ZIP handling can be done mostly by via Tcl_ExternalToUtfDStringEx now. 2025-08-04 08:58:57 +00:00
apnadkarni 7c308a99f7 Re-fix [fccb9f322f]. Also eliminate bumping of file system epoch on every interp creation introduced in Tcl 9 2025-08-03 17:42:28 +00:00
apnadkarni 902548b5ec Proposed fix for [87b69745be]. Move search of zipfs to process initialization, not interp initialization 2025-08-03 15:22:47 +00:00
apnadkarni 0a57b1e0c7 Delete extraneous redundant line 2025-08-03 15:07:31 +00:00
apnadkarni 4d20eb490b Protect zipfs location with lock 2025-08-03 14:01:28 +00:00
apnadkarni b6b37b7c74 Delete dead code 2025-08-03 12:07:40 +00:00
apnadkarni 0da7d37ae9 Move search of zipfs to process initialization, not interp initialization 2025-08-03 11:38:46 +00:00
sebres 23a39ad85f (windows, noregistry only) invalidate base fields cache for TZ ":localtime", if TZ-epoch changed (without registry module and real TZ name, the local data epoch may be updated, but cache may contain offset of previos TZ, so ensure it'd be invalidated) 2025-08-01 11:59:34 +00:00
dgp fb7805683f Open release branch
Updates to the changes file.
2025-07-31 20:03:33 +00:00
sebres 3fe5d2c50d more informative result of test clock-38.2 (in failure case it'd output all 3 results of formats as subst of expr) 2025-07-31 17:08:47 +00:00
apnadkarni a37a480bf5 Add test for [87b69745be]. 2025-07-31 13:57:58 +00:00
sebres 7ccad65c74 clock.test: fixes bug [5137b4387019d0e1] (test clock with -singleproc 1); rewrite clock tests locale, timezone, environment (TZ, TCL_TZ) and also registry independent, also improve several setups/cleanups and usage of test-own registry 2025-07-31 13:43:47 +00:00
sebres b099048f89 tcltest: output begin/end timestamps locale independently (as ISO 8601 datetime), also it'd help to avoid side effects like [5137b4387019d0e1] (windows may need registry package to get system locale) 2025-07-31 13:37:02 +00:00
dgp cc1ea405b7 merge release 2025-07-30 18:36:48 +00:00
apnadkarni 25b0e9b76d Merge 9.0 - Workaround for [8c63606802] - testsetplatform / path caching with -singleproc 1 2025-07-30 16:23:17 +00:00
apnadkarni 5c1c118b8a Workaround for [8c63606802] - testsetplatform / path caching with -singleproc 1 2025-07-30 16:20:10 +00:00
dgp e1b559b602 merge trunk 2025-07-30 15:12:31 +00:00
apnadkarni 8f511d22c9 Merge 9.0. Fix some, not all, Windows test failures with -singleproc 1 2025-07-30 11:58:49 +00:00
apnadkarni 691d6c5fc0 Fix singleproc test failures for Windows 2025-07-30 11:38:10 +00:00
apnadkarni 1be1ad4d27 Fix test errors for -singleproc 1 runs on Windows 2025-07-30 10:26:34 +00:00
apnadkarni d6ef48a710 Update changes.md for TIP's 649 and 712 2025-07-30 09:01:58 +00:00
bch 3a52401ad2 comment grammar; NFC 2025-07-27 17:42:04 +00:00
apnadkarni bd24ad87ac Add manpage for unicode command 2025-07-27 17:28:32 +00:00
apnadkarni 559b1b2e28 Add manpage for normalization API 2025-07-27 08:41:24 +00:00
apnadkarni 985deea75b Add tests Tcl_UtfToNormalized API 2025-07-27 08:07:03 +00:00
apnadkarni 4da420a519 Add C API Tcl_UtfToNormalized 2025-07-27 00:59:37 +00:00
apnadkarni 19128173ab Merge tip-726-plus to eliminate use of tclUniData.c. 2025-07-26 06:14:54 +00:00
apnadkarni 875011d6f2 Fix test loading for mingw which uses tclsh, not tcltest for tests 2025-07-26 05:26:50 +00:00
apnadkarni da34f9f408 Fix gcc warnings, mingw build and extraneous prototype defs used in debug 2025-07-26 05:00:04 +00:00
apnadkarni 97bb071f95 Remove unicode toXXXX commands as no longer needed for confirming equivalence with string toXXXX 2025-07-25 17:55:29 +00:00
apnadkarni b2d6d22bf0 Eliminate use of tclUniData.c 2025-07-25 17:46:15 +00:00
dgp 09d76814f4 merge trunk 2025-07-25 17:43:24 +00:00
apnadkarni b66fac0f73 Implement unicode toXXXX congruent to string toXXXX 2025-07-25 17:34:27 +00:00
apnadkarni fd550b5cb8 Disable tests for bug 1ecea011 2025-07-25 16:05:25 +00:00
apnadkarni 88c4d1b817 Implement unicode is CLASS to match string is CLASS 2025-07-25 15:49:23 +00:00
apnadkarni cb86661230 Merged tip-726 2025-07-23 16:28:31 +00:00
apnadkarni 4fa79a7023 Merged trunk 2025-07-23 16:27:50 +00:00
apnadkarni 039786589f Test out of range codepoints 2025-07-23 16:07:38 +00:00
sebres 09489c384b merge 9.0: improve interpreter creation speed, if there is no zipfs tcl-library (avoid performance penalty [62019f8aa9f5ec73]) 2025-07-22 18:20:45 +00:00
sebres d7c57a0c14 improve interpreter creation speed, if there is no zipfs tcl-library (avoid performance penalty [62019f8aa9f5ec73]) 2025-07-22 18:18:41 +00:00
apnadkarni 0e4baeaa35 Oops, forgot upper case 2025-07-22 17:53:30 +00:00
apnadkarni a7943f6350 Add UCD tests for string is lower,upper. Add ICU and utf8proc API's for the same 2025-07-22 17:40:51 +00:00
apnadkarni 650bb69c7b Add support to read UCD properties file 2025-07-22 17:30:46 +00:00
apnadkarni 60f0a67594 Move UCD readers into separate file 2025-07-22 12:02:50 +00:00
apnadkarni a025151f2d Add normalization tests for nul and tcl8 profile. Fix linker warnings on Windows. 2025-07-22 10:40:26 +00:00
sebres 5c3426d524 merge 9.0 to trunk: amend to [61c01e0edb08a9ed], more cases for increment ref-count with use-after-free prevention for interim normalized path object; provide fixes minimally invasive (if API used with fresh created path object, so decrement would not destroy it if normalized path equal original given path) 2025-07-21 18:57:36 +00:00
sebres cb3067db94 merge 8.6 to 9.0: amend to [61c01e0edb08a9ed], more cases for increment ref-count with use-after-free prevention for interim normalized path object; provide fixes minimally invasive (if API used with fresh created path object, so decrement would not destroy it if normalized path equal original given path) 2025-07-21 18:54:00 +00:00
sebres 899a818f23 merge 8.5 to 8.6: amend to [61c01e0edb08a9ed], more cases for increment ref-count with use-after-free prevention for interim normalized path object; provide fixes minimally invasive (if API used with fresh created path object, so decrement would not destroy it if normalized path equal original given path) 2025-07-21 18:32:50 +00:00
sebres e7e759c639 amend to [61c01e0edb08a9ed], more cases for increment ref-count with use-after-free prevention for interim normalized path object; provide fixes minimally invasive (if API used with fresh created path object, so decrement would not destroy it if normalized path equal original given path) 2025-07-21 18:21:43 +00:00
sebres 970eb178b2 merge 9.0 to trunk: fixes [61c01e0edb08a9ed] (TclpMatchInDirectory, windows only), increment ref-count to avoid use-after-free for interim normalized path object, what may cause crash (SF/BO), usage of wrong path, etc. 2025-07-18 17:45:41 +00:00
sebres 135e331c3a merge 8.6 to 9.0: fixes [61c01e0edb08a9ed] (TclpMatchInDirectory, windows only), increment ref-count to avoid use-after-free for interim normalized path object, what may cause crash (SF/BO), usage of wrong path, etc. 2025-07-18 17:38:39 +00:00
sebres 9ff2ef9fe1 merge 8.5 to 8.6: fixes [61c01e0edb08a9ed] (TclpMatchInDirectory, windows only), increment ref-count to avoid use-after-free for interim normalized path object, what may cause crash (SF/BO), usage of wrong path, etc. 2025-07-18 17:29:45 +00:00
sebres 6f2c08cfba fixes [61c01e0edb08a9ed] (TclpMatchInDirectory, windows only), increment ref-count to avoid use-after-free for interim normalized path object, what may cause crash (SF/BO), usage of wrong path, etc. 2025-07-18 17:20:51 +00:00
jan.nijtmans de58f61c2a Merge 9.0 2025-07-18 17:06:10 +00:00
jan.nijtmans 8fb869a726 Add check for working --disable-high-entropy-va. Fix check for --enable-auto-image-base (which always succeeded) 2025-07-18 17:02:29 +00:00
jan.nijtmans 635ba5bd14 Add check for working --disable-high-entropy-va. Fix check for --enable-auto-image-base (which always succeeded) 2025-07-18 11:52:06 +00:00
jan.nijtmans e499be71f0 Add check for working --disable-high-entropy-va. Fix check for --enable-auto-image-base (which always succeeded) 2025-07-18 09:52:12 +00:00
jan.nijtmans 9feb99ecb1 Fix 2 warnings on 32-bit platform (thanks, Emiliano) 2025-07-18 07:37:28 +00:00
dgp 06740b2fe5 merge trunk 2025-07-17 15:36:57 +00:00
jan.nijtmans 78cb74134b Fix installation of dde/registry packages (Thanks, Harald, for noticing this!) 2025-07-17 07:59:16 +00:00
jan.nijtmans c1432f0462 Merge 9.0 2025-07-17 07:47:44 +00:00
jan.nijtmans db32da8682 Merge 8.6 2025-07-17 07:41:05 +00:00
jan.nijtmans a8a1f62999 Fix [https://core.tcl-lang.org/tk/info/06892c6e12|06892c6e12]: loading windows dll's in Cygwin doesn't work with high-entropy-va 2025-07-17 07:15:30 +00:00
apnadkarni 5af2155539 Merge 9.0 - Fix [c9f0520f7e] 2025-07-16 16:44:34 +00:00
apnadkarni c9498e0b05 Merge 8.6. Fix [c9f0520f7e] - Tcl_SplitList memory size computation overflow. No test because not practical to overflow Tcl_Size on 9.0. 2025-07-16 16:26:59 +00:00
apnadkarni 7fe677cf6b Fix [c9f0520f7e] - Tcl_SplitList memory overflow overwrite 2025-07-16 15:26:05 +00:00
apnadkarni 71581e9afa Check interp for NULL before storing error! 2025-07-16 11:26:46 +00:00
apnadkarni 4882c7bc07 Merge 8.6 2025-07-16 10:49:49 +00:00
apnadkarni dde6018798 Add tests for C API 2025-07-16 04:53:02 +00:00
dgp 21d149f5e9 merge trunk 2025-07-15 16:35:37 +00:00
apnadkarni dc7f50b812 TIP 726 implementation with tests 2025-07-15 11:41:33 +00:00
jan.nijtmans 6fb310bb09 Merge 8.6 2025-07-15 10:25:46 +00:00
jan.nijtmans 45f4c1b34e 2 minor comment fixes 2025-07-15 10:21:13 +00:00
jan.nijtmans 4562b6d22c Minor review comment (since 8.6 still uses ckfree) 2025-07-15 10:14:35 +00:00
apnadkarni 0dee7bed88 Proposed fix for [c9f0520f7e] Tcl_SplitList crash. 2025-07-15 03:31:20 +00:00
apnadkarni f4a5ba54ac Fix [25265a2705] - dup test names in listTypes.test 2025-07-15 02:31:28 +00:00
apnadkarni b1ac90a4a8 Implement Tcl_UtfToNormalizedDString 2025-07-14 16:44:26 +00:00
jan.nijtmans 1528383bf1 Backout [816e9ddf1b]: TclVarHashCreateVar() is still used in Itcl 2025-07-14 15:31:08 +00:00
dgp e6d42cbc43 Open release branch for 9.1a0 2025-07-14 12:30:56 +00:00
jan.nijtmans f9d43f296c Doc update. See [8cd74c5cd2] 2025-07-13 08:30:48 +00:00
jan.nijtmans c3ceb84d68 Doc update. See [8cd74c5cd2] 2025-07-13 08:02:35 +00:00
jan.nijtmans 23015fefad Doc update. See [8cd74c5cd2]. Backport more doc improvements from 9.1 2025-07-13 07:51:22 +00:00
jan.nijtmans b9b2db3c5f [8cd74c5cd2]: 2-argument string toupper/tolower/totitle doesn't work as documented. Either change the documentation, or the implementation. Both are done in this commit (but only one of them should be merged to trunk) 2025-07-12 16:42:09 +00:00
apnadkarni 0b12aaa081 Start on TIP 726. Add utf8proc to the build system 2025-07-12 16:03:14 +00:00
jan.nijtmans 01ff23f34d Some int -> Tcl_Size modifications, and type-cast changes, which were missed up to now. 2025-07-10 11:50:06 +00:00
jan.nijtmans 8727b0b49a Related to [bdaf890168]: Use Tcl_Size in stead of int while using TclParseAllWhiteSpace() 2025-07-09 12:31:12 +00:00
apnadkarni 6e5503565e Fix [f8dd3d8d35]. Memory leak in uplevel compile 2025-07-08 14:23:55 +00:00
apnadkarni 51f172a42a Proposed fix for [f8dd3d8d35]. Memory leak in uplevel compile. 2025-07-08 02:58:56 +00:00
apnadkarni 0f6435157f TIP 649 2025-07-05 09:36:47 +00:00
apnadkarni f6bf9def7e Merge trunk 2025-07-05 06:05:51 +00:00
jan.nijtmans b01a4e6bd3 Merge 9.0 2025-07-03 11:59:16 +00:00
jan.nijtmans 1a3d7da175 Version -> 9.0.3 2025-07-03 11:57:22 +00:00
jan.nijtmans b4169bc203 Fix [6b8e39e83]: On Unix, IsTimeNative() always defined but not always used 2025-07-03 10:42:21 +00:00
jan.nijtmans 1d58e7eba2 Merge 9.0 2025-07-03 09:20:53 +00:00
jan.nijtmans 4e8007f55d Merge-mark 2025-07-03 08:11:40 +00:00
jan.nijtmans 40bc3d16a3 Fix [6b0f776c52]: gcc 14 breaks configure test for bigendian leading to broken floating point 2025-07-03 07:45:14 +00:00
dgp e4f4cb135c merge release 2025-07-02 15:16:16 +00:00
dgp 0cb9c0b3f8 merge 9.0 2025-07-01 17:28:51 +00:00
dgp 66c3ad95b6 Edits to the changes file 2025-07-01 15:23:13 +00:00
oehhar 4073788a7e [0cb3d93a] fix example in link documentation 2025-07-01 07:56:25 +00:00
oehhar ed50905900 [0cb3d93a] fix example in link documentation 2025-07-01 07:55:02 +00:00
dgp 2a51e8e640 Note the new releases of bundled packages in the changes. 2025-06-30 21:23:58 +00:00
dgp cb357cc4bf merge 9.0 2025-06-30 20:11:39 +00:00
dkf 99cd5e5444 Make some internal magic flags into an enum. Nobody will ever override these. 2025-06-30 14:59:32 +00:00
jan.nijtmans 8f6b586b58 Unbreak build with clang, introduced in last few commits 2025-06-29 19:38:44 +00:00
dkf 934c9819c7 Add bytecode compilation of [uplevel] 2025-06-29 06:36:50 +00:00
dkf e634d18c48 merge trunk 2025-06-29 06:25:43 +00:00
dkf 7ec3df7ddd Add bytecode compilation of [lseq] 2025-06-29 06:21:24 +00:00
dkf cb435cd742 Add bytecode compilation of [ledit] and [lpop] 2025-06-29 06:09:32 +00:00
apnadkarni 8678f0ba6a Merge 9.0. Fix test exec-bug-4f0b5767ac error when MSYS scrubs PATH 2025-06-28 10:47:53 +00:00
apnadkarni 269d6061c3 Fix test exec-bug-4f0b5767ac error when MSYS scrubs PATH 2025-06-28 10:45:43 +00:00
jan.nijtmans cb6415b2d5 Merge 9.0 2025-06-27 15:41:21 +00:00
jan.nijtmans 34630d5ca1 Fix [9dfae3413d]: interp limit commands still seems to be 32 bits 2025-06-27 15:28:01 +00:00
jan.nijtmans b50a64424f Fix [ef7042075c]: tcl::build-info not documented 2025-06-27 15:20:01 +00:00
dkf 72ab4731bf merge trunk 2025-06-27 10:55:20 +00:00
dkf 93c204b162 merge trunk 2025-06-27 10:53:43 +00:00
dkf ee4c12f1b4 merge trunk 2025-06-27 10:50:43 +00:00
dkf 5142b5748e All test cases now pass. 2025-06-27 10:50:11 +00:00
jan.nijtmans 5d75a1e629 Merge 9.0 2025-06-27 08:34:44 +00:00
jan.nijtmans 662d103e7d doc fix 2025-06-27 08:12:13 +00:00
dkf 0d4d978c52 Some of the test failures fixed... 2025-06-27 08:03:03 +00:00
apnadkarni 5721de48ca Make exec-bug-4f0b5767ac test independent of locale 2025-06-27 07:45:18 +00:00
jan.nijtmans bb3e4af18d Make all references to -DFOO compiler flags bold in documentation 2025-06-27 07:16:03 +00:00
dgp e41cc9b99b merge 9.0 2025-06-26 14:51:57 +00:00
dkf ce70b3ebe4 Compiled [uplevel] works. Except for some tests which see differences in [info frame] as a result. 2025-06-26 14:28:29 +00:00
jan.nijtmans dc55749c58 Merge 9.0 2025-06-26 13:46:33 +00:00
jan.nijtmans af368b9049 Document what happens for non-documented field values 2025-06-26 13:38:36 +00:00
dgp b824cdafec [27fa01a7db] Restore default option to [namespace which] implementation. 2025-06-26 13:19:43 +00:00
dkf 6c2dedfaa4 Draft of instruction done... but crashes. 2025-06-26 13:12:02 +00:00
jan.nijtmans 9e7c74bb55 Merge 9.0 2025-06-26 11:15:59 +00:00
jan.nijtmans 55777cb64d Make everthing compile (again) and run with a C++ compiler. 2025-06-26 11:14:11 +00:00
dkf 89b3243fd8 Start of developing compilation for [uplevel] 2025-06-26 10:45:06 +00:00
dkf 9cd8ebbfe8 mark some more commands for future expansion consideration 2025-06-26 10:32:07 +00:00
jan.nijtmans ad4985397d Merge 9.0 2025-06-26 09:56:50 +00:00
jan.nijtmans ecd951296b tclWinPipe.c:3427:12: warning: unused parameter ‘wakeEvent’ [-Wunused-parameter] 2025-06-26 09:55:11 +00:00
jan.nijtmans bc62e73bb8 @dkf's review comments (Thanks!) 2025-06-26 08:48:02 +00:00
jan.nijtmans d5ba2b9a38 Fix Tcl_LimitGetCommands() signature (int -> Tcl_Size) 2025-06-26 08:03:33 +00:00
jan.nijtmans c708a47b25 Fix [9dfae3413d]: interp limit commands still seems to be 32 bits 2025-06-26 07:59:27 +00:00
dkf daa1e38bab merge trunk 2025-06-26 07:56:35 +00:00
dkf 2426c3bd63 Change bytecode flag names to match their related instruction 2025-06-26 07:53:31 +00:00
jan.nijtmans d84809538f [ef7042075c]: tcl::build-info not documented 2025-06-26 07:35:48 +00:00
apnadkarni d832d24006 Merge 9.0 - Fix [40b1814b93] and [7c2716733a] Window handle use-after-frees. 2025-06-25 16:41:27 +00:00
apnadkarni ea836428c1 Fix [7c2716733a] - use after free on Windows pipe handles 2025-06-25 16:23:23 +00:00
apnadkarni afdd41dd6a Fix [40b1814b93] - use after free on TSD in Winsock 2025-06-25 15:48:13 +00:00
dkf 8b9e2d4583 Better disassembly of [lpop]-related flag argument 2025-06-25 13:46:01 +00:00
dgp e6fdf643b3 merge 9.0 2025-06-25 13:44:07 +00:00
jan.nijtmans b90ddeb75c Merge 9.0 2025-06-25 12:20:30 +00:00
jan.nijtmans b264aa7c57 Merge-mark 2025-06-25 12:04:48 +00:00
jan.nijtmans 264e9e9793 Fix [ecafd8611d]: Euro/Tail-sign missing from cp864 encoding 2025-06-25 11:51:09 +00:00
jan.nijtmans 2e36c3e97b Fix [ecafd8611d]: Euro/Tail-sign missing from cp864 encoding 2025-06-25 11:15:53 +00:00
jan.nijtmans e57c57e122 Fix [ecafd8] Euro-sign missing from cp864 encoding 2025-06-25 09:38:58 +00:00
dkf 3b5e99739b Better argument processing order in [lpop] compiler. Not necessary, but nicer to read 2025-06-25 09:10:40 +00:00
dkf f1d8f0a503 Handle non-trivial single indices in [lpop] compiler 2025-06-25 07:25:04 +00:00
apnadkarni 7b258bd47c Merge 9.0 2025-06-25 03:29:27 +00:00
apnadkarni 7b458b0a03 Merge 9.0 2025-06-25 03:09:52 +00:00
dkf 17437636cb merge trunk 2025-06-24 20:18:46 +00:00
dkf 3c192328ca Better compilation of [ledit]. Still not convinced about refcount management 2025-06-24 20:16:41 +00:00
dgp 5193d058c2 [ecf35c7120] Correct nested handling of return option -options
(backport from 9.0)
2025-06-24 17:15:01 +00:00
dgp 214cce5517 merge 9.0 2025-06-24 16:55:07 +00:00
dgp dcb9cf19bb merge 9.0 2025-06-24 16:35:48 +00:00
dgp 86070b6f26 [ecf35c7120] Correct nested handling of return option -options 2025-06-24 16:23:04 +00:00
jan.nijtmans 122a3f6a2d Add testcases 2025-06-24 15:09:15 +00:00
jan.nijtmans 69768ac78c Fix encoding-28.0 unit-test, since we now have an additional encoding 2025-06-24 14:59:34 +00:00
jan.nijtmans 487afeafb4 Fix [ecafd8611d]: Euro-sign missing from cp864 encoding. While on it, add cp165 which is very similar to cp864 2025-06-24 14:54:48 +00:00
dkf a46ef482b3 Note about variable ordering 2025-06-24 08:11:43 +00:00
dkf a570556b6e Add [ledit] compilation, tweak safety conditions in [lpop] compiler 2025-06-24 08:02:26 +00:00
dgp cc4e06ba60 [ecf35c7120] Pending fix for nested -options processing. 2025-06-23 19:58:15 +00:00
dgp 9631a6e074 Two more tests demonstrating the inconsistency between processing
-options {...} to emulate {*} argument expansion and processing
according to the behavior of dictionaries and how [dict create] combines
its arguments, notably how it handes duplicate keys.

This is exposed by nested -options, because the outer processing handles
in one way, while the nested processing handles in the other way.
2025-06-23 17:36:21 +00:00
dkf 24a53e6920 Move test to runtime, check enabled by new flag bit to INST_LREPLACE 2025-06-23 16:17:42 +00:00
dkf 1b050f07c1 Add in test for index-in-range. Not enough... but fixes some test cases. 2025-06-23 16:04:28 +00:00
dkf 209a4cd4ff Tweak tests; still test the same thing, but more succinctly 2025-06-23 14:55:41 +00:00
dkf 0ae1b02c78 improve tests: run in procedure context as well as outside 2025-06-23 11:33:13 +00:00
dkf 7ad8f9bfd7 Partial compilation of [lpop]; missing error handling 2025-06-23 11:14:19 +00:00
dkf 2d48fa2684 Mark some commands as needing bytecode compilation. Capitalise some function names to follow Tcl style 2025-06-23 07:39:13 +00:00
dkf c8a2ab1879 Move code that might work to shared place, and delete copy that definitely won't ever work 2025-06-23 07:26:33 +00:00
dkf b20c1053ab merge trunk 2025-06-23 06:57:16 +00:00
dkf 6c81bff536 Make [yieldto] work with {*}; turns out no new opcodes were needed, just a test for a previously-impossible case 2025-06-22 13:52:20 +00:00
apnadkarni e8b57cc705 Merge trunk 2025-06-22 08:44:53 +00:00
apnadkarni 636cda54f0 Avoid repetion in manpage 2025-06-22 08:43:51 +00:00
apnadkarni 8a631b4d12 Update manpages for TIP 649 2025-06-22 08:39:08 +00:00
apnadkarni ea30a47ef4 Better limit exceeded message 2025-06-22 05:01:21 +00:00
apnadkarni f981dcbe94 Clean up comments 2025-06-22 03:17:40 +00:00
apnadkarni 8e85d70b91 Use list limit error reporting function 2025-06-22 02:43:25 +00:00
dkf 0d3b650a17 merge trunk 2025-06-21 10:31:46 +00:00
dkf 8db5a8ae20 Make the bytecode compilation of [next] and [nextto] understand {*} in arguments. 2025-06-21 10:29:29 +00:00
apnadkarni 1b671ec0dd Update two tests - lassign will no longer shimmer abstract lists even if they lack a slice method 2025-06-21 10:10:47 +00:00
apnadkarni 66cd404c19 Merge trunk 2025-06-21 09:46:28 +00:00
dkf aa73ee6e56 Better express intent of a cast 2025-06-21 08:06:26 +00:00
dkf 16c428e8b9 merge trunk 2025-06-21 07:57:19 +00:00
dkf 624802c0f3 merge trunk 2025-06-21 07:56:31 +00:00
dgp 4b07d6b1e2 [ecf35c7120] Test for the bug. Open branch for fixing. 2025-06-20 17:24:27 +00:00
dgp 480e15a41c silence compiler warning 2025-06-20 17:14:08 +00:00
apnadkarni beb9469222 Merge 9.0. Fix [e8b18d7b1f] - release encodings on error 2025-06-20 16:05:22 +00:00
apnadkarni f1a3e189ec Fix [e8b18d7b1f] - release encodings on error 2025-06-20 16:00:23 +00:00
dkf 44b80fc8ad Clean up aux data correctly on failed compile [c587295271] 2025-06-20 15:51:53 +00:00
apnadkarni 68c9014a4a Partial fix for [c587295271] memory leak in TclCompileTryCmd 2025-06-19 16:14:57 +00:00
dkf 84be74fba6 Move general variable compiler to file where it makes sense 2025-06-19 14:08:10 +00:00
dkf baec983c04 Make more assoc-data keys into named defines, for greater mnemonicity 2025-06-19 13:52:17 +00:00
apnadkarni fea176b546 Start on [e8b18d7b1f] fix. 2025-06-18 18:12:18 +00:00
apnadkarni 7b90822271 Merge 9.0. Fix [4f338b91c1] - add missing Tcl_CloseEx docs 2025-06-18 17:39:32 +00:00
apnadkarni 19591e2473 Merge 8.6. Fix [4f338b91c1] - add missing Tcl_CloseEx docs 2025-06-18 17:34:31 +00:00
apnadkarni c39440fea5 Fix [4f338b91c1] - add missing Tcl_CloseEx docs 2025-06-18 17:24:11 +00:00
apnadkarni 875729efc9 Fix indent 2025-06-18 17:14:34 +00:00
apnadkarni 2aabb685b6 Merge trunk 2025-06-18 15:55:09 +00:00
jan.nijtmans 1b654bc947 Fix indenting/eol-spacing 2025-06-18 11:22:09 +00:00
dkf dc52697066 tidy up some list related code; no functionality change 2025-06-18 10:48:30 +00:00
dgp 5aff1b51d1 merge 9.0 2025-06-17 16:28:01 +00:00
dgp b55915dc2d merge 9.0 2025-06-17 16:27:34 +00:00
dgp ec6493f2b8 [da5e1bc7bc] exec channel not closed on errors 2025-06-17 16:06:02 +00:00
oehhar 74867b094c Update macOS info in README.md and macosx/README 2025-06-17 14:52:15 +00:00
culler 5c21ccca7b Update macOS info in README.md and macosx/README 2025-06-17 13:35:58 +00:00
max dab38fe514 TIP 712 - Add "positive" options to the subst command 2025-06-17 12:27:48 +00:00
dkf 28aca7303b merge trunk 2025-06-17 10:17:49 +00:00
dkf 43cbca4fbf Make ParseArithSeriesArgument slightly better 2025-06-17 08:57:47 +00:00
dkf 01cd0a0e45 Reduce number of gotos (and general twistiness) in GenerateArithSeries 2025-06-17 08:51:10 +00:00
dkf d5fb294747 Move most of INST_ARITH_SERIES logic into a separate function. Much easier to understand that way. 2025-06-17 08:19:17 +00:00
apnadkarni c283aca1bc Document Tcl_CloseEx. Proposed fix for [4f338b91c1]. 2025-06-17 05:26:38 +00:00
apnadkarni f07a0838c2 Bug [da5e1bc7bc] - exec channel not closed on errors 2025-06-17 04:26:54 +00:00
dgp 94b7fc5ca7 makeFile hygiene 2025-06-16 19:04:20 +00:00
dgp 99d97ce43f Dup test name 2025-06-16 19:01:44 +00:00
dgp 7278dc8cbc Open release branch for Tcl 9.0.2 2025-06-16 17:50:22 +00:00
dkf 3de98b6fb6 Add compilers for expanding [next] and [nextto] 2025-06-16 16:02:11 +00:00
dkf b38f2f3429 Neater comment 2025-06-16 11:54:09 +00:00
dkf cea3281fa1 Use function we have in other appropriate places 2025-06-16 11:52:14 +00:00
dkf b537b155ed more cleaning up of the way [next]'s bytecode works 2025-06-16 11:43:35 +00:00
dkf ccdaf5990b Start of {*}-aware [next] and [nextto] 2025-06-16 10:41:48 +00:00
apnadkarni bd808f7dcc Fat fingers in constraints 2025-06-15 10:15:48 +00:00
apnadkarni 5e3100e225 Merge 9.0 - tests for handle leaks for exec 2025-06-15 03:03:13 +00:00
apnadkarni e88b3c601b Add tests to check handle leaks for exec 2025-06-15 03:01:46 +00:00
apnadkarni 38808ad999 Bug [7c2716733a] - use after free on Windows event handle 2025-06-14 13:59:53 +00:00
apnadkarni a01dee70ea Disable additional tests under App Verifier - timing or locale do not work with it 2025-06-14 13:59:08 +00:00
apnadkarni 11ab70fd89 Merge 9.0 - Disable timing dependent tests when running under AppVerifier on Windows 2025-06-14 11:50:26 +00:00
apnadkarni 1dfad0a9d3 Merge core-9-0-branch 2025-06-14 11:44:45 +00:00
apnadkarni d24753dbf1 Disable timing dependent tests when running under AppVerifier on Windows 2025-06-14 11:40:33 +00:00
apnadkarni 1958ac85c0 Bug [40b1814b93] - Proposed fix for Winsock use-after-frees 2025-06-14 05:31:49 +00:00
apnadkarni 6ad83f332d Merge 9.0 - Add testhandlecount command. 2025-06-14 03:29:29 +00:00
apnadkarni 995249252e Add testhandlecount command to check Windows handle leaks 2025-06-14 03:25:33 +00:00
dkf c7a571a771 merge trunk 2025-06-13 13:32:43 +00:00
dkf 0cf8975e2a Implement [tailcall {*}...] in bytecode 2025-06-13 13:27:53 +00:00
dkf a367c2d812 Add new macro, EnvIsProc, to cover cases where we should be stricter. [fa7995bdf2] 2025-06-13 08:14:31 +00:00
dkf 7b34cb4a15 [fa7995bdf2] Add more direct test case for real bug 2025-06-13 07:46:41 +00:00
dkf c6afdfc531 Move magic values into header file 2025-06-13 07:22:59 +00:00
dgp 6cc142428e [fa7995bdf2] End multiple segfaults in httpcookie.test. 2025-06-12 15:08:52 +00:00
dkf 24f8828f4d merge trunk 2025-06-12 08:58:07 +00:00
dkf a7346777c6 Make sure there are no memory leaks in the arithSeries operation 2025-06-11 12:41:08 +00:00
dkf 082bbbea10 All edge case tests now pass. But why does [lseq] behave like this??? 2025-06-11 11:00:04 +00:00
dkf f748950db6 More edge cases 2025-06-11 08:45:36 +00:00
dkf 304456608e final cases 2025-06-10 16:28:27 +00:00
dkf 3ab0bb6501 Handle the three-argument cases 2025-06-10 16:07:17 +00:00
dkf b4b10b99d7 And I already have the right tools to make this easy. Excellent. 2025-06-10 15:32:47 +00:00
dkf ce74537dd7 Add compilation of two arg case... and note that we need to compile args as expressions 2025-06-10 15:25:41 +00:00
jan.nijtmans da8d758711 Merge 9.0 2025-06-10 15:12:44 +00:00
dkf e7cf3a048c Basic [lseq] compiler that handles just the one case. 2025-06-10 15:12:43 +00:00
dkf 401ff4964c Name the operation's flag bits 2025-06-10 15:00:42 +00:00
jan.nijtmans 76f4308926 Fix [0ee626dfb2]: lseq numeric overflow 2025-06-10 14:18:14 +00:00
dkf abc2391b16 Define an instruction to build an arithmetic series. Not yet issued 2025-06-10 13:53:59 +00:00
dkf 077a6cbece Outermost skeleton of [lseq] compiler. Much more still to do! 2025-06-10 11:38:33 +00:00
dkf 6cdf0568cf Tinkering with the ArithSeries object type implementation 2025-06-10 11:34:13 +00:00
jan.nijtmans 4bdb2c7b6e Fix [b876737a0b]: tcl::tm::path doesn't handle tilde expand 2025-06-10 11:34:07 +00:00
jan.nijtmans 791b296b8e Let the caller of ::tcl::tm::roots do the [file tildeexpand] 2025-06-10 10:56:07 +00:00
dkf 7d0bbc47d7 Delete code that caused failures with -ftrapv and otherwise did nothing useful 2025-06-10 09:08:23 +00:00
dkf f6627105c2 Remove unused argument 2025-06-10 08:41:00 +00:00
dkf be130b0337 Convert defines to enums in remaining Windows-specific code 2025-06-10 07:53:06 +00:00
jan.nijtmans 40c5514475 Backport github ACTIONS build scripts from Tcl 9.1 2025-06-09 19:08:03 +00:00
jan.nijtmans 62d918cae7 Fix for [b876737a0b]: tcl::tm::path doesn't handle tilde expand 2025-06-09 16:55:39 +00:00
jan.nijtmans 8ebcf55a9f Merge 8.6 2025-06-09 13:58:21 +00:00
apnadkarni cd3de32c6b Merge core-9-0-branch. Pick up fix for [0ee626dfb2] and other sundry unmerged changes 2025-06-09 13:41:41 +00:00
jan.nijtmans 255658907d Backout [ac279496ac], see [https://core.tcl-lang.org/tk/info/1562e10c58]. Since Tk 8.7 won't be released, we don't have to worry about multiple Tk versions for Tcl 8.6 2025-06-09 13:31:02 +00:00
apnadkarni 36db921e01 Fix [0ee626dfb2] - lseq numeric overflow 2025-06-09 13:17:48 +00:00
jan.nijtmans e569e9e9ab Indenting 2025-06-09 11:17:54 +00:00
dkf c34088c42a Greatly improved [tailcall] handling, including more special cases. 2025-06-09 08:18:09 +00:00
apnadkarni 1b6a0ff3b0 Clarify in manpage that lseq can produce doubles 2025-06-09 06:03:26 +00:00
apnadkarni 31181a01b6 Merge trunk 2025-06-09 05:34:19 +00:00
apnadkarni 08f8cf1a9e Bug [0ee626dfb2] - arithseries integer overflow checks 2025-06-08 12:02:53 +00:00
dkf 2ea0874f3f merge trunk 2025-06-08 11:58:01 +00:00
apnadkarni 2d357d6e45 Add test cases 2025-06-08 11:34:21 +00:00
dkf 502fec899c Fix error 2025-06-08 11:30:01 +00:00
apnadkarni 1d7632f6e0 Create new branch named "bug-0ee626dfb2" 2025-06-08 11:18:31 +00:00
apnadkarni 9ca9c5016b Added memory leak tests for Tcl_ListObj* 2025-06-07 16:08:16 +00:00
apnadkarni ee9184e1a9 Add Tcl_ListObjReverse tests 2025-06-07 15:17:36 +00:00
apnadkarni c4db257e2e Tests for Tcl_ListObjRepeat 2025-06-07 07:55:43 +00:00
jan.nijtmans 7c6afac7e6 Fix [2bf9fbcb99]: Tcl 9 docs outdated regarding tcl_platform(threaded) 2025-06-06 22:34:11 +00:00
apnadkarni f1d660fcb3 Start on TIP 649 tests. Also fix [5773c78e86]. 2025-06-06 16:55:52 +00:00
dkf 98d42037a5 merge trunk 2025-06-06 14:58:31 +00:00
dkf 326bfdff35 give tests human-readable names 2025-06-06 13:54:51 +00:00
dkf de6f149f5f fix silly capitalisation error 2025-06-06 13:33:10 +00:00
dkf 48c4185146 After private testing, this works correctly and is shorter too 2025-06-06 13:29:37 +00:00
dkf 0eb53a0627 [9a2351225c] Alternate, portable way of testing for [foreach] and [lseq] interacting badly 2025-06-06 08:39:54 +00:00
dkf 370566c1e6 That script can be used on the other two platforms too. Excellent! 2025-06-06 08:28:16 +00:00
dkf dfa4a65a52 Move support Tcl script into its own file 2025-06-06 08:24:34 +00:00
apnadkarni 24d8781502 Add new list functions to stubs 2025-06-06 05:49:35 +00:00
apnadkarni e2ce695c5d Start on TIP 649 2025-06-05 13:49:37 +00:00
dkf 3170aa3764 Don't need to save the value from the subprocess in a variable 2025-06-05 12:49:07 +00:00
dkf 114535264c Alternate way of testing for no memory bloat in foreach+lseq; should be cross-platform and MUCH less sensitive to configuration 2025-06-05 08:42:11 +00:00
dkf 35dc38b268 rewrite test to use a constraint instead of a silly result condition 2025-06-05 08:17:53 +00:00
jan.nijtmans d4406723ec Check for tag "core-*", not "core-**" everywhere the same 2025-06-05 08:12:05 +00:00
dkf b9f37656c8 Correct syntax error in github action command files 2025-06-05 08:02:41 +00:00
dkf d554c361d3 Reduce size of build matrices for non-critical commits. This needs deeper Github Actions wizardry. 2025-06-04 10:51:44 +00:00
jan.nijtmans e0792c933b Merge 9.0 2025-06-04 10:28:41 +00:00
jan.nijtmans b4f22927e5 fix leak in lseq.test 2025-06-04 10:21:51 +00:00
jan.nijtmans 1978e5ad54 Simplify tcl::build-info parsing for testConstraint's 2025-06-04 07:54:00 +00:00
apnadkarni 08fa057f64 Update changes.md for TIP's 711, 716, 717 2025-06-04 03:26:53 +00:00
apnadkarni a9d4c8d1cd TIP 716 - add stub for Tcl_GetEncodingNameForUser 2025-06-04 03:11:35 +00:00
dkf d0020e0e23 Make the [tailcall] compiler understand {*}; a common case 2025-06-03 15:16:07 +00:00
apnadkarni 5cced2c4ac Test Tcl_GetEncodingName* functions callable via stubs 2025-06-03 05:00:27 +00:00
apnadkarni a331adea33 Add stubs function from TIP 716 2025-06-03 03:34:57 +00:00
jan.nijtmans ba9e9a59a9 rebase to trunk 2025-06-02 15:52:36 +00:00
apnadkarni 6e5baa7e71 Merge mark 2025-06-02 15:45:38 +00:00
apnadkarni 327160f25e Update changes.md for TIP 716 2025-06-02 15:38:43 +00:00
jan.nijtmans 69a513d135 Merge-mark 2025-06-02 15:37:50 +00:00
jan.nijtmans 56ec7b2901 Backport: Add [[unreachable]] and [[fallthrough]] from C23 (where available) 2025-06-02 14:18:14 +00:00
apnadkarni d99e33e348 Merge core-9-0-branch: TIP 716 accepted 2025-06-02 12:42:50 +00:00
apnadkarni f145c7fbd2 TIP 716 accepted 2025-06-02 12:07:31 +00:00
dkf 9534c91a41 Upgrade [lappend] so it bytecode compiles directly with expansion of arguments 2025-06-02 11:54:46 +00:00
dkf 810f50427c Ensure we never concatenate too many values at once 2025-06-02 11:42:02 +00:00
dkf 97d5fe7c2b merge trunk 2025-06-02 11:24:58 +00:00
dkf 3f43b4f84e Use correct variable name... 2025-06-02 08:52:39 +00:00
apnadkarni 923be72f83 Cherrypick 57d619a23f - Jan's changes for unused vars 2025-06-01 18:13:01 +00:00
apnadkarni 700440e0f3 Merge core-9-0-branch 2025-06-01 15:32:38 +00:00
dkf 7d59bf0f64 Add [[unreachable]] and [[fallthrough]] from C23 (where available) 2025-06-01 10:24:33 +00:00
dkf 3f8091f15a Should set variable earlier 2025-05-31 08:13:16 +00:00
dgp 8e0716b082 [9a4876e887] Get ooWhat initialized before any error handling paths. 2025-05-30 19:35:52 +00:00
dgp 1eb17e0903 silence compiler warning 2025-05-30 19:14:02 +00:00
dgp 14c5e416e3 [fa7995bdf2] Stop crash in [http::cookiejar create]. 2025-05-30 18:55:57 +00:00
dkf 2e70d1dbe5 merge trunk 2025-05-30 14:17:53 +00:00
dkf d8ceb92fcc Minor refactor of some parts of TclOO code 2025-05-30 14:00:04 +00:00
dkf ddd949b958 Another switch that can be marked explicitly as exhaustive 2025-05-30 13:35:28 +00:00
dkf 780e40c538 Workaround for Clang being obnoxious 2025-05-30 08:28:08 +00:00
dkf c939f74973 Don't read uninitialised memory; store in TEBCdata instead 2025-05-29 20:26:35 +00:00
dkf 6e2188ef57 Go back to other way of working; actually more efficient in this case 2025-05-29 15:18:39 +00:00
dkf ebff9819e9 merge trunk 2025-05-29 15:10:40 +00:00
dkf c4d746554b put back accidentally removed code 2025-05-29 15:07:03 +00:00
dkf dfa5717634 Apple's clang-pretending-to-be-gcc is slightly fussy 2025-05-29 08:17:45 +00:00
dkf 14e9c92103 more unreachable/fallthrough marks 2025-05-29 08:13:56 +00:00
dkf 5f4f0bf1e6 More marking of paths as unreachable 2025-05-27 19:11:46 +00:00
dkf deb0e4ee28 Add a TCL_UNREACHABLE macro for marking a code path as never reached
Inspired by https://en.cppreference.com/w/c/language/attributes/deprecated
2025-05-27 11:28:24 +00:00
apnadkarni 59040bcaaa Merge 9.0. Disable unsupported icu tests for valgrind as dl_load of icu muddies valgrind output 2025-05-27 05:02:21 +00:00
apnadkarni a6a2d6ced9 Disable unsupported icu tests for valgrind as dl_load of icu muddies valgrind output 2025-05-27 05:01:08 +00:00
apnadkarni 5303e4fc8c Proposed fix for memory leak in TclCompileTryCmd 2025-05-27 03:23:54 +00:00
jan.nijtmans 010caf4f10 Add some more Tcl_Attempt* functions 2025-05-26 12:59:04 +00:00
apnadkarni beea64e0dc Merge mark for 9.0 changes.md 2025-05-26 11:59:46 +00:00
apnadkarni 5c2cca7db2 Update changes for fixed tickets 2025-05-26 11:56:49 +00:00
jan.nijtmans 5637219381 Merge 9.0 2025-05-26 11:48:29 +00:00
apnadkarni 58b76f95b2 Update changes.md 2025-05-26 11:47:06 +00:00
jan.nijtmans 7a6af69ba8 Update changes.md 2025-05-26 11:41:49 +00:00
apnadkarni 6b4720e854 New internal list representations for lreverse, lrepeat, lrange. See https://core.tcl-lang.org/tcl/wiki?name=New+abstract+list+representations 2025-05-26 11:40:37 +00:00
jan.nijtmans 72c2ffce20 Fix [1dcda0e862]: Build broken (trunk branch) tclCompExpr.c tclOOCall.c. Just by disabling the warning. 2025-05-26 11:40:28 +00:00
jan.nijtmans 352041bd83 Indenting (backported from 9.1) 2025-05-26 11:37:48 +00:00
apnadkarni 7778d0116c Merge trunk 2025-05-26 11:10:26 +00:00
apnadkarni 3ea2a44644 Merge 9.0 - Fix [7346adc50f] - memory runaway on truncated iso2022 encoding 2025-05-26 10:31:22 +00:00
apnadkarni 0ce06d0a65 Fix [7346adc50f] - memory runaway on truncated iso2022 encoding 2025-05-26 10:29:00 +00:00
jan.nijtmans efc03cf36f Use TclAttemptInitStringRep() in a few more places where it's possible. Fix indenting. 2025-05-26 10:04:29 +00:00
apnadkarni 9087f55082 Add table driven truncation at end test 2025-05-26 06:12:50 +00:00
apnadkarni c4618712a0 Handle tcl8 and replace profiles for truncated escape encodings. Add tests. 2025-05-26 05:12:10 +00:00
apnadkarni 5d722018ba Start on [7346adc50f]. Now raise error on truncated encoding. Still have to handle replace and tcl8 profiles. 2025-05-25 17:27:37 +00:00
apnadkarni 17c37ca31c Merge trunk 2025-05-25 02:59:42 +00:00
dkf 0f9b3af702 Factor out code for describing the args to a method. 2025-05-23 14:51:23 +00:00
dkf 122acc8cfc merge trunk 2025-05-23 10:59:51 +00:00
jan.nijtmans f4148ccf2d Rebase to trunk 2025-05-23 09:24:35 +00:00
dkf 852b5011b5 TIP 720: Bytecode generation improvements/sanity 2025-05-23 09:10:27 +00:00
dkf 9aadfdb56c Clean up indentation and overlong lines 2025-05-23 09:03:35 +00:00
apnadkarni 2162d59e4e Move new list implementations to 9.1 2025-05-23 06:31:09 +00:00
apnadkarni da37aa322d Merged core-9-0-branch 2025-05-23 06:08:46 +00:00
apnadkarni b335e24a13 Create new branch named "apn-tip636-appl-91" 2025-05-23 06:07:03 +00:00
apnadkarni 9a0c9856d3 Merge core-9-0-branch 2025-05-23 02:21:39 +00:00
apnadkarni 86256cad5d Fix [c776eb586d]. Read codepage from registry (reported by Jan) 2025-05-23 02:18:55 +00:00
dkf c0d43e104e Clean up the stat buffer renderer a bit 2025-05-22 19:36:32 +00:00
dkf bb617aa011 tidy up spaces 2025-05-22 14:35:42 +00:00
jan.nijtmans f3b1fa4a60 Merge 9.0 2025-05-22 12:05:05 +00:00
dkf 71b8db3a9a Improvements to TRACE macros and reduce warnings (on some platforms/configs) 2025-05-22 09:39:11 +00:00
jan.nijtmans aef01f5394 Minor optimization: Make sure that TclIsSpaceProcM() doesn't call TclIsSpaceProc() for 'negative' byte values 2025-05-22 09:25:06 +00:00
dkf cb54d306f9 MSVC doesn't like #ifdef in arguments to a macro 2025-05-22 08:11:34 +00:00
apnadkarni 70debab1ce Implement expr in/ni for repeated and reversed list types 2025-05-22 03:19:42 +00:00
dkf 71edf928c8 Use the right internal macro 2025-05-21 10:52:30 +00:00
jan.nijtmans 251a65dfe2 Rebase to latest trunk 2025-05-21 10:09:15 +00:00
dkf b2a81a3d7e merge fix 2025-05-21 08:16:58 +00:00
dkf c1ee663c10 Add back missing file. I don't know why it keeps getting nuked... 2025-05-21 08:03:20 +00:00
apnadkarni 32b0659781 Merge core-9-0-branch 2025-05-21 02:15:43 +00:00
apnadkarni 261e788b4b Update docs 2025-05-21 00:53:05 +00:00
dkf d7d393915e merge trunk (indirectly) 2025-05-20 08:43:43 +00:00
dkf d64b72d8fd fix (rare) merge error 2025-05-20 08:41:34 +00:00
jan.nijtmans 5e124df2db Rebase to trunk 2025-05-20 08:39:33 +00:00
dkf 54cca63d30 merge trunk 2025-05-20 08:39:25 +00:00
dkf a360d1ff46 Fix TEBC internal operand signedness/width; use better variable names for operands 2025-05-20 08:26:21 +00:00
dkf f0f7d04113 merge no-variable-width-instruction-issue 2025-05-20 07:58:15 +00:00
dkf af3de31400 merge trunk 2025-05-20 07:56:37 +00:00
dkf 8195694d54 A few more corrections to Tcl_BounceRefCount usage; definitely no leaks in test suite 2025-05-20 07:55:29 +00:00
apnadkarni e13b7bf325 Fix [3335120320]. Create include dir for installing extensions in non-default locations 2025-05-20 05:30:15 +00:00
apnadkarni a1e0baea6b Fix [3335120320]. Create include dir for installing extensions in non-default locations 2025-05-20 05:26:02 +00:00
dkf 16999286b6 Disable deprecation notices with MSVC; they can get them if they turn on support for C23 2025-05-19 12:01:16 +00:00
dkf 673fb318a9 Promote IsEmptyToken to TclIsEmptyToken, and use in other relevant places 2025-05-19 11:58:18 +00:00
apnadkarni 7a29841637 Some small clarification to abstract list method docs 2025-05-19 11:52:10 +00:00
jan.nijtmans 372a2a96af Update version in .project file 2025-05-19 10:28:56 +00:00
jan.nijtmans bbb91873be Update version in .project file 2025-05-19 10:27:26 +00:00
dkf 912328358c Don't generate the next clause of [for] if it's known to be empty 2025-05-19 09:04:41 +00:00
dkf 293ec0d7c9 Use the sense of space-ness from the parser, not the unicode support 2025-05-19 07:44:59 +00:00
dkf f0c7d69b86 fix errors 2025-05-18 20:26:14 +00:00
apnadkarni a2080b3378 Bug [3335120320]. Fix for case where extension is installed into a directory other than where Tcl is installed 2025-05-18 15:53:31 +00:00
apnadkarni 1b611e1bee merge core-9-0-branch 2025-05-18 06:31:01 +00:00
dkf a3059ecfb2 merge tebc-opnd-types 2025-05-17 15:10:13 +00:00
dkf ca60852f72 Can't just blithely use unsigned; need more Tcl_Size. But that works. 2025-05-16 14:18:29 +00:00
dkf 95655e1884 A bit of tweaking to reduce warnings. 2025-05-16 11:17:51 +00:00
jan.nijtmans 40a88a72aa Merge 8.6 2025-05-16 11:02:26 +00:00
jan.nijtmans 6e0db94a9d Disable filename-16.14 testcase in Github CI. Something changed in this environment, nothing changed in the code 2025-05-16 10:56:07 +00:00
dkf 2607730ae3 Fix TEBC internal operand signedness/width 2025-05-16 09:51:46 +00:00
apnadkarni 3c66bcb735 Oops, CLANG_ASSERT->assert 2025-05-15 15:56:48 +00:00
apnadkarni 1dc49da1cb Minor cleanup 2025-05-15 15:39:40 +00:00
jan.nijtmans bd0d093bad New function Tcl_AttemptGetString(). WIP 2025-05-15 15:14:11 +00:00
dkf 770dd633db Actually, standards-compliant compilers should use the standard form for deprecation 2025-05-15 15:10:38 +00:00
dkf 944bea7be8 Minor optimisation in light of TIP 717 2025-05-15 15:01:15 +00:00
dkf 9ea5c1a2b0 merge no-variable-width-instruction-issue 2025-05-15 14:55:44 +00:00
dkf 0ac7bff9c6 merge trunk 2025-05-15 14:54:46 +00:00
dkf 9ded4a5c19 Need to test _MSVC_VER to see if we're in 19.0 or later to enable [[deprecated]] 2025-05-15 13:15:09 +00:00
dkf c6d1381fb4 Drop reference counts on duplicated objects on error: DICT_PUT and DICT_REMOVE 2025-05-15 13:03:11 +00:00
jan.nijtmans e45ea65375 Something changed in the Github CI environment. Does this fix filename-16.14 testcase? 2025-05-15 11:52:55 +00:00
apnadkarni e115aca98d Add tests for memory leaks 2025-05-15 11:35:18 +00:00
apnadkarni 300e6fafe8 Use internalRep.twoPtrValue.ptr1 and initialize .ptr2 to NULL instead of using
otherValuePtr. Otherwise valgrind complains as Tcl_Representation accesses
.ptr2 which is uninitialized.
2025-05-15 05:59:26 +00:00
dkf 0e0fc46b35 remove TODO comment 2025-05-14 13:19:00 +00:00
dkf 5f9fe4c7b3 Make the [lappend] command into one that handles expansion natively 2025-05-14 12:19:40 +00:00
apnadkarni e174970572 Complete list operation tests 2025-05-14 12:15:24 +00:00
jan.nijtmans 6a0ca4e14c Merge 9.0 2025-05-14 09:19:04 +00:00
jan.nijtmans 379052de37 Merge 8.6 2025-05-14 09:18:15 +00:00
jan.nijtmans 5c7bff1cc5 Fix scan-15.1 testcase for gcc on Windows (which has a slightly different "inf" representation) 2025-05-14 09:14:37 +00:00
jan.nijtmans 338cdcc115 TIP 717: New function: Tcl_AttemptCreateHashEntry() 2025-05-14 08:09:51 +00:00
apnadkarni e4abfe81b8 Bit more progress on test suite 2025-05-13 19:07:45 +00:00
jan.nijtmans b15dc02b2a Merge trunk 2025-05-13 15:58:54 +00:00
jan.nijtmans bd0892c974 Merge 9.0 2025-05-13 15:42:58 +00:00
jan.nijtmans 9247bf55f4 Merge 8.6 2025-05-13 15:41:57 +00:00
jan.nijtmans 94d3df3717 Put (back) Tcl_CreateHashEntry() stub entry. For better upwards compatibility with TIP #717. Not used in Tcl 9.0 2025-05-13 15:41:21 +00:00
dkf fd8f8e85b0 Expand comments and tidy up a little in the [lappend] compiler 2025-05-13 10:43:02 +00:00
jan.nijtmans dd341f2f32 Fix scan-15.1 testcase, for c runtimes which limit the number of float digits. 2025-05-13 10:37:28 +00:00
dkf 7520900f79 merge trunk 2025-05-13 07:27:50 +00:00
apnadkarni 550e49b9df Add tests for more list operations and variable indices (when they have a separate code path from literals) 2025-05-12 15:50:18 +00:00
jan.nijtmans de090950d0 Remove Tcl_GetString() stub entry: it isn't used anywhere any more 2025-05-12 11:33:33 +00:00
jan.nijtmans ff74101e1b Merge 9.0 2025-05-12 08:46:23 +00:00
jan.nijtmans 196f398e9f Forget speedup of TclLog2: Negative numbers should behave as 0. 2025-05-12 08:42:13 +00:00
jan.nijtmans 2ab4e97376 _BitScanReverse64() is tested now, so remove comment. Slight speedup for TclLog2, using OR 2025-05-12 08:36:51 +00:00
dkf edf5dfe3e9 fix INST_LAPPEND_LIST semantics with zero-length lists 2025-05-12 06:46:42 +00:00
apnadkarni 7d6d88eb1c ledit and lreplace tests for new abstract lists 2025-05-10 15:12:04 +00:00
dkf ca052cf9ed Notes on expanded-lappend: requires a deep fix elsewhere, so for a future date 2025-05-10 09:26:35 +00:00
dgp 0e8128247f [fd1585e2a1] Adopt efficient internal indexing calculation utility TclMSB(). 2025-05-09 18:13:17 +00:00
dgp 2210bdaf09 [fd1585e2a1] Adopt efficient internal indexing calculation utility TclMSB(). 2025-05-09 18:10:25 +00:00
dgp f2bca09409 Shift stubs entry 2025-05-09 17:55:13 +00:00
dgp 71820613ac merge trunk 2025-05-09 17:52:45 +00:00
jan.nijtmans 07b458931d Merge 9.0 2025-05-09 14:07:22 +00:00
dkf 460ff921b5 merge trunk 2025-05-09 13:16:39 +00:00
dkf 455497137d Final set of changes 2025-05-09 12:09:57 +00:00
jan.nijtmans c3e0794dac Merge 9.0 2025-05-08 15:20:18 +00:00
jan.nijtmans 9c7449fb49 Fix [9dcdddeefe]: compiler warnings. No need to put this in changelog, since it's introduced after 9.0.1. 2025-05-08 15:19:32 +00:00
jan.nijtmans 9a6ca5c470 Merge-mark 2025-05-07 21:22:50 +00:00
jan.nijtmans df7ef174ae Merge 8.6 2025-05-07 21:15:53 +00:00
jan.nijtmans 47f3be4dd5 Only call GetACP() once. Cleanup backported from 9.0 2025-05-07 21:01:31 +00:00
dkf c07a381b03 merge trunk 2025-05-06 13:42:02 +00:00
dkf 349112862e Fix comment indentation 2025-05-06 13:41:29 +00:00
jan.nijtmans 57d6a76259 Change implementation, using 2 new stub entries 2025-05-06 09:06:53 +00:00
sbron adb1650aa3 Fix links to tickets. 2025-05-06 08:46:45 +00:00
apnadkarni bc01294a88 Merge mark for update 9.0 changes.md 2025-05-06 07:58:13 +00:00
apnadkarni 218a91458a Update changes.md for fixed lseq tickets 2025-05-06 07:54:14 +00:00
jan.nijtmans 8565b15660 Merge 9.0 2025-05-06 07:45:01 +00:00
jan.nijtmans a034b5b04e Fix [8ffd8cabd1]: "encoding system": wrong result without manifest 2025-05-06 07:42:52 +00:00
dkf 9b753ab59f Preparing to be able to disable the opcodes at some later date; we do not want to alter the opcode numbers when we do 2025-05-05 20:14:45 +00:00
dgp d8892d524c Test of [testmsb] checking upper range boundary. 2025-05-05 19:40:29 +00:00
oehhar a0ecb0cc3c [78f44214] Document Tcl_InitStringRep: copy description from TIP 445: better than nothing... 2025-05-05 16:27:48 +00:00
jan.nijtmans 9e8816331f Merge-mark 2025-05-05 15:38:09 +00:00
jan.nijtmans 8d9737dce6 Fix [b7834045b9]: MS-VC 6 on core-8-6-branch: compile error C2520: conversion from unsigned __int64 to double not implemented, use signed __int64
No need to put it in change log, because regression was caused by [4128866276b86868]
2025-05-05 15:37:13 +00:00
dkf aff1f2501e merge trunk 2025-05-05 15:34:34 +00:00
dkf 1f531e65e3 Merge tclCompUtils.h into tclCompile.h 2025-05-05 15:34:04 +00:00
oehhar a8485dc6d6 [42d14c495a] Parsing long floating point strings 2025-05-05 14:49:59 +00:00
oehhar 165eb1f3e7 Add to changes.md bug section: scan "long mantissa" %g [42d14c] 2025-05-05 14:47:52 +00:00
dkf c489ce3000 Clean up a bit 2025-05-05 14:43:47 +00:00
oehhar 39223e515f Add to changes: 2025-05-05 (bug) [42d14c] Fix scan with long mantissa. Ex.: scan "1.[string repeat 1 191]e-321" %g 2025-05-05 14:41:31 +00:00
oehhar ea6c1b6230 [42d14c495a] Parsing long floating point strings 2025-05-05 14:40:43 +00:00
oehhar 7ece2cabd3 [42d14c495a] Parsing long floating point strings 2025-05-05 14:30:52 +00:00
dgp 5a7a1ab379 Don't let tests pass out-of-range argument to TclMSB(). 2025-05-05 11:44:27 +00:00
jan.nijtmans 5bdca475f1 Merge 9.0 2025-05-05 09:53:44 +00:00
jan.nijtmans ab8975174d Proposed fix for [8ffd8cabd1]: "encoding system": wrong result without manifest
Extracted from TIP 716 implementation
2025-05-05 09:14:42 +00:00
jan.nijtmans c7d153cbbb Missing TclOOM() calls, which produce a panic when Tcl_InitStringRep() fails 2025-05-05 06:53:48 +00:00
oehhar 075a14cd43 [42d14c495a] Add source code comment and test case provided by Christian Werner (thanks) 2025-05-05 06:21:52 +00:00
dkf 3fcdad6278 Minor tinkering 2025-05-04 16:43:44 +00:00
apnadkarni dc785821c0 Use rangeList Tcl_ObjType for lassign of large lists 2025-05-04 06:51:29 +00:00
oehhar 0ec38e800a [42d14c495a] Add simple test cases 2025-05-03 13:15:15 +00:00
apnadkarni 4ddbdc2f1b Implement lrangeType Tcl_Obj 2025-05-03 12:05:05 +00:00
dgp 60aa83fdd4 merge 9.0 2025-05-02 18:31:31 +00:00
dgp 4078b3aa79 merge 8.7 2025-05-02 18:30:34 +00:00
dgp 47dd25a0aa Use Tcl_InitStringRep() as intended. 2025-05-02 18:29:24 +00:00
dgp bb33ee662c merge 9.0 2025-05-02 17:58:26 +00:00
dgp dd843d4484 merge fix 2025-05-02 17:58:06 +00:00
dgp 51df805a81 Rework overflow test so it happens in a valid range. 2025-05-02 17:57:36 +00:00
dgp a65023af76 typo 2025-05-02 17:00:11 +00:00
dgp 6e4e90b77a typo 2025-05-02 16:57:37 +00:00
dkf ef3d4161e5 Update comment: INST_RETURN_CODE_BRANCH isn't needed in asm any more 2025-05-02 16:06:36 +00:00
dkf c6a7fdc9d4 merge trunk 2025-05-02 16:03:34 +00:00
dkf e33638fe9d Combine the new jumptable into this branch 2025-05-02 15:54:41 +00:00
oehhar 23dca0cd0d [78f44214] Document Tcl_InitStringRep: copy description from TIP 445: better than nothing... 2025-05-02 12:31:29 +00:00
dkf c815194539 Add INST_IS_EMPTY, a surfacing of Tcl_IsEmpty() to bytecode 2025-05-02 08:21:35 +00:00
jan.nijtmans 3929f9e90e Deprecate (internal) TclVarHashCreateVar() function. It isn't (and shouldn't) be used by any extension. 2025-05-02 08:00:32 +00:00
jan.nijtmans e507bdc0e4 Rebase to trunk 2025-05-01 09:19:48 +00:00
apnadkarni eb94916257 Add framework for testing nested lists in different list type combinations 2025-05-01 05:50:08 +00:00
jan.nijtmans 19d1fdff7c Merge 9.0 (indenting) 2025-04-29 13:49:26 +00:00
jan.nijtmans ac3567a097 Indenting and comments, backported from 9.1 2025-04-29 13:48:09 +00:00
dkf 93069ee44f Convert [try ... on ... finally ...] to use a jump table 2025-04-29 09:20:14 +00:00
jan.nijtmans e9fe9e755c Unbreak (gcc) build 2025-04-29 08:51:25 +00:00
dkf 2146c122aa Use a jump table for [try] without 'trap' or 'finally' 2025-04-28 21:22:02 +00:00
apnadkarni 67681ec324 Fix cmdAH tests. See comments below.
Tcl_GetEncodingForUser will not be available until 9.1 for stubs compatibility.
In any case, as a rule, wide char API's should be used in code and tests to avoid the exact kind
of problems we are currently trying to solve with code pages.
2025-04-28 11:30:02 +00:00
apnadkarni febd18f728 Pick up lindex fixes from 9.0 2025-04-28 10:16:32 +00:00
apnadkarni 745e9ef82f Start on test suite for all internal list representations 2025-04-28 10:15:07 +00:00
apnadkarni 4fa72e4d11 Minor tweak. Pass interp as NULL as error thrown away. 2025-04-28 10:03:39 +00:00
apnadkarni a905678adc Minor tweak. Pass interp as NULL as error thrown away. 2025-04-28 09:51:38 +00:00
apnadkarni 88670a2902 Fix [7d3101bf28] and [452b103a74] - lseq indexing crashes. 2025-04-28 09:20:38 +00:00
dkf fa450103b8 Preparing to use a numeric jump table in [try]... but that's tricky to get right so it'll be in a later commit. 2025-04-28 09:03:29 +00:00
apnadkarni 96b3e6bc09 Fix [7d3101bf28] and [452b103a74] - lseq indexing crashes. 2025-04-28 09:01:15 +00:00
jan.nijtmans 8e247cc6a3 Attempt to fix cmdAH test failures. Doesn't work. 2025-04-28 07:37:06 +00:00
apnadkarni 6625300b0d Fix compiled indexlist for lseq 2025-04-28 03:05:52 +00:00
apnadkarni 7e6ae2d3b4 Partial fix and test cases for bug [452b103a74] - lseq nested indices 2025-04-27 14:59:58 +00:00
apnadkarni 1bd82c3ea9 Fix [7d3101bf28] - crash on out of bounds lindex into lseq 2025-04-27 10:48:52 +00:00
apnadkarni 81f7db2d51 Fix lindex crash on non-numeric index into lseq 2025-04-27 10:42:36 +00:00
apnadkarni 1fd30794f5 Crash tests for bugs [45b2] and [7d31] 2025-04-27 10:29:26 +00:00
dkf 03d79b534e Convert [subst] to use a numeric jump table instead of magic offset computations 2025-04-26 15:52:49 +00:00
dkf baee7785fd Whether a value is new to a jump table matters. 2025-04-26 15:08:29 +00:00
dkf 693f52fa84 merge no-variable-width-instruction-issue 2025-04-26 13:36:28 +00:00
dkf 369748c404 Fix cut-n-paste-ism 2025-04-25 15:08:09 +00:00
dkf 3bb36458a1 Add INST_DICT_REMOVE to go with INST_DICT_PUT 2025-04-25 14:37:55 +00:00
dkf fb90452743 More towards the new jump table opcode 2025-04-25 13:52:40 +00:00
jan.nijtmans d3734ecb52 Unneeded "#undef" 2025-04-24 10:09:34 +00:00
jan.nijtmans 03eff5665c Unneeded (char *) typecast 2025-04-24 10:06:25 +00:00
dgp 7393667c57 High performance implementation using GNU compiler builtin. 2025-04-23 18:27:05 +00:00
dgp a6bfdceed2 Speculative high performance implementation using Microsoft compiler intrinsics.
UNTESTED!!!
2025-04-23 17:39:50 +00:00
dkf 6bdfb292f2 Starting to develop a new jump table type for numeric keys 2025-04-23 08:50:08 +00:00
dgp cd11dabef8 Apply Tcl 9 guarantees and conventions. 2025-04-22 17:26:41 +00:00
dgp 18b33c63ad Port the Brodnik adaptation implementaton of TclMSB() from dgp-refactor branch 2025-04-22 17:12:23 +00:00
dgp ee58b4b226 Update testing to Tcl 9 guarantees and conventions. 2025-04-22 17:00:18 +00:00
dgp a54a0757a8 Bring over testing command and tests for TclMSB() from dgp-refactor branch. 2025-04-22 16:50:34 +00:00
dgp 5ea2ee0bfb Restore TclLog2() status to be available only for --enable-symbols=compile 2025-04-22 16:30:58 +00:00
dkf ce3e961fed Make [switch -exact -nocase] compiled 2025-04-22 15:16:56 +00:00
dkf 443637dcd2 Better comments 2025-04-22 14:59:18 +00:00
dkf cf0978ad98 Generate correct arguments to INST_TAILCALL so we don't need to patch them in TEBC 2025-04-21 16:52:17 +00:00
dkf 8058b22442 Factor out some clock-related constants into their own enum 2025-04-21 15:37:21 +00:00
dkf 0a074deaa3 remove junk whitespace 2025-04-21 08:30:11 +00:00
apnadkarni 74bb80deb6 Use abstract lists only above a element count threshold 2025-04-21 04:08:54 +00:00
dkf 0f506c60ed merge trunk 2025-04-20 19:58:16 +00:00
dkf a6be688d45 merge trunk 2025-04-20 19:57:04 +00:00
jan.nijtmans d5e9e1ba68 Merge trunk 2025-04-20 17:07:27 +00:00
jan.nijtmans 4c439372a6 Merge 9.0 2025-04-20 17:03:36 +00:00
jan.nijtmans 07df807261 VarHashCreateVar() isn't used in tclExecute.c 2025-04-20 16:58:24 +00:00
jan.nijtmans eba3a79748 Rebase to trunk 2025-04-20 16:19:32 +00:00
dkf eddf277649 Fix the weirdest bug in the assembler with getting line numbers wrong... sometimes. I'm not even sure that the right thing was being done before... 2025-04-20 15:14:21 +00:00
jan.nijtmans 7e01424293 3th round of (harmless) -Wconversion fixes. Contains better fix for previous commit (thanks, dkf!) 2025-04-20 15:03:12 +00:00
dkf 9a2719509c Fix type.
In at least one compiler, having the line number as int just blew up the build. It's an internal type too; no compat concerns with having it be Tcl_Size.
2025-04-20 12:01:05 +00:00
apnadkarni 4366d35d49 Add abstract list type for lrepeat 2025-04-20 07:49:51 +00:00
apnadkarni 6b33a12391 Add an abstract list type for reversing lists 2025-04-19 11:41:18 +00:00
jan.nijtmans f2e4744fc4 Merge 9.0 2025-04-18 14:04:28 +00:00
dgp 2367b2f504 Re-implement TclLog2() in terms of TclMSB with range limiting wrapped
around the core function.

NOTE: TclLog2() was implemented incorrectly.  As written it was never
going to return values 23 through 30.  It would falsely pin them up to 31.
This bug is still present on the trunk, so will need fixing if this
branch is not approved to merge.
2025-04-17 17:44:54 +00:00
dgp 9d702a3135 The callers of TclLog2() needed its range to be limited to [0..31].
RequiredPrecision needs support for the full long long range.  Create a 
new utility routine TclMSB() to provide the functionality without truncated
range.  Use it.  Put it internal stubs anticipating testing.
2025-04-17 17:30:26 +00:00
dgp 3fcc1a8bb2 Remove code that purports to handle the circumstance when
sizeof(Tcl_WideUInt) > sizeof(long long)

It is believed this is never true in Tcl 9.
2025-04-17 16:41:41 +00:00
dgp 56c39ebf06 Fix up the handling of zero input to RequiredPrecision 2025-04-17 16:30:12 +00:00
dkf 93c9217da1 remove unread field 2025-04-17 09:09:14 +00:00
dkf 03a7150261 Add INST_TCLOO_ID/tclooId to TAL 2025-04-17 09:07:25 +00:00
dgp 74dd7b71b7 The routine RequiredPrecision() is just a variation on the same function
provided by TclLog2().  Re-implement as a simple wrapper.
2025-04-16 19:26:34 +00:00
dgp 2cf3949e32 Expose TclLog2() to all builds, not limited to --enable-symbols=compile 2025-04-16 18:54:05 +00:00
dgp 54b083e10a Work in progress deploying further optimization and usage of TclLog2(). 2025-04-16 18:04:19 +00:00
dgp b1b52b0143 Correct false claims in the header comment of RequiredPrecision() 2025-04-16 17:34:13 +00:00
dkf 82d26bceb4 Clean up some code sections affected by change to always using 4-byte jumps 2025-04-16 12:37:25 +00:00
jan.nijtmans 0841fa9252 Rebase to trunk 2025-04-16 11:25:40 +00:00
jan.nijtmans 7a7d102788 Missing TCL_NO_DEPRECATED 2025-04-15 09:10:23 +00:00
dkf 90f7b103f2 Give [dict merge] its own compiler using INST_DICT_PUT; enables better [try] and [dict create] compiling too 2025-04-14 19:28:58 +00:00
apnadkarni 2c5e45746f Fix Unix build. Add basic tests 2025-04-14 16:15:05 +00:00
dkf b3f2fec373 Add [info object creationid] to fully compiled operations; simplify some instruction descriptors 2025-04-14 13:29:57 +00:00
jan.nijtmans 4472e53a91 Put back comment, accidently removed 2025-04-14 11:58:21 +00:00
jan.nijtmans 40ca720fc0 Finish documentation too 2025-04-14 11:23:49 +00:00
dkf 31ca9f0983 merge trunk 2025-04-14 10:46:38 +00:00
dkf aaf74cba98 Minor improvement to [try/finally] instruction sequence 2025-04-14 09:11:09 +00:00
jan.nijtmans 2b0fe4a3ef Implement Tcl_AttemptCreateHashEntry() 2025-04-13 22:16:52 +00:00
jan.nijtmans d46e9784ab Fully functional now, with a lot of examples for the improvement. Also, merge trunk 2025-04-13 21:37:52 +00:00
dkf 66da10b424 merge trunk 2025-04-13 20:58:34 +00:00
dkf ab6d0556fe Macros for comparing tokens to literals, making compiler logically easier to read 2025-04-13 20:46:43 +00:00
apnadkarni 6beacbba8a Added -encoding option to exec 2025-04-12 16:57:22 +00:00
apnadkarni ad696be16d Added encoding user command 2025-04-12 15:11:18 +00:00
apnadkarni 8e89253fad Start on TIP 716 implementation 2025-04-12 12:03:19 +00:00
jan.nijtmans 8b2d288738 fix for BogusCreate() 2025-04-12 08:41:42 +00:00
jan.nijtmans 020cd464d7 Attempt to change special value to (int *)-1. Doesn't work yet. 2025-04-12 08:24:28 +00:00
jan.nijtmans f3965a147d Fix [236d18f49b]: More efficient Tcl_FindHashEntry() 2025-04-11 10:36:16 +00:00
dkf 93c27b3700 Some definite cleanup of the [switch] issuer, with neater passing of information around 2025-04-10 21:22:41 +00:00
dkf be8b424ef4 Cleaning up a bunch of things in code generation. 2025-04-09 14:18:06 +00:00
jan.nijtmans aeecd32b9b Proposed fix for [42d14c495a]: Parsing long floating point strings (thanks, Christian) 2025-04-02 21:18:41 +00:00
dkf 0706496a46 More corrections 2025-03-30 17:11:03 +00:00
dkf afdadec486 Forgot a critical file. Derp! 2025-03-30 16:45:57 +00:00
dkf c6322dc7d5 Reset after failure a bit more carefully. 2025-03-30 16:30:26 +00:00
dkf eab48b4a77 more consistency of error messages 2025-03-29 15:22:50 +00:00
dkf 9e753e6ef6 merge trunk 2025-03-29 15:12:33 +00:00
dkf 0f6cd492bf Fix [while] compilation, remove a couple of useless tests (opcode changes) 2025-03-29 15:04:21 +00:00
dkf 02e0539f3c Must reset exception ranges on syntax error in assembled code 2025-03-29 11:57:25 +00:00
dkf c80c627dd0 Most tests working, but not yet all. 2025-03-29 09:23:17 +00:00
dkf c21651adee Many changes to basic opcode issuing to eliminate most 1-byte args. Not yet fully working... 2025-03-28 15:25:12 +00:00
dkf 6d80c9d7b2 Switch over to using 4-byte args; mark some ops as deprecated (gcc/clang) 2025-03-18 12:17:50 +00:00
dkf b2b4b1a7d6 This is an experiment with eliminating the issuing of variable-width instructions
Much complexity in the compiler and bytecode engine comes from handling both instructions with width-1 arguments and width-4 arguments. Just issuing the width-4 versions should simplify things quite a bit, at a cost of making the bytecode less dense. This experiment is to look at the consequences of that.
2025-03-09 15:16:24 +00:00
sebres 1ad46af73b simplify detection of combination for positive and negative options 2025-02-10 10:24:31 +00:00
sebres 6b8af07217 merge trunk (optimized TclSubstOptions, etc); reorganizes options (almost alphanumeric, positive group first); optimizes TclSubstOptions - reducing the branch misprediction, etc 2025-02-08 16:10:46 +00:00
max 7826ad63b8 subst: Fix segfault when mixing positive and negative options and add a test case for it. 2025-02-04 18:06:37 +00:00
max 2fcdb49939 subst.test: Rearrange the new tests for positve options to subst into a single block. 2025-02-04 12:38:32 +00:00
max 50891f3a2d TclSubstOptions: Optimize the positive/negative detection logic (thanks, Rolf). Other minor refinements. 2025-02-04 12:29:44 +00:00
max 6dd788dfc6 Initial reference implementation of TIP 712 (Add "positive" options to the subst command) with code, documentation and tests. 2025-01-31 14:47:13 +00:00
246 changed files with 69885 additions and 12678 deletions
+7
View File
@@ -0,0 +1,7 @@
puts exe:\t[info nameofexecutable]
puts ver:\t[info patchlevel]
catch {
puts build:\t[tcl::build-info]
}
puts lib:\t[info library]
puts plat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]
+39 -15
View File
@@ -5,32 +5,54 @@ on:
- "main"
- "core-9-0-branch"
tags:
- "core-**"
- "core-*"
permissions:
contents: read
jobs:
plan:
runs-on: ubuntu-latest
outputs:
gcc: ${{ steps.matrix.outputs.gcc }}
steps:
- name: Select build matrix based on branch name
id: matrix
run: |
(
echo gcc=$(jq -nc '{config: (if env.IsMatched == "true" then env.FULL else env.PARTIAL end) | fromjson }' )
) | tee -a $GITHUB_OUTPUT
env:
IsMatched: ${{ github.ref_name == 'main' || github.ref_name == 'core-9-0-branch' }}
# DO NOT CHANGE THESE MATRIX SPECS; IT AFFECTS OUR COST CONTROLS
FULL: >
[
"",
"CFLAGS=-DTCL_NO_DEPRECATED=1",
"--disable-shared",
"--disable-zipfs",
"--enable-symbols",
"--enable-symbols=mem",
"--enable-symbols=all",
"CFLAGS=-ftrapv",
"CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit"
]
PARTIAL: >
[
"",
"--enable-symbols=all",
"CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit"
]
gcc:
needs: plan
runs-on: ubuntu-24.04
strategy:
matrix:
config:
- ""
- "CFLAGS=-DTCL_NO_DEPRECATED=1"
- "--disable-shared"
- "--disable-zipfs"
- "--enable-symbols"
- "--enable-symbols=mem"
- "--enable-symbols=all"
- "CFLAGS=-ftrapv"
# Duplicated below
- "CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit"
matrix: ${{ fromJson(needs.plan.outputs.gcc) }}
defaults:
run:
shell: bash
working-directory: unix
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
timeout-minutes: 5
- name: Install 32-bit dependencies if needed
# Duplicated from above
@@ -60,7 +82,7 @@ jobs:
- name: Info
run: |
ulimit -a || echo 'get limit failed'
echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
make runtest SCRIPT=../.github/workflows/info.tcl || echo 'get info failed'
- name: Run Tests
run: |
make test
@@ -72,10 +94,12 @@ jobs:
make install
timeout-minutes: 5
- name: Create Distribution Package
if: ${{ matrix.config == '' }}
run: |
make dist
timeout-minutes: 5
- name: Convert Documentation to HTML
if: ${{ matrix.config == '' }}
run: |
make html-tcl
timeout-minutes: 5
+34 -12
View File
@@ -5,10 +5,38 @@ on:
- "main"
- "core-9-0-branch"
tags:
- "core-**"
- "core-*"
permissions:
contents: read
jobs:
plan:
runs-on: ubuntu-latest
outputs:
clang: ${{ steps.matrix.outputs.clang }}
steps:
- name: Select build matrix based on branch name
id: matrix
run: |
(
echo clang=$(jq -nc '{config: (if env.IsMatched == "true" then env.FULL else env.PARTIAL end) | fromjson }' )
) | tee -a $GITHUB_OUTPUT
env:
IsMatched: ${{ github.ref_name == 'main' || github.ref_name == 'core-9-0-branch' }}
# DO NOT CHANGE THIS MATRIX SPEC; IT AFFECTS OUR COST CONTROLS
FULL: >
[
"",
"--disable-shared",
"--disable-zipfs",
"--enable-symbols",
"--enable-symbols=mem",
"--enable-symbols=all"
]
PARTIAL: >
[
"",
"--enable-symbols=all"
]
xcode:
runs-on: macos-15
defaults:
@@ -17,7 +45,7 @@ jobs:
working-directory: macosx
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
timeout-minutes: 5
- name: Prepare
run: |
@@ -36,22 +64,16 @@ jobs:
timeout-minutes: 15
clang:
runs-on: macos-15
needs: plan
strategy:
matrix:
config:
- ""
- "--disable-shared"
- "--disable-zipfs"
- "--enable-symbols"
- "--enable-symbols=mem"
- "--enable-symbols=all"
matrix: ${{ fromJson(needs.plan.outputs.clang) }}
defaults:
run:
shell: bash
working-directory: unix
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
timeout-minutes: 5
- name: Prepare
run: |
@@ -74,7 +96,7 @@ jobs:
- name: Info
run: |
ulimit -a || echo 'get limit failed'
echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
make runtest SCRIPT=../.github/workflows/info.tcl || echo 'get info failed'
- name: Run Tests
run: |
make test
+7 -7
View File
@@ -5,7 +5,7 @@ on:
- "main"
- "core-9-0-branch"
tags:
- "core-**"
- "core-*"
permissions:
contents: read
jobs:
@@ -18,7 +18,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Prepare
run: |
touch generic/tclStubInit.c generic/tclOOStubInit.c
@@ -61,9 +61,9 @@ jobs:
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Checkout create-dmg
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
repository: create-dmg/create-dmg
ref: v1.0.8
@@ -139,7 +139,7 @@ jobs:
msystem: UCRT64
install: git mingw-w64-ucrt-x86_64-toolchain make zip
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Prepare
run: |
touch generic/tclStubInit.c generic/tclOOStubInit.c
@@ -194,7 +194,7 @@ jobs:
run: |
mkdir data
- name: Get Linux build
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
path: data
# Can't download by artifact ID; stupid missing feature!
@@ -205,7 +205,7 @@ jobs:
working-directory: data
- name: Transfer built files
# https://github.com/marketplace/actions/rsync-deployments-action
uses: burnett01/rsync-deployments@7.0.2
uses: burnett01/rsync-deployments@7.1.0
id: rsync
if: false # Disabled... for now
with:
+58 -24
View File
@@ -5,31 +5,69 @@ on:
- "main"
- "core-9-0-branch"
tags:
- "core-**"
- "core-*"
permissions:
contents: read
env:
ERROR_ON_FAILURES: 1
jobs:
plan:
runs-on: ubuntu-latest
outputs:
msvc: ${{ steps.matrix.outputs.msvc }}
gcc: ${{ steps.matrix.outputs.gcc }}
steps:
- name: Select build matrix based on branch name
id: matrix
run: |
(
echo msvc=$(jq -nc '{config: (if env.IsMatched == "true" then env.MSVC_FULL else env.MSVC_PARTIAL end) | fromjson }' )
echo gcc=$(jq -nc '{config: (if env.IsMatched == "true" then env.GCC_FULL else env.GCC_PARTIAL end) | fromjson }' )
) | tee -a $GITHUB_OUTPUT
env:
IsMatched: ${{ github.ref_name == 'main' || github.ref_name == 'core-9-0-branch' }}
# DO NOT CHANGE THESE MATRIX SPECS; IT AFFECTS OUR COST CONTROLS
MSVC_FULL: >
[
"",
"CHECKS=nodep",
"OPTS=static",
"OPTS=noembed",
"OPTS=symbols",
"OPTS=symbols STATS=compdbg,memdbg"
]
MSVC_PARTIAL: >
[
"",
"OPTS=symbols STATS=compdbg,memdbg"
]
GCC_FULL: >
[
"",
"CFLAGS=-DTCL_NO_DEPRECATED=1",
"--disable-shared",
"--disable-zipfs",
"--enable-symbols",
"--enable-symbols=mem",
"--enable-symbols=all"
]
GCC_PARTIAL: >
[
"",
"--disable-shared",
"--enable-symbols=all"
]
msvc:
runs-on: windows-2025
needs: plan
defaults:
run:
shell: powershell
working-directory: win
strategy:
matrix:
config:
- ""
- "CHECKS=nodep"
- "OPTS=static"
- "OPTS=noembed"
- "OPTS=symbols"
- "OPTS=symbols STATS=compdbg,memdbg"
matrix: ${{ fromJson(needs.plan.outputs.msvc) }}
# Using powershell means we need to explicitly stop on failure
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
timeout-minutes: 5
- name: Init MSVC
uses: ilammy/msvc-dev-cmd@v1
@@ -55,23 +93,17 @@ jobs:
throw "nmake exit code: $lastexitcode"
}
timeout-minutes: 30
env:
ERROR_ON_FAILURES: 1
gcc:
runs-on: windows-2025
needs: plan
defaults:
run:
shell: msys2 {0}
working-directory: win
strategy:
matrix:
config:
- ""
- "CFLAGS=-DTCL_NO_DEPRECATED=1"
- "--disable-shared"
- "--disable-zipfs"
- "--enable-symbols"
- "--enable-symbols=mem"
- "--enable-symbols=all"
# Using powershell means we need to explicitly stop on failure
matrix: ${{ fromJson(needs.plan.outputs.gcc) }}
steps:
- name: Install MSYS2
uses: msys2/setup-msys2@v2
@@ -80,7 +112,7 @@ jobs:
install: git mingw-w64-x86_64-toolchain make
timeout-minutes: 10
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
timeout-minutes: 5
- name: Prepare
run: |
@@ -102,10 +134,12 @@ jobs:
- name: Info
run: |
ulimit -a || echo 'get limit failed'
echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
make runtest SCRIPT=../.github/workflows/info.tcl || echo 'get info failed'
- name: Run Tests
run: make test
timeout-minutes: 30
env:
ERROR_ON_FAILURES: 1
# If you add builds with Wine, be sure to define the environment variable
# CI_USING_WINE when running them so that broken tests know not to run.
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>tcl9</name>
<name>tcl9.1</name>
<comment></comment>
<projects>
</projects>
+2 -2
View File
@@ -1,6 +1,6 @@
# README: Tcl
This is the **Tcl 9.1a0** source distribution.
This is the **Tcl 9.1a1** source distribution.
You can get any source release of Tcl from [our distribution
site](https://sourceforge.net/projects/tcl/files/Tcl/).
@@ -31,7 +31,7 @@ site](https://sourceforge.net/projects/tcl/files/Tcl/).
Tcl provides a powerful platform for creating integration applications that
tie together diverse applications, protocols, devices, and frameworks.
When paired with the Tk toolkit, Tcl provides the fastest and most powerful
way to create GUI applications that run on PCs, Unix, and Mac OS X.
way to create GUI applications that run on PCs, Unix, and macOS.
Tcl can also be used for a variety of web-related tasks and for creating
powerful command languages for applications.
+19 -1
View File
@@ -4,12 +4,30 @@ changes to the Tcl source code at
> [Tcl Source Code](https://core.tcl-lang.org/tcl/timeline)
Release Tcl 9.1a0 arises from the check-in with tag `core-9-1-a0`.
Release Tcl 9.1a1 arises from the check-in with tag `core-9-1-a1`.
Highlighted differences between Tcl 9.1 and Tcl 9.0 are summarized below,
with focus on changes important to programmers using the Tcl library and
writing Tcl scripts.
# New commands and options
- [New options -backslashes, -commands and -variables for subst command](https://core.tcl-lang.org/tips/doc/trunk/tip/712.md)
- [New command unicode for Unicode normalization](https://core.tcl-lang.org/tips/doc/trunk/tip/726.md)
# New public C API
- [Tcl\_IsEmpty checks if the string representation of a value would be the empty string](https://core.tcl-lang.org/tips/doc/trunk/tip/711.md)
- [Tcl\_GetEncodingNameForUser returns name of encoding from user settings](https://core.tcl-lang.org/tips/doc/trunk/tip/716.md)
- [Tcl\_AttemptCreateHashEntry - version of Tcl\_CreateHashEntry that returns NULL instead of panic'ing on memory allocation errors](https://core.tcl-lang.org/tips/doc/trunk/tip/717.md)
- [Tcl\_ListObjRange, Tcl\_ListObjRepeat, Tcl\_TclListObjReverse - C API for new list operations](https://core.tcl-lang.org/tips/doc/trunk/tip/649.md)
- [Tcl\_UtfToNormalized, Tcl\_UtfToNormalizedDString - C API for Unicode normalization](https://core.tcl-lang.org/tips/doc/trunk/tip/726.md)
# Performance
- [Memory efficient internal representations](https://core.tcl-lang.org/tcl/wiki?name=New+abstract+list+representations)
for list operations on large lists.
# Bug fixes
- [tclEpollNotfy PlatformEventsControl panics if websocket disconnected](https://core.tcl-lang.org/tcl/tktview/010d8f38)
+1 -1
View File
@@ -47,7 +47,7 @@ Interpreter to use for error reporting.
Points to space where the number of bytes in the array may be written.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
NULL for byte arrays larger than INT_MAX (which should
trigger proper error-handling), otherwise expect it to crash.
.BE
+1 -1
View File
@@ -87,7 +87,7 @@ for an alias.
Pointer to location to store count of additional value arguments to be
passed to the alias. The location is in storage owned by the caller.
If it points to a variable which type is not \fBTcl_Size\fR, a compiler
warning will be generated. If your extensions is compiled with -DTCL_8_API,
warning will be generated. If your extensions is compiled with \fB-DTCL_8_API\fR,
this function will return TCL_ERROR for aliases with more than INT_MAX
value arguments, otherwise expect it to crash
.AP Tcl_Obj ***objvPtr out
+1 -1
View File
@@ -74,7 +74,7 @@ Points to a variable that will have the number of key/value pairs
contained within the dictionary placed within it.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
NULL for dictionaries larger than INT_MAX (which should
trigger proper error-handling), otherwise expect it to crash.
.AP Tcl_DictSearch *searchPtr in/out
+20 -7
View File
@@ -8,7 +8,7 @@
.so man.macros
.BS
.SH NAME
Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtfDStringEx, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternalDStringEx, Tcl_UtfToExternal, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath \- procedures for creating and using encodings
Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtfDStringEx, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternalDStringEx, Tcl_UtfToExternal, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNameForUser, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath \- procedures for creating and using encodings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -53,6 +53,9 @@ int
const char *
\fBTcl_GetEncodingNameFromEnvironment\fR(\fIbufPtr\fR)
.sp
const char *
\fBTcl_GetEncodingNameForUser\fR(\fIbufPtr\fR)
.sp
\fBTcl_GetEncodingNames\fR(\fIinterp\fR)
.sp
Tcl_Encoding
@@ -308,12 +311,22 @@ procedure increments the reference count of the new system encoding,
decrements the reference count of the old system encoding, and returns
\fBTCL_OK\fR.
.PP
\fBTcl_GetEncodingNameFromEnvironment\fR provides a means for the Tcl
library to report the encoding name it believes to be the correct one
to use as the system encoding, based on system calls and examination of
the environment suitable for the platform. It accepts \fIbufPtr\fR,
a pointer to an uninitialized or freed \fBTcl_DString\fR and writes
the encoding name to it. The \fBTcl_DStringValue\fR is returned.
\fBTcl_GetEncodingNameFromEnvironment\fR retrieves the encoding name to
use as the system encoding. On non-Windows platforms, this is derived
from the \fBnl_langinfo\fR system call if available, and environment
variables \fBLC_ALL\fR, \fBLC_CTYPE\fR or \fBLANG\fR otherwise. On
Windows versions Windows 10 Build 18362 and later the returned value is
always \fButf-8\fR. On earlier Windows versions, it is derived from the
user settings in the Windows registry. \fBTcl_GetEncodingNameForUser\fR
retrieves the encoding name based on the user settings for the current
user and is derived in the same manner as
\fBTcl_GetEncodingNameFromEnvironment\fR on non-Windows platforms. On
Windows, unlike \fBTcl_GetEncodingNameFromEnvironment\fR, it returns the
encoding name as per the Windows registry settings irrespective of the
Windows version. Both functions accept \fIbufPtr\fR, a pointer to an
uninitialized or freed \fBTcl_DString\fR and write the encoding name to
it. They return \fBTcl_DStringValue(bufPtr)\fR which points to the stored
name.
.PP
\fBTcl_GetEncodingNames\fR sets the \fIinterp\fR result to a list
consisting of the names of all the encodings that are currently defined
+1 -1
View File
@@ -278,7 +278,7 @@ permissions will be set on the created file.
Filled with the number of elements in the split path.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
NULL for paths having more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP Tcl_Obj *basePtr in
+10 -1
View File
@@ -9,7 +9,7 @@
.so man.macros
.BS
.SH NAME
Tcl_InitHashTable, Tcl_InitCustomHashTable, Tcl_InitObjHashTable, Tcl_DeleteHashTable, Tcl_CreateHashEntry, Tcl_DeleteHashEntry, Tcl_FindHashEntry, Tcl_GetHashValue, Tcl_SetHashValue, Tcl_GetHashKey, Tcl_FirstHashEntry, Tcl_NextHashEntry, Tcl_HashStats \- procedures to manage hash tables
Tcl_InitHashTable, Tcl_InitCustomHashTable, Tcl_InitObjHashTable, Tcl_DeleteHashTable, Tcl_CreateHashEntry, Tcl_AttemptCreateHashEntry, Tcl_DeleteHashEntry, Tcl_FindHashEntry, Tcl_GetHashValue, Tcl_SetHashValue, Tcl_GetHashKey, Tcl_FirstHashEntry, Tcl_NextHashEntry, Tcl_HashStats \- procedures to manage hash tables
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -25,6 +25,9 @@ Tcl_InitHashTable, Tcl_InitCustomHashTable, Tcl_InitObjHashTable, Tcl_DeleteHash
Tcl_HashEntry *
\fBTcl_CreateHashEntry\fR(\fItablePtr, key, newPtr\fR)
.sp
Tcl_HashEntry *
\fBTcl_AttemptCreateHashEntry\fR(\fItablePtr, key, newPtr\fR)
.sp
\fBTcl_DeleteHashEntry\fR(\fIentryPtr\fR)
.sp
Tcl_HashEntry *
@@ -170,10 +173,16 @@ If an entry already existed with the given key then \fI*newPtr\fR
is set to zero.
If a new entry was created, then \fI*newPtr\fR is set to a non-zero
value and the value of the new entry will be set to zero.
\fI*newPtr\fR is allowed to be NULL.
The return value from \fBTcl_CreateHashEntry\fR is a pointer to
the entry, which may be used to retrieve and modify the entry's
value or to delete the entry from the table.
.PP
\fBTcl_AttemptCreateHashEntry\fR does the same as
\fBTcl_CreateHashEntry\fR, except in case of a memory
overflow. \fBTcl_AttemptCreateHashEntry\fR returns NULL
in that case while \fBTcl_CreateHashEntry\fR panics.
.PP
\fBTcl_DeleteHashEntry\fR will remove an existing entry from a
table.
The memory associated with the entry itself will be freed, but
+83 -33
View File
@@ -4,11 +4,11 @@
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_ListObj 3 8.0 Tcl "Tcl Library Procedures"
.TH Tcl_ListObj 3 9.1 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_ListObjAppendList, Tcl_ListObjAppendElement, Tcl_NewListObj, Tcl_SetListObj, Tcl_ListObjGetElements, Tcl_ListObjLength, Tcl_ListObjIndex, Tcl_ListObjReplace \- manipulate Tcl values as lists
Tcl_ListObjAppendList, Tcl_ListObjAppendElement, Tcl_NewListObj, Tcl_SetListObj, Tcl_ListObjGetElements, Tcl_ListObjLength, Tcl_ListObjIndex, Tcl_ListObjReplace, Tcl_ListObjRange, Tcl_ListObjRepeat, Tcl_ListObjReverse \- manipulate Tcl values as lists
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -35,6 +35,15 @@ int
.sp
int
\fBTcl_ListObjReplace\fR(\fIinterp, listPtr, first, count, objc, objv\fR)
.sp
int
\fBTcl_ListObjRange\fR(\fIinterp, listPtr, first, last, objPtrPtr\fR)
.sp
int
\fBTcl_ListObjRepeat\fR(\fIinterp, count, objc, objv, objPtrPtr\fR)
.sp
int
\fBTcl_ListObjReverse\fR(\fIinterp, listPtr, objPtrPtr\fR)
.fi
.SH ARGUMENTS
.AS "Tcl_Obj *const" *elemListPtr in/out
@@ -43,9 +52,12 @@ If an error occurs while converting a value to be a list value,
an error message is left in the interpreter's result value
unless \fIinterp\fR is NULL.
.AP Tcl_Obj *listPtr in/out
Points to the list value to be manipulated.
Points to the input list value.
If \fIlistPtr\fR does not already point to a list value,
an attempt will be made to convert it to one.
Some functions may store a reference to it internally so
care must be taken when managing its reference count.
See the \fBREFERENCE COUNT MANAGEMENT\fR section below.
.AP Tcl_Obj *elemListPtr in/out
For \fBTcl_ListObjAppendList\fR, this points to a list value
containing elements to be appended onto \fIlistPtr\fR.
@@ -65,29 +77,22 @@ Points to location where \fBTcl_ListObjGetElements\fR
stores the number of element values in \fIlistPtr\fR.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
If your extensions is compiled with \fB\-DTCL_8_API\fR, this function will return
NULL for lists with more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP Tcl_Obj ***objvPtr out
A location where \fBTcl_ListObjGetElements\fR stores a pointer to an array
of pointers to the element values of \fIlistPtr\fR.
.AP Tcl_Size objc in
The number of Tcl values that \fBTcl_NewListObj\fR
will insert into a new list value,
and \fBTcl_ListObjReplace\fR will insert into \fIlistPtr\fR.
For \fBTcl_SetListObj\fR,
the number of Tcl values to insert into \fIobjPtr\fR.
The number of Tcl values in the \fIobjv\fR array.
.AP "Tcl_Obj *const" objv[] in
An array of pointers to values.
\fBTcl_NewListObj\fR will insert these values into a new list value
and \fBTcl_ListObjReplace\fR will insert them into an existing \fIlistPtr\fR.
Each value will become a separate list element.
An array of pointers to Tcl values.
.AP "Tcl_Size \&| int" *lengthPtr out
Points to location where \fBTcl_ListObjLength\fR
stores the length of the list.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
TCL_ERROR for lists with more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP Tcl_Size index in
@@ -95,23 +100,22 @@ Index of the list element that \fBTcl_ListObjIndex\fR
is to return.
The first element has index 0.
.AP Tcl_Obj **objPtrPtr out
Points to place where \fBTcl_ListObjIndex\fR is to store
a pointer to the resulting list element value.
Points to location to store an output list or element value. No assumptions
should be made about the reference count of the returned value.
See the \fBREFERENCE COUNT MANAGEMENT\fR section below.
.AP Tcl_Size first in
Index of the starting list element that \fBTcl_ListObjReplace\fR
is to replace.
The list's first element has index 0.
Index of the first element in a range of elements in a list.
.AP Tcl_Size last in
Index of the last element in a range of elements in a list.
.AP Tcl_Size count in
The number of elements that \fBTcl_ListObjReplace\fR
is to replace.
The number of elements to be operated on or a repetition count.
.BE
.SH DESCRIPTION
.PP
Tcl list values have an internal representation that supports
the efficient indexing and appending.
The procedures described in this man page are used to
create, modify, index, and append to Tcl list values from C code.
create, modify, access, and transform Tcl list values from C code.
.PP
\fBTcl_ListObjAppendList\fR and \fBTcl_ListObjAppendElement\fR
both add one or more values
@@ -209,7 +213,6 @@ change from Tcl 8 where all list elements always have a reference
count of at least 1. (See \fBABSTRACT LIST TYPES\fR, \fBSTORAGE
MANAGEMENT OF VALUES\fR, Tcl_BounceRefCount(3), and lseq(n) for more
information.)
.PP
\fBTcl_ListObjReplace\fR replaces zero or more elements
of the list referenced by \fIlistPtr\fR
@@ -268,8 +271,44 @@ with a NULL \fIobjvPtr\fR:
result = \fBTcl_ListObjReplace\fR(interp, listPtr, first, count,
0, NULL);
.CE
.PP
\fBTcl_ListObjRange\fR stores in \fIobjPtrPtr\fR a pointer to a list value
containing all elements in the passed input list \fIlistPtr\fR at indices
between \fIfirst\fR and \fIlast\fR, both inclusive. An empty
list is returned in the case of \fIfirst\fR being greater than \fIlast\fR.
.PP
\fBTcl_ListObjRepeat\fR stores in \fIobjPtrPtr\fR a pointer to a list value
whose elements are the \fIobjc\fR elements passed in \fIobjv\fR, repeated
\fIcount\fR number of times. An error is raised if \fIcount\fR is negative.
.PP
\fBTcl_ListObjReverse\fR stores in \fIobjPtrPtr\fR a pointer to a list value
containing all elements of the input list \fIlistPtr\fR in reverse order.
.PP
For all three functions, \fBTcl_ListObjRange\fR, \fBTcl_ListObjRepeat\fR and
\fBTcl_ListObjReverse\fR, the value passed in \fIlistPtr\fR need not be unshared.
The pointer stored at \fIobjPtrPtr\fR is guaranteed to be different from
\fIlistPtr\fR but no assumptions should be made about its reference count.
In case of errors, the location addressed by \fIobjPtrPtr\fR may have been
modified and should be treated by the caller as undefined.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
Care must be taken by callers when managing the reference count
of values passed in as well as values returned from the above functions.
.PP
Unless specified otherwise below, the above functions may internally
keep a reference to the value passed in \fIlistPtr\fR and increment its
reference count. Therefore, if \fIlistPtr\fR is newly allocated and has
a zero reference count, it should not be freed after the call with
\fBTcl_DecrRefCount\fR. Rather, use \fBTcl_BounceRefCount\fR instead.
Furthermore, if \fIlistPtr\fR was retrieved from the interpreter result
(e.g. via \fBTcl_GetObjResult\fR) and that is the only reference to the
value, it may be deleted if a function sets the interpreter result on
error. The more general and safe method for passing values is to
increment their reference counts with \fBTcl_IncrRefCount\fR prior to
the call and release them with \fBTcl_DecrRefCount\fR when the call
returns. However, this may preclude certain optimizations based on
modifying unshared values in-place.
.PP
\fBTcl_NewListObj\fR always returns a zero-reference object, much like
\fBTcl_NewObj\fR. If a non-NULL \fIobjv\fR argument is given, the reference
counts of the first \fIobjc\fR values in that array are incremented.
@@ -279,20 +318,31 @@ argument, but does require that the object be unshared. The reference counts
of the first \fIobjc\fR values in the \fIobjv\fR array are incremented.
.PP
\fBTcl_ListObjGetElements\fR, \fBTcl_ListObjIndex\fR, and
\fBTcl_ListObjLength\fR do not modify the reference count of their
\fIlistPtr\fR arguments; they only read. Note however that these three
functions may set the interpreter result; if that is the only place that is
holding a reference to the object, it will be deleted.
\fBTcl_ListObjLength\fR do not modify the reference count of the
\fIlistPtr\fR argument except on error when the interpreter
result holds a reference to it as described earlier.
.PP
\fBTcl_ListObjAppendList\fR, \fBTcl_ListObjAppendElement\fR, and
\fBTcl_ListObjReplace\fR require an unshared \fIlistPtr\fR argument.
\fBTcl_ListObjAppendList\fR only reads its \fIelemListPtr\fR argument.
\fBTcl_ListObjAppendElement\fR increments the reference count of its
\fIobjPtr\fR on success. \fBTcl_ListObjReplace\fR increments the reference
count of the first \fIobjc\fR values in the \fIobjv\fR array on success. Note
however that all these three functions may set the interpreter result on
failure; if that is the only place that is holding a reference to the object,
it will be deleted.
\fIobjPtr\fR on success. \fBTcl_ListObjReplace\fR increments the
reference count of the first \fIobjc\fR values in the \fIobjv\fR array
on success. Note that the same caveat stated earlier applies if the
interpreter result holds a reference to \fIlistPtr\fR.
.PP
The pointer to a result value returned in \fIobjPtrPtr\fR by the
functions \fBTcl_ListObjRange\fR,
\fBTcl_ListObjRepeat\fR and \fBTcl_ListObjReverse\fR is guaranteed
to be different from the \fBlistPtr\fR passed in. It is therefore
safe to manage its reference count independently from that of
\fBlistPtr\fR. No assumptions should be made about its reference
count and the standard reference counting idiom should be followed.
The caller can pass it to a function such as \fBTcl_SetObjResult\fR,
\fBTcl_ListObjAppendElement\fR etc. which take ownership of
its reference count management or dispose of the value itself
with either a \fBTcl_IncrRefCount\fR/\fBTcl_DecrRefCount\fR pair or
\fBTcl_BounceRefCount\fR.
.SH "SEE ALSO"
Tcl_NewObj(3), Tcl_DecrRefCount(3), Tcl_IncrRefCount(3), Tcl_GetObjResult(3)
.SH KEYWORDS
+5 -2
View File
@@ -8,7 +8,7 @@
.so man.macros
.BS
.SH NAME
Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_BounceRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl values
Tcl_NewObj, Tcl_DuplicateObj, Tcl_AttemptDuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_BounceRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl values
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -19,6 +19,9 @@ Tcl_Obj *
Tcl_Obj *
\fBTcl_DuplicateObj\fR(\fIobjPtr\fR)
.sp
Tcl_Obj *
\fBTcl_AttemptDuplicateObj\fR(\fIobjPtr\fR)
.sp
\fBTcl_IncrRefCount\fR(\fIobjPtr\fR)
.sp
\fBTcl_DecrRefCount\fR(\fIobjPtr\fR)
@@ -28,7 +31,7 @@ Tcl_Obj *
int
\fBTcl_IsShared\fR(\fIobjPtr\fR)
.sp
\fBTcl_InvalidateStringRep\fR(\fIobjPtr\fR)3
\fBTcl_InvalidateStringRep\fR(\fIobjPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Obj *objPtr
+34 -5
View File
@@ -128,6 +128,17 @@ When \fInumBytes\fR is greater than zero, and the returned pointer is
representation.
The caller may then choose whether to raise an error or panic.
.PP
\fBTcl_InitStringRep\fR performs the function of the existing internal macro
\fBTclInitStringRep\fR, but is extended to return a pointer to the string rep,
and to accept \fBNULL\fR as a value for bytes.
When \fIbytes\fR is \fBNULL\fR and \fIobjPtr\fR has no string rep, an uninitialzed
buffer of numBytes bytes is created for filling by the caller.
When \fIbytes\fR is \fBNULL\fR and \fIobjPtr\fR has a string rep, the string
rep will be truncated to a length of numBytes bytes.
When numBytes is greater than zero, and the returned pointer is \fBNULL\fR, that
indicates a failure to allocate memory for the string representation.
The caller may then choose whether to raise an error or panic.
.PP
\fBTcl_HasStringRep\fR returns a boolean indicating whether or not a string
rep is currently stored in \fIobjPtr\fR.
This is used when the caller wants to act on \fIobjPtr\fR differently
@@ -258,6 +269,9 @@ Tcl routines accepting string values as arguments.
Storage for the byte array must be allocated in the heap by \fBTcl_Alloc\fR.
Note that \fIupdateStringProc\fRs must allocate
enough storage for the string's bytes and the terminating null byte.
If the \fIupdateStringProc\fR cannot do that, it must set
interp->bytes to be NULL (freeing the previous content), and set
interp->length to the number of bytes it tried to allocate.
.PP
The \fIupdateStringProc\fR for Tcl's built-in double type, for example,
calls Tcl_PrintDouble to write to a buffer of size TCL_DOUBLE_SPACE,
@@ -338,8 +352,9 @@ without converting the value to a List type. This requires the custom
type to provide functions that will perform the given operation on the
custom data representation. Not all functions are required. In the
absence of a particular function (set to NULL), the fallback is to
allow the internal List operation to perform the operation, most
likely causing the value type to be converted to a traditional list.
allow the internal List operation to perform the operation, which
may possibly cause the value type to be converted to a traditional
list.
.SS "SCALAR VALUE TYPES"
.PP
For a custom value type that is scalar or atomic in nature, i.e., not
@@ -353,6 +368,17 @@ Version 2, \fBTCL_OBJTYPE_V2\fR, allows full List support when the
functions described below are provided. This allows for script level
use of the List commands without causing the type of the Tcl_Obj value
to be converted to a list.
Unless specified otherwise, all functions specific to Version 2 should return
\fBTCL_OK\fR on success and \fBTCL_ERROR\fR on failure.
In the case that a \fBTcl_Obj*\fR is also returned, the reference count of the
returned \fBTcl_Obj\fR should not be incremented so, for example, if a new
\fBTcl_Obj\fR value is returned it should have a reference count of zero.
The functions should not assume that any \fBTcl_Obj\fR passed in
is unshared.
.SS "THE LENGTHPROC FIELD"
.PP
The \fBLengthProc\fR function correlates with the \fBTcl_ListObjLength\fR
@@ -367,8 +393,11 @@ typedef Tcl_Size
.SS "THE INDEXPROC FIELD"
.PP
The \fBIndexProc\fR function correlates with with the
\fBTcl_ListObjIndex\fR C API. The function returns a Tcl_Obj value for
the element at the specified index.
\fBTcl_ListObjIndex\fR C API. The function should store a pointer to
the element at the specified \fBindex\fR in \fB*elemObj\fR.
Indices that are out of bounds should not be treated as errors;
rather, the function should store a null pointer and
return TCL_OK.
.CS
typedef int (\fBTcl_ObjTypeIndexProc\fR) (
Tcl_Interp *interp,
@@ -393,7 +422,7 @@ typedef int (\fBTcl_ObjTypeSliceProc\fR) (
.PP
The \fBReverseProc\fR correlates with the \fBlreverse\fR command,
returning a List or Abstract List that has the same elements as the
input Abstract List, with the elements in the reverse order.
input Abstract List, but in reverse order.
.CS
typedef int (\fBTcl_ObjTypeReverseProc\fR) (
Tcl_Interp *interp,
+22 -8
View File
@@ -9,7 +9,7 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_GetChannelNames, Tcl_GetChannelNamesEx, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_DetachChannel, Tcl_IsStandardChannel, Tcl_Close, Tcl_ReadChars, Tcl_Read, Tcl_GetsObj, Tcl_Gets, Tcl_WriteObj, Tcl_WriteChars, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_TruncateChannel, Tcl_GetChannelOption, Tcl_SetChannelOption, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_OutputBuffered, Tcl_Ungets, Tcl_ReadRaw, Tcl_WriteRaw \- buffered I/O facilities using channels
Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_GetChannelNames, Tcl_GetChannelNamesEx, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_DetachChannel, Tcl_IsStandardChannel, Tcl_Close, Tcl_CloseEx, Tcl_ReadChars, Tcl_Read, Tcl_GetsObj, Tcl_Gets, Tcl_WriteObj, Tcl_WriteChars, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_TruncateChannel, Tcl_GetChannelOption, Tcl_SetChannelOption, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_OutputBuffered, Tcl_Ungets, Tcl_ReadRaw, Tcl_WriteRaw \- buffered I/O facilities using channels
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -46,6 +46,9 @@ int
int
\fBTcl_Close\fR(\fIinterp, channel\fR)
.sp
int
\fBTcl_CloseEx\fR(\fIinterp, channel, closeFlags\fR)
.sp
Tcl_Size
\fBTcl_ReadChars\fR(\fIchannel, readObjPtr, charsToRead, appendFlag\fR)
.sp
@@ -157,6 +160,10 @@ channel.
The number of characters to read from the channel. If the channel's encoding
is \fBbinary\fR, this is equivalent to the number of bytes to read from the
channel.
.AP int closeFlags in
If \fB0\fR, the channel is closed in both directions. If \fBTCL_CLOSE_READ\fR,
the channel is only closed for reading. If \fBTCL_CLOSE_WRITE\fR, the channel
is only closed for writing. These flags must not be combined.
.AP int appendFlag in
If non-zero, data read from the channel will be appended to the value.
Otherwise, the data will replace the existing contents of the value.
@@ -369,7 +376,7 @@ If so, it returns 1, otherwise 0.
.PP
No attempt is made to check whether the given channel or the standard
channels are initialized or otherwise valid.
.SH TCL_CLOSE
.SH "TCL_CLOSE AND TCL_CLOSEEX"
.PP
\fBTcl_Close\fR destroys the channel \fIchannel\fR, which must denote a
currently open channel. The channel should not be registered in any
@@ -383,16 +390,23 @@ immediately; output is flushed in the background and the channel will be
closed once all of the buffered data has been output. In this case errors
during flushing are not reported.
.PP
If the channel was closed successfully, \fBTcl_Close\fR returns \fBTCL_OK\fR.
If an error occurs, \fBTcl_Close\fR returns \fBTCL_ERROR\fR and records a
POSIX error code that can be retrieved with \fBTcl_GetErrno\fR.
\fBTcl_CloseEx\fR allows for both full closing and half-closing of channels
depending on its \fBcloseFlags\fR parameter. See the description of the
parameter above. It is an error to attempt to close the channel for
a direction for which it is not open. The channel is destroyed only when
it has been closed for both reading and writing. Only socket and command
pipe channels support half-closing.
.PP
If the channel was closed successfully, \fBTcl_Close\fR and \fBTcl_CloseEx\fR
return \fBTCL_OK\fR. If an error occurs, they return \fBTCL_ERROR\fR and record
a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR.
If the channel is being closed synchronously and an error occurs during
closing of the channel and \fIinterp\fR is not NULL, an error message is
left in the interpreter's result.
.PP
Note that it is not safe to call \fBTcl_Close\fR on a channel that has been
registered using \fBTcl_RegisterChannel\fR; see the documentation for
\fBTcl_RegisterChannel\fR, above, for details. If the channel has ever
Note that it is not safe to call the channel closing functions on a channel
that has been registered using \fBTcl_RegisterChannel\fR; see the documentation
for \fBTcl_RegisterChannel\fR, above, for details. If the channel has ever
been given as the \fBchan\fR argument in a call to
\fBTcl_RegisterChannel\fR, you should instead use
\fBTcl_UnregisterChannel\fR, which will internally call \fBTcl_Close\fR
+1 -1
View File
@@ -28,7 +28,7 @@ modified to hold number of arguments left in the unprocessed argument list
stored in \fIremObjv\fR.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
NULL for argument lists with more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP "Tcl_Obj *const" *objv in
+1 -1
View File
@@ -43,7 +43,7 @@ Pointer to a string with proper list structure.
Filled in with number of elements in \fIlist\fR.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will return
TCL_ERROR for lists with more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP "const char" ***argvPtr out
+1 -1
View File
@@ -30,7 +30,7 @@ File path in a form appropriate for the current platform (see the
Filled in with number of path elements in \fIpath\fR.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, argcPtr will be filled
If your extensions is compiled with \fB-DTCL_8_API\fR, argcPtr will be filled
with -1 for paths with more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP "const char" ***argvPtr out
+15 -2
View File
@@ -8,7 +8,7 @@
.so man.macros
.BS
.SH NAME
Tcl_NewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicodeFromObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendObjToObj, Tcl_AppendStringsToObj, Tcl_AppendLimitedToObj, Tcl_Format, Tcl_AppendFormatToObj, Tcl_ObjPrintf, Tcl_AppendPrintfToObj, Tcl_SetObjLength, Tcl_AttemptSetObjLength, Tcl_ConcatObj, Tcl_IsEmpty \- manipulate Tcl values as strings
Tcl_NewStringObj, Tcl_AttemptNewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_AttemptSetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicodeFromObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_AttemptGetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendObjToObj, Tcl_AppendStringsToObj, Tcl_AppendLimitedToObj, Tcl_Format, Tcl_AppendFormatToObj, Tcl_ObjPrintf, Tcl_AppendPrintfToObj, Tcl_SetObjLength, Tcl_AttemptSetObjLength, Tcl_ConcatObj, Tcl_IsEmpty \- manipulate Tcl values as strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -17,11 +17,17 @@ Tcl_Obj *
\fBTcl_NewStringObj\fR(\fIbytes, length\fR)
.sp
Tcl_Obj *
\fBTcl_AttemptNewStringObj\fR(\fIbytes, length\fR)
.sp
Tcl_Obj *
\fBTcl_NewUnicodeObj\fR(\fIunicode, numChars\fR)
.sp
void
\fBTcl_SetStringObj\fR(\fIobjPtr, bytes, length\fR)
.sp
char *
\fBTcl_AttemptSetStringObj\fR(\fIobjPtr, bytes, length\fR)
.sp
void
\fBTcl_SetUnicodeObj\fR(\fIobjPtr, unicode, numChars\fR)
.sp
@@ -43,6 +49,9 @@ int
Tcl_Size
\fBTcl_GetCharLength\fR(\fIobjPtr\fR)
.sp
Tcl_Size
\fBTcl_AttemptGetCharLength\fR(\fIobjPtr\fR)
.sp
Tcl_Obj *
\fBTcl_GetRange\fR(\fIobjPtr, first, last\fR)
.sp
@@ -127,7 +136,7 @@ The location where \fBTcl_GetStringFromObj\fR will store the length
of a value's string representation.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will
If your extensions is compiled with \fB-DTCL_8_API\fR, this function will
panic for strings with more than INT_MAX bytes/characters, otherwise
expect it to crash.
.AP "const char" *string in
@@ -224,6 +233,10 @@ negative, then the returned string ends at the end of the value.
\fBTcl_GetCharLength\fR returns the number of characters (as opposed
to bytes) in the string value.
.PP
\fBTcl_AttemptGetCharLength\fR returns the number of characters
(as opposed to bytes) in the string value. It returns -1 if this
cannot be determined.
.PP
\fBTcl_AppendToObj\fR appends the data given by \fIbytes\fR and
\fIlength\fR to the string representation of the value specified by
\fIobjPtr\fR. If the value has an invalid string representation,
+1 -1
View File
@@ -34,7 +34,7 @@ Tcl_Obj *
Number of elements in \fIargv\fR.
.AP char *argv[] in
Array of strings containing command-line arguments. On Windows, when
using -DUNICODE, the parameter type changes to wchar_t *.
using \fB\-DUNICODE\fR, the parameter type changes to wchar_t *.
.AP char *charargv[] in
As argv, but does not change type to wchar_t.
.AP char *wideargv[] in
+66
View File
@@ -0,0 +1,66 @@
'\"
'\" Copyright (c) 2025 Ashok P. Nadkarni.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH unicode n "9.1" Tcl "Tcl Built-In Commands"
.so man.macros
.BS
.SH NAME
unicode \- Unicode character transforms
.SH SYNOPSIS
\fBunicode \fIfunction\fR ?\fIoptions\fR? \fIstring\fR
.BE
.SH DESCRIPTION
.PP
The command performs one of several Unicode character transformations, depending on
\fIfunction\fR which may take the values described below.
.\" METHOD: tonfc
.VS "TIP726"
.TP
\fBunicode tonfc\fR ?\fB-profile\fR \fIprofile\fR \fIstring\fR
.VE "TIP726"
.
Returns \fIstring\fR normalized as per Unicode \fBNormalization Form C\fR (NFC).
.PP
.\" METHOD: tonfd
.VS "TIP726"
.TP
\fBunicode tonfd\fR ?\fB-profile\fR \fIprofile\fR \fIstring\fR
.VE "TIP726"
.
Returns \fIstring\fR normalized as per Unicode \fBNormalization Form D\fR (NFD).
.PP
.\" METHOD: tonfkc
.VS "TIP726"
.TP
\fBunicode tonfkc\fR ?\fB-profile\fR \fIprofile\fR \fIstring\fR
.VE "TIP726"
.
Returns \fIstring\fR normalized as per Unicode \fBNormalization Form KC\fR (NFKC).
.PP
.\" METHOD: tonfkd
.VS "TIP726"
.TP
\fBunicode tonfkd\fR ?\fB-profile\fR \fIprofile\fR \fIstring\fR
.VE "TIP726"
.
Returns \fIstring\fR normalized as per Unicode \fBNormalization Form KD\fR (NFKD).
.PP
The normalization forms NFC, NFD, NFKC and NFKD referenced above are defined
in \fBSection 3.11\fR of the Unicode standard
(see https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/).
.PP
The \fB-profile\fR option determines the command behavior in the presence
of conversion errors. The passed profile must be \fBstrict\fR or \fBreplace\fR.
See the \fBPROFILES\fR section in the documentation
of the \fBencoding\fR command for details on profiles.
.PP
.SH "SEE ALSO"
Tcl_UtfToNormalized(3)
.SH KEYWORDS
Unicode, normalize
.\" Local Variables:
.\" mode: nroff
.\" End:
+82
View File
@@ -0,0 +1,82 @@
'\"
'\" Copyright (c) 2025 Ashok P. Nadkarni
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_UtfToNormalized 3 "9.1" Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_UtfToNormalized, Tcl_UtfToNormalizedDString \- procedures for Unicode normalization
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_UtfToNormalized\fR(\fIinterp, src, numBytes, normForm, profile, dst, dstLen, dstWrotePtr\fR)
.sp
int
\fBTcl_UtfToNormalizedDString\fR(\fIinterp, src, numBytes, normForm, profile, dstPtr\fR)
.fi
.SH ARGUMENTS
.AP Tcl_Interp *interp in
Interpreter to use for error reporting, or NULL if no error reporting is
desired.
.AP "const char" *src in
An array of bytes in Tcl's internal UTF-8 based encoding.
.AP Tcl_Size numBytes in
Length of \fIsrc\fR in bytes. If the length is negative,
the length includes all bytes until the first nul byte.
.AP char *dst out
Buffer in which the converted result will be stored. No more than
\fIdstLen\fR bytes will be stored in \fIdst\fR.
.AP Tcl_Size dstLen in
The size of the output buffer \fIdst\fR in bytes.
.AP Tcl_Size *dstWrotePtr out
Filled with the number of bytes in the normalized string. This number
does not include the terminating nul character.
May be NULL.
.AP Tcl_UnicodeNormalizationForm normForm in
Must be one of the \fBTcl_UnicodeNormalizationForm\fR members
\fBTCL_NFC\fR, \fBTCL_NFD\fR, \fBTCL_NFKC\fR or \fBTCL_NFKD\fR specifying
the Unicode normalization type.
.AP int profile in/out
The encoding profile as described in the \fBTcl_GetEncoding\fR documentation.
Must be either \fBTCL_ENCODING_PROFILE_STRICT\fR
or \fBTCL_ENCODING_PROFILE_REPLACE\fR.
.AP Tcl_DString *dstPtr out
Pointer to an uninitialized or free \fBTcl_DString\fR in which the converted
result, which is also encoded in Tcl's internal UTF-8 encoding, will be stored.
The function initializes the storage and caller must call
\fBTcl_DStringFree\fR on success.
.BE
.SH DESCRIPTION
.PP
The \fBTcl_UtfToNormalized\fR and \fBTcl_UtfToNormalizedDString\fR functions
transform the passed string into one of the standard normalization forms defined
in the Unicode standard. The normalization form is specified via the
\fInormForm\fR argument which must have one of the values \fBTCL_NFC\fR,
\fBTCL_NFD\fR, \fBTCL_NFKC\fR or \fBTCL_NFKD\fR corresponding to the Unicode
normalization forms \fBNormalization Form C\fR (NFC), \fBNormalization Form D\fR
(NFD), \fBNormalization Form KC\fR (NFKC) and \fBNormalization Form KD\fR (NFKD)
respectively. For details on the above normalization forms, refer to Section
3.11 of the Unicode standard
(https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/).
.PP
The \fBTcl_UtfToNormalized\fR function stores the normalized result
in the buffer provided by the caller through the \fIdst\fR argument. The
result is nul terminated but the nul is not included in the count of
stored bytes returned in \fIdstWrotePtr\fR. The function returns TCL_OK
on success, TCL_CONVERT_NOSPACE if there is insufficient room in the output
buffer and TCL_ERROR in case of other failures. In the latter two cases,
an error message is stored in \fIinterp\fR if it is not NULL.
.PP
The \fBTcl_UtfToNormalizedDString\fR function stores the normalized result
in \fIdstPtr\fR which must eventually be freed by caller through
\fBTcl_DStringFree\fR. The function returns TCL_OK on success and
TCL_ERROR on failure with an error message in \fIinterp\fR if it is not NULL.
.SH "SEE ALSO"
unicode(n)
.SH KEYWORDS
utf, Unicode, normalize
+173
View File
@@ -0,0 +1,173 @@
'\"
'\" Copyright (c) 2025 Jan Nijtmans.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH build-info n 9.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
buildinfo \- Build info
.SH SYNOPSIS
\fB::tcl::build-info\fR ?\fIfield\fR?
.BE
.SH DESCRIPTION
.PP
This command provides a way to retrieve information about how Tcl was built.
Without any options, the command returns the Tcl patchlevel, followed
by the '+'-sign, followed by the fossil commit-id followed by a list of
dot-separated tags. If a \fIfield\fR is given, this command extracts that
field as described below. Any other \fIfield\fR value not mentioned
below will always return "0". For official Tcl releases, the \fIfield\fRs are:
.\" METHOD: clang
.TP
\fB::tcl::build-info clang\fR
.
Returns the clang version number (as 4 digits) if Tcl is compiled with clang, 0 otherwise.
.\" METHOD: commit
.TP
\fB::tcl::build-info commit\fR
.
Returns the fossil commit-id where Tcl was built from.
.\" METHOD: compiledebug
.TP
\fB::tcl::build-info compiledebug\fR
.
Returns 1 if Tcl is compiled with \fB\-DTCL_COMPILE_DEBUG\fR, 0 otherwise.
.\" METHOD: compiler
.TP
\fB::tcl::build-info compiler\fR
.
Returns the compiler name (either clang, gcc, icc or msvc), followed by a dash and a (4-digit) version number.
.\" METHOD: compilestats
.TP
\fB::tcl::build-info compilestats\fR
.
Returns 1 if Tcl is compiled with \fB\-DTCL_COMPILE_STATS\fR, 0 otherwise.
.\" METHOD: cplusplus
.TP
\fB::tcl::build-info cplusplus\fR
.
Returns 1 if Tcl is compiled with a C++ compiler, 0 otherwise.
.\" METHOD: debug
.TP
\fB::tcl::build-info debug\fR
.
Returns 1 if Tcl is not compiled with \fB\-DNDEBUG\fR, 0 otherwise.
.\" METHOD: gcc
.TP
\fB::tcl::build-info gcc\fR
.
Returns the gcc version number (as 4 digits) if Tcl is compiled with gcc, 0 otherwise.
.\" METHOD: icc
.TP
\fB::tcl::build-info icc\fR
.
Returns the icc version number (as 4 digits) if Tcl is compiled with icc, 0 otherwise.
.\" METHOD: ilp32
.TP
\fB::tcl::build-info ilp32\fR
.
Returns 1 if Tcl is compiled such that integers, longs and pointers are all 32-bit, 0 otherwise.
.\" METHOD: memdebug
.TP
\fB::tcl::build-info memdebug\fR
.
Returns 1 if Tcl is compiled with \fB\-DTCL_MEM_DEBUG\fR, 0 otherwise.
.\" METHOD: msvc
.TP
\fB::tcl::build-info msvc\fR
.
Returns the msvc version number (as 4 digits) if Tcl is compiled with msvc, 0 otherwise.
.\" METHOD: nmake
.TP
\fB::tcl::build-info nmake\fR
.
Returns 1 if Tcl is built using nmake, 0 otherwise.
.\" METHOD: no-deprecate
.TP
\fB::tcl::build-info no-deprecate\fR
.
Returns 1 if Tcl is compiled with \fB\-DTCL_NO_DEPRECATED\fR, 0 otherwise.
.\" METHOD: no-thread
.TP
\fB::tcl::build-info no-thread\fR
.
Returns 1 if Tcl is compiled with \fB\-DTCL_THREADS=0\fR, 0 otherwise.
.\" METHOD: no-optimize
.TP
\fB::tcl::build-info no-optimize\fR
.
Returns 1 if Tcl is not compiled with \fB\-DTCL_CFG_OPTIMIZED\fR, 0 otherwise.
.\" METHOD: objective-c
.TP
\fB::tcl::build-info objective-c\fR
.
Returns 1 if Tcl is compiled with an objective-c compiler, 0 otherwise.
.\" METHOD: objective-cplusplus
.TP
\fB::tcl::build-info objective-cplusplus\fR
.
Returns 1 if Tcl is compiled with an objective-c++ compiler, 0 otherwise.
.\" METHOD: patchlevel
.TP
\fB::tcl::build-info patchlevel\fR
.
Returns the Tcl patchlevel, same as \fBinfo patchlevel\fR.
.\" METHOD: profile
.TP
\fB::tcl::build-info profile\fR
.
Returns 1 if Tcl is compiled with \fB\-DTCL_CFG_PROFILED\fR, 0 otherwise.
.\" METHOD: purify
.TP
\fB::tcl::build-info purify\fR
.
Returns 1 if Tcl is compiled with \fB\-DPURIFY\fR, 0 otherwise.
.\" METHOD: static
.TP
\fB::tcl::build-info static\fR
.
Returns 1 if Tcl is compiled as a static library, 0 otherwise.
.\" METHOD: tommath
.TP
\fB::tcl::build-info tommath\fR
.
Returns the libtommath version number (as 4 digits) if libtommath is built into Tcl, 0 otherwise.
.\" METHOD: version
.TP
\fB::tcl::build-info version\fR
.
Returns the Tcl version, same as \fBinfo tclversion\fR.
.\" METHOD: zlib
.TP
\fB::tcl::build-info zlib\fR
.
Returns the zlib version number (as 4 digits) if zlib is built into Tcl, 0 otherwise.
.SH "EXAMPLES"
.PP
These show the use of \fB::tcl::build-info\fR.
.PP
.CS
\fB::tcl::build-info\fR
\fI\(-> 9.0.2+af16c07b81655fabde8028374161ad54b84ef9956843c63f49976b4ef601b611.gcc-1204\fR
\fB::tcl::build-info commit\fR
\fI\(-> af16c07b81655fabde8028374161ad54b84ef9956843c63f49976b4ef601b611\fR
\fB::tcl::build-info compiler\fR
\fI\(-> gcc-1204\fR
\fB::tcl::build-info gcc\fR
\fI\(-> 1204\fR
\fB::tcl::build-info version\fR
\fI\(-> 9.0\fR
\fB::tcl::build-info patchlevel\fR
\fI\(-> 9.0.2\fR
.CE
.SH "SEE ALSO"
info(n)
.SH "KEYWORDS"
build-info
'\" Local Variables:
'\" mode: nroff
'\" End:
+8
View File
@@ -104,6 +104,14 @@ Returns a list of the names of encoding profiles. See \fBPROFILES\fR below.
Set the system encoding to \fIencoding\fR. If \fIencoding\fR is
omitted then the command returns the current system encoding. The
system encoding is used whenever Tcl passes strings to system calls.
.TP
\fBencoding user\fR
.VS TIP716
Returns the name of encoding as per the user's preferences. On Windows
systems, this is based on the user's code page settings in the registry.
On other platforms, the returned value is the same as returned by
\fBencoding system\fR.
.VE TIP716
.\" Do not put .VS on whole section as that messes up the bullet list alignment
.SH PROFILES
.PP
+6
View File
@@ -31,6 +31,12 @@ If the initial arguments to \fBexec\fR start with \fB\-\fR then
they are treated as command-line switches and are not part
of the pipeline specification. The following switches are
currently supported:
.\" OPTION: -encoding
.TP 13
\fB\-encoding \fIencodingName\fR
.
Specifies the name of the encoding to use to decode the output of the first
subprocess. Defaults to that returned by the \fBencoding system\fR command.
.\" OPTION: -ignorestderr
.TP 13
\fB\-ignorestderr\fR
+1 -1
View File
@@ -109,7 +109,7 @@ oo::class create Ex {
}
set o [Ex new]
$o 3 5 7
$o call 3 5 7
\fI\(-> This is a\fR
\fI\(-> This is b(3)\fR
\fI\(-> This is c(5,7)\fR
+5 -1
View File
@@ -19,7 +19,8 @@ lseq \- Build a numeric sequence returned as a list
.BE
.SH DESCRIPTION
.PP
The \fBlseq\fR command creates a sequence of numeric values using the given
The \fBlseq\fR command creates a sequence of numeric values, which may
be either wide integers or doubles, using the given
parameters \fIstart\fR, \fIend\fR, and \fIstep\fR. The \fIoperation\fR
argument "\fB..\fR" or "\fBto\fR" defines the range. The "\fBcount\fR" option
is used to define a count of the number of elements in the list. A short form
@@ -42,6 +43,9 @@ empty list is returned. For example:
% \fBlseq\fR 5 to 1 ;# decreasing
\fI\(-> 5 4 3 2 1
% \fBlseq\fR 0 0.5 by 0.1 ;# doubles
\fI\(-> 0.0 0.1 0.2 0.3 0.4 0.5\fR
% \fBlseq\fR 6 to 1 by 2 ;# decreasing, step wrong sign, empty list
% \fBlseq\fR 1 to 5 by 0 ;# all step sizes of 0 produce an empty list
+10 -7
View File
@@ -348,8 +348,9 @@ characters in the reverse order.
Returns a value equal to \fIstring\fR except that all upper (or title)
case letters have been converted to lower case. If \fIfirst\fR is
specified, it refers to the first char index in the string to start
modifying. If \fIlast\fR is specified, it refers to the char index in
the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be
modifying. If \fIlast\fR is not specified, only the character at position
\fIfirst\fR is converted, otherwise \fIlast\fR refers to the char index
in the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be
specified using the forms described in \fBSTRING INDICES\fR.
.\" METHOD: totitle
.TP
@@ -360,9 +361,10 @@ in \fIstring\fR is converted to its Unicode title case variant (or
upper case if there is no title case variant) and the rest of the
string is converted to lower case. If \fIfirst\fR is specified, it
refers to the first char index in the string to start modifying. If
\fIlast\fR is specified, it refers to the char index in the string to
stop at (inclusive). \fIfirst\fR and \fIlast\fR may be specified
using the forms described in \fBSTRING INDICES\fR.
\fIlast\fR is not specified, only the character at position \fIfirst\fR
is converted, otherwise \fIlast\fR refers to the char index in
the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be
specified using the forms described in \fBSTRING INDICES\fR.
.\" METHOD: toupper
.TP
\fBstring toupper \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR?
@@ -370,8 +372,9 @@ using the forms described in \fBSTRING INDICES\fR.
Returns a value equal to \fIstring\fR except that all lower (or title)
case letters have been converted to upper case. If \fIfirst\fR is
specified, it refers to the first char index in the string to start
modifying. If \fIlast\fR is specified, it refers to the char index in
the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be
modifying. If \fIlast\fR is not specified, only the character at position
\fIfirst\fR is converted, otherwise \fIlast\fR refers to the char index
in the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be
specified using the forms described in \fBSTRING INDICES\fR.
.\" METHOD: trim
.TP
+15
View File
@@ -13,7 +13,10 @@
.SH NAME
subst \- Perform backslash, command, and variable substitutions
.SH SYNOPSIS
.nf
\fBsubst \fR?\fB\-nobackslashes\fR? ?\fB\-nocommands\fR? ?\fB\-novariables\fR? \fIstring\fR
\fBsubst \fR?\fB\-backslashes\fR? ?\fB\-commands\fR? ?\fB\-variables\fR? \fIstring\fR
.fi
.BE
.SH DESCRIPTION
.PP
@@ -33,6 +36,18 @@ For example, if \fB\-nocommands\fR is specified, command substitution
is not performed: open and close brackets are treated as ordinary characters
with no special interpretation.
.PP
If any of the \fB\-backslashes\fR, \fB\-commands\fR, or
\fB\-variables\fR are specified, then only the corresponding
substitutions are performed. This means that the following lines are
equivalent:
.PP
.CS
\fBsubst\fR -nobackslashes -nocommands $string
\fBsubst\fR -variables $string
.CE
.PP
It is not allowed to combine positive and negated options.
.PP
Note that the substitution of one kind can include substitution of
other kinds. For example, even when the \fB\-novariables\fR option
is specified, command substitution is performed without restriction.
-3
View File
@@ -330,9 +330,6 @@ general operating environment of the machine.
.IP \fBpointerSize\fR
This gives the size of the native-machine pointer in bytes (strictly, it
is same as the result of evaluating \fIsizeof(void*)\fR in C.)
.IP \fBthreaded\fR
If this variable exists, then the interpreter
was compiled with threads enabled.
.IP \fBuser\fR
This identifies the
current user based on the login information available on the platform.
+66 -9
View File
@@ -104,6 +104,9 @@ declare 20 {
declare 21 {
int Tcl_DbIsShared(Tcl_Obj *objPtr, const char *file, int line)
}
declare 22 {
char *Tcl_DbGetStringFromObj(Tcl_Obj *objPtr, Tcl_Size *lengthPtr, const char *file, int line)
}
declare 23 {
Tcl_Obj *Tcl_DbNewByteArrayObj(const unsigned char *bytes,
Tcl_Size numBytes, const char *file, int line)
@@ -193,6 +196,9 @@ declare 55 {
declare 56 {
Tcl_Obj *Tcl_NewStringObj(const char *bytes, Tcl_Size length)
}
declare 57 {
Tcl_Obj *Tcl_AttemptNewStringObj(const char *bytes, Tcl_Size length)
}
declare 58 {
unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, Tcl_Size numBytes)
}
@@ -203,6 +209,9 @@ declare 59 {
declare 60 {
void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue)
}
declare 61 {
Tcl_Size Tcl_AttemptGetCharLength(Tcl_Obj *objPtr)
}
declare 62 {
void Tcl_SetListObj(Tcl_Obj *objPtr, Tcl_Size objc, Tcl_Obj *const objv[])
}
@@ -1039,7 +1048,13 @@ declare 339 {
Tcl_Size Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr)
}
declare 340 {
char *Tcl_GetString(Tcl_Obj *objPtr)
char *Tcl_AttemptGetStringFromObj(Tcl_Obj *objPtr, Tcl_Size *lengthPtr)
}
declare 341 {
char *Tcl_AttemptSetStringObj(Tcl_Obj *objPtr, const char *bytes, Tcl_Size length)
}
declare 342 {
Tcl_Obj *Tcl_AttemptDuplicateObj(Tcl_Obj *objPtr)
}
declare 343 {
void Tcl_AlertNotifier(void *clientData)
@@ -1118,10 +1133,10 @@ declare 365 {
char *Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)
}
declare 366 {
int Tcl_Chdir(const char *dirName)
int Tcl_Chdir(const char *dirName)
}
declare 367 {
int Tcl_Access(const char *path, int mode)
int Tcl_Access(const char *path, int mode)
}
declare 368 {
int Tcl_Stat(const char *path, struct stat *bufPtr)
@@ -1288,6 +1303,14 @@ declare 417 {
declare 418 {
int Tcl_IsChannelExisting(const char *channelName)
}
declare 421 {
Tcl_HashEntry *Tcl_DbCreateHashEntry(Tcl_HashTable *tablePtr,
const void *key, int *newPtr, const char *file, int line)
}
declare 422 {
Tcl_HashEntry *Tcl_CreateHashEntry(Tcl_HashTable *tablePtr,
const void *key, int *newPtr)
}
declare 423 {
void Tcl_InitCustomHashTable(Tcl_HashTable *tablePtr, int keyType,
const Tcl_HashKeyType *typePtr)
@@ -2081,12 +2104,12 @@ declare 626 {
# TIP #357 (Export TclLoadFile and TclpFindSymbol) kbk
declare 627 {
int Tcl_LoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
const char *const symv[], int flags, void *procPtrs,
Tcl_LoadHandle *handlePtr)
const char *const symv[], int flags, void *procPtrs,
Tcl_LoadHandle *handlePtr)
}
declare 628 {
void *Tcl_FindSymbol(Tcl_Interp *interp, Tcl_LoadHandle handle,
const char *symbol)
const char *symbol)
}
declare 629 {
int Tcl_FSUnloadFile(Tcl_Interp *interp, Tcl_LoadHandle handlePtr)
@@ -2331,7 +2354,7 @@ declare 682 {
# TIP 643
declare 683 {
Tcl_Size Tcl_GetEncodingNulLength(Tcl_Encoding encoding)
Tcl_Size Tcl_GetEncodingNulLength(Tcl_Encoding encoding)
}
# TIP #650
@@ -2360,15 +2383,49 @@ declare 689 {
void Tcl_SetWideUIntObj(Tcl_Obj *objPtr, Tcl_WideUInt uwideValue)
}
# ----- BASELINE -- FOR -- 8.7.0 / 9.0.0 ----- #
# ----- BASELINE -- FOR -- 9.0.0 ----- #
# TIP 711
declare 690 {
int Tcl_IsEmpty(Tcl_Obj *obj)
}
# TIP 716
declare 691 {
const char *Tcl_GetEncodingNameForUser(Tcl_DString *bufPtr)
}
# TIP 649
declare 692 {
int Tcl_ListObjReverse(Tcl_Interp *interp, Tcl_Obj *objPtr,
Tcl_Obj **resultPtrPtr)
}
declare 693 {
int Tcl_ListObjRepeat(Tcl_Interp *interp, Tcl_Size repeatCount,
Tcl_Size objc, Tcl_Obj *const objv[], Tcl_Obj **resultPtrPtr)
}
declare 694 {
int Tcl_ListObjRange(Tcl_Interp *interp, Tcl_Obj *objPtr,
Tcl_Size start, Tcl_Size end, Tcl_Obj **resultPtrPtr)
}
# TIP 726
declare 695 {
int Tcl_UtfToNormalizedDString(Tcl_Interp *interp,
const char *bytes, Tcl_Size length,
Tcl_UnicodeNormalizationForm normForm, int profile,
Tcl_DString *dsPtr)
}
declare 696 {
int Tcl_UtfToNormalized(Tcl_Interp *interp,
const char *bytes, Tcl_Size length,
Tcl_UnicodeNormalizationForm normForm, int profile,
char *bufPtr, Tcl_Size bufLen, Tcl_Size *lengthPtr)
}
# ----- BASELINE -- FOR -- 9.1.0 ----- #
declare 691 {
declare 697 {
void TclUnusedStubEntry(void)
}
+23 -7
View File
@@ -54,10 +54,10 @@ extern "C" {
#endif
#define TCL_MINOR_VERSION 1
#define TCL_RELEASE_LEVEL TCL_ALPHA_RELEASE
#define TCL_RELEASE_SERIAL 0
#define TCL_RELEASE_SERIAL 1
#define TCL_VERSION "9.1"
#define TCL_PATCH_LEVEL "9.1a0"
#define TCL_PATCH_LEVEL "9.1a1"
#if defined(RC_INVOKED)
/*
@@ -1020,7 +1020,7 @@ typedef struct Tcl_DString {
* Forward declarations of Tcl_HashTable and related types.
*/
#ifndef TCL_HASH_TYPE
#if !defined(TCL_HASH_TYPE) && !defined (TCL_NO_DEPRECATED)
# define TCL_HASH_TYPE size_t
#endif
@@ -1155,7 +1155,11 @@ struct Tcl_HashTable {
* TCL_ONE_WORD_KEYS, or an integer giving the
* number of ints that is the size of the
* key. */
#ifndef TCL_NO_DEPRECATED
Tcl_HashEntry *(*findProc) (Tcl_HashTable *tablePtr, const char *key);
#else
void *unUsed;
#endif
Tcl_HashEntry *(*createProc) (Tcl_HashTable *tablePtr, const char *key,
int *newPtr);
const Tcl_HashKeyType *typePtr;
@@ -2042,6 +2046,13 @@ typedef unsigned short Tcl_UniChar;
#else
# error "This TCL_UTF_MAX value is not supported"
#endif
/*
* Specifiers for Unicode normalization forms.
*/
typedef enum {
TCL_NFC, TCL_NFD, TCL_NFKC, TCL_NFKD
} Tcl_UnicodeNormalizationForm;
/*
*----------------------------------------------------------------------------
@@ -2409,12 +2420,12 @@ EXTERN const char *TclZipfs_AppHook(int *argc, char ***argv);
static inline void
TclBounceRefCount(
Tcl_Obj* objPtr,
const char* fn,
const char* file,
int line)
{
if (objPtr) {
if ((objPtr)->refCount == 0) {
Tcl_DbDecrRefCount(objPtr, fn, line);
Tcl_DbDecrRefCount(objPtr, file, line);
}
}
}
@@ -2510,9 +2521,14 @@ TclBounceRefCount(
*/
#define Tcl_FindHashEntry(tablePtr, key) \
(*((tablePtr)->findProc))(tablePtr, (const char *)(key))
#define Tcl_CreateHashEntry(tablePtr, key, newPtr) \
(*((tablePtr)->createProc))(tablePtr, (const char *)(key), (int *)-1)
#define Tcl_AttemptCreateHashEntry(tablePtr, key, newPtr) \
(*((tablePtr)->createProc))(tablePtr, (const char *)(key), newPtr)
#ifdef TCL_MEM_DEBUG
#undef Tcl_CreateHashEntry
#define Tcl_CreateHashEntry(tablePtr, key, newPtr) \
Tcl_DbCreateHashEntry(tablePtr, key, newPtr, __FILE__, __LINE__)
#endif
#endif /* RC_INVOKED */
+127 -76
View File
@@ -217,7 +217,7 @@ ArithSeriesGetInternalRep(
}
/*
* Compute number of significant fractional digits
* Compute number of significant fractional digits.
*/
static inline unsigned
ObjPrecision(
@@ -228,8 +228,7 @@ ObjPrecision(
if (TclHasInternalRep(numObj, &tclDoubleType) || (
Tcl_GetNumberFromObj(NULL, numObj, &ptr, &type) == TCL_OK
&& type == TCL_NUMBER_DOUBLE)
) { /* TCL_NUMBER_DOUBLE */
&& type == TCL_NUMBER_DOUBLE)) {
const char *str = TclGetString(numObj);
if (strchr(str, 'e') == NULL && strchr(str, 'E') == NULL) {
@@ -275,15 +274,13 @@ maxObjPrecision(
*
* ArithSeriesLen --
*
* Compute the length of the equivalent list where
* every element is generated starting from *start*,
* and adding *step* to generate every successive element
* that's < *end* for positive steps, or > *end* for negative
* steps.
* Compute the length of the equivalent list where every element is
* generated starting from *start*, and adding *step* to generate every
* successive element that's < *end* for positive steps, or > *end* for
* negative steps.
*
* Results:
* The length of the list generated by the given range,
* that may be zero.
* The length of the list generated by the given range, that may be zero.
* The function returns -1 if the list is of length infinite.
*
* Side effects:
@@ -456,21 +453,61 @@ static Tcl_Obj *
NewArithSeriesInt(
Tcl_WideInt start,
Tcl_WideInt step,
Tcl_WideInt len)
Tcl_WideInt length)
{
Tcl_WideInt length;
Tcl_Obj *arithSeriesObj;
Tcl_Obj *arithSeriesObj = NULL;
ArithSeriesInt *arithSeriesRepPtr;
length = len>=0 ? len : -1;
if (length < 0) {
length = -1;
}
TclNewObj(arithSeriesObj);
if (length <= 0) {
/* TODO - should negative lengths be an error? */
return arithSeriesObj;
} else if (length > 1) {
/* Check for numeric overflow. Not needed for single element lists */
Tcl_WideUInt absoluteStep;
Tcl_WideInt numIntervals = length - 1;
/*
* The checks below can probably be condensed but it is very easy to
* either inadvertently use undefined C behavior or unintended type
* promotion. Separating the cases helps me think more clearly.
*/
if (step >= 0) {
absoluteStep = step;
} else if (step == WIDE_MIN) {
/* -step and abs(step) are both undefined behavior */
absoluteStep = 1 + (Tcl_WideUInt)WIDE_MAX;
} else {
absoluteStep = -step;
}
/* First, step*number of intervals should not overflow */
if ((UWIDE_MAX / absoluteStep) < (Tcl_WideUInt) numIntervals) {
goto invalidRange;
}
if (step > 0) {
/*
* Because of check above and UWIDE_MAX=2*WIDE_MAX+1,
* second term will not underflow a Tcl_WideInt
*/
if (start > (WIDE_MAX - (step * numIntervals))) {
goto invalidRange;
}
} else if (step == WIDE_MIN) {
if (numIntervals > 0 || start < 0) {
goto invalidRange;
}
} else if (step < 0) {
/*
* Because of check above and UWIDE_MAX=2*WIDE_MAX+1 and
* step != WIDE_MIN second term will not underflow a Tcl_WideInt.
* DON'T use absoluteStep here because of unsigned type promotion
*/
if (start < (WIDE_MIN + ((-step) * numIntervals))) {
goto invalidRange;
}
} else /* step == 0 */ {
/* TODO - step == 0 && length > 1 should be error? */
}
}
arithSeriesRepPtr = (ArithSeriesInt *) Tcl_Alloc(sizeof(ArithSeriesInt));
@@ -483,11 +520,13 @@ NewArithSeriesInt(
arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr;
arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL;
arithSeriesObj->typePtr = &arithSeriesType;
if (length > 0) {
Tcl_InvalidateStringRep(arithSeriesObj);
}
Tcl_InvalidateStringRep(arithSeriesObj);
return arithSeriesObj;
invalidRange:
Tcl_BounceRefCount(arithSeriesObj);
return NULL;
}
/*
@@ -504,6 +543,7 @@ NewArithSeriesInt(
*
* Side Effects:
* None.
*
*----------------------------------------------------------------------
*/
static Tcl_Obj *
@@ -561,6 +601,7 @@ NewArithSeriesDbl(
*
* Side Effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
@@ -622,6 +663,7 @@ assignNumber(
*
* Side Effects:
* None.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
@@ -639,6 +681,8 @@ TclNewArithSeriesObj(
Tcl_WideInt len = -1;
Tcl_Obj *objPtr;
unsigned precision = (unsigned)-1; /* unknown precision */
const char *description;
char tmp[TCL_DOUBLE_SPACE + 2] = {0};
if (startObj) {
if (assignNumber(interp, useDoubles, &start, &dstart, startObj) != TCL_OK) {
@@ -657,15 +701,11 @@ TclNewArithSeriesObj(
return objPtr;
}
}
if (endObj) {
if (assignNumber(interp, useDoubles, &end, &dend, endObj) != TCL_OK) {
return NULL;
}
if (endObj && assignNumber(interp, useDoubles, &end, &dend, endObj) != TCL_OK) {
return NULL;
}
if (lenObj) {
if (Tcl_GetWideIntFromObj(interp, lenObj, &len) != TCL_OK) {
return NULL;
}
if (lenObj && Tcl_GetWideIntFromObj(interp, lenObj, &len) != TCL_OK) {
return NULL;
}
if (endObj) {
@@ -682,24 +722,13 @@ TclNewArithSeriesObj(
}
}
}
assert(dstep!=0);
assert(dstep != 0);
if (!lenObj) {
if (useDoubles) {
if (isinf(dstart) || isinf(dend)) {
goto exceeded;
}
if (isnan(dstart) || isnan(dend)) {
const char *description = "non-numeric floating-point value";
char tmp[TCL_DOUBLE_SPACE + 2];
tmp[0] = '\0';
Tcl_PrintDouble(NULL, isnan(dstart)?dstart:dend, tmp);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"cannot use %s \"%s\" to estimate length of arith-series",
description, tmp));
Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description,
(char *)NULL);
return NULL;
} else if (isnan(dstart) || isnan(dend)) {
goto notANumber;
}
precision = maxObjPrecision(startObj, endObj, stepObj);
len = ArithSeriesLenDbl(dstart, dend, dstep, precision);
@@ -707,32 +736,23 @@ TclNewArithSeriesObj(
len = ArithSeriesLenInt(start, end, step);
}
}
} else {
if (useDoubles) {
// Compute precision based on given command argument values
precision = maxObjPrecision(startObj, NULL, stepObj);
} else if (useDoubles) {
// Compute precision based on given command argument values
precision = maxObjPrecision(startObj, NULL, stepObj);
dend = dstart + (dstep * (double)(len-1));
// Make computed end value match argument(s) precision
dend = ArithRound(dend, precision);
end = dend;
} else {
end = start + (step * (len - 1));
dend = (double)end;
}
dend = dstart + (dstep * (double)(len-1));
// Make computed end value match argument(s) precision
dend = ArithRound(dend, precision);
end = dend;
}
/*
* todo: check whether the boundary must be rather LIST_MAX, to be more
* similar to plain lists, otherwise it'd generare an error or panic later
* similar to plain lists, otherwise it'd generate an error or panic later
* (0x0ffffffffffffffa instead of 0x7fffffffffffffff by 64bit)
*/
if (len > TCL_SIZE_MAX) {
exceeded:
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"max length of a Tcl list exceeded", TCL_AUTO_LENGTH));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
return NULL;
goto exceeded;
}
if (useDoubles) {
@@ -740,10 +760,8 @@ TclNewArithSeriesObj(
* so simply check the end of it and behave like [expr {Inf - Inf}] */
double d = dstart + (double)(len - 1) * dstep;
if (isnan(d)) {
const char *s = "domain error: argument not in valid range";
Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, (char *)NULL);
return NULL;
description = "domain error: argument not in valid range";
goto domain;
}
if (precision == (unsigned)-1) {
@@ -755,7 +773,31 @@ TclNewArithSeriesObj(
objPtr = NewArithSeriesInt(start, step, len);
}
if (objPtr == NULL && interp) {
description = "invalid arithmetic series parameter values";
goto domain;
}
return objPtr;
exceeded:
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"max length of a Tcl list exceeded", TCL_AUTO_LENGTH));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
return NULL;
domain:
Tcl_SetObjResult(interp, Tcl_NewStringObj(description, TCL_AUTO_LENGTH));
Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description, (char *)NULL);
return NULL;
notANumber:
description = "non-numeric floating-point value";
Tcl_PrintDouble(NULL, isnan(dstart) ? dstart : dend, tmp);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"cannot use %s \"%s\" to estimate length of arith-series",
description, tmp));
Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description, (char *)NULL);
return NULL;
}
/*
@@ -1147,11 +1189,11 @@ UpdateStringOfArithSeries(
{
ArithSeries *arithSeriesRepPtr = (ArithSeries *)
arithSeriesObjPtr->internalRep.twoPtrValue.ptr1;
char *p;
char *p, *srep;
Tcl_Size i, bytlen = 0;
if (!arithSeriesRepPtr->len) {
TclInitEmptyStringRep(arithSeriesObjPtr);
if (arithSeriesRepPtr->len == 0) {
(void)Tcl_InitStringRep(arithSeriesObjPtr, NULL, 0);
return;
}
@@ -1169,15 +1211,15 @@ UpdateStringOfArithSeries(
char tmp[TCL_DOUBLE_SPACE + 2];
for (i = 0; i < arithSeriesRepPtr->len; i++) {
double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i);
Tcl_Size elen;
tmp[0] = '\0';
Tcl_PrintDouble(NULL,d,tmp);
bytlen += strlen(tmp);
if (bytlen > TCL_SIZE_MAX) {
/* overflow, todo: check we could use some representation instead of the panic
* to signal it is too large for string representation, because too heavy */
Tcl_Panic("UpdateStringOfArithSeries: too large to represent");
elen = strlen(tmp);
if (bytlen > TCL_SIZE_MAX - elen) {
goto repTooLarge;
}
bytlen += elen;
}
}
bytlen += arithSeriesRepPtr->len; // Space for each separator
@@ -1186,7 +1228,17 @@ UpdateStringOfArithSeries(
* Pass 2: generate the string repr.
*/
p = Tcl_InitStringRep(arithSeriesObjPtr, NULL, bytlen);
p = srep = TclAttemptInitStringRep(arithSeriesObjPtr, NULL, bytlen);
if (!p) {
repTooLarge:
if (arithSeriesObjPtr->bytes) {
Tcl_Free(arithSeriesObjPtr->bytes);
arithSeriesObjPtr->bytes = 0;
}
arithSeriesObjPtr->length = bytlen;
return;
}
if (!arithSeriesRepPtr->isDouble) {
for (i = 0; i < arithSeriesRepPtr->len; i++) {
Tcl_WideInt d = ArithSeriesIndexInt(arithSeriesRepPtr, i);
@@ -1205,8 +1257,7 @@ UpdateStringOfArithSeries(
*p++ = ' ';
}
}
*(--p) = '\0';
arithSeriesObjPtr->length = p - arithSeriesObjPtr->bytes;
(void) Tcl_InitStringRep(arithSeriesObjPtr, NULL, (--p - srep));
}
/*
+525 -524
View File
File diff suppressed because it is too large Load Diff
+63 -62
View File
@@ -237,7 +237,6 @@ static Tcl_NRPostProc TEOV_RunLeaveTraces;
static Tcl_NRPostProc EvalObjvCore;
static Tcl_NRPostProc Dispatch;
static Tcl_NRPostProc NRPostInvoke;
static Tcl_ObjCmdProc CoroTypeObjCmd;
static Tcl_ObjCmdProc TclNRCoroInjectObjCmd;
static Tcl_ObjCmdProc TclNRCoroProbeObjCmd;
@@ -250,12 +249,10 @@ MODULE_SCOPE const TclStubs tclStubs;
* Magical counts for the number of arguments accepted by a coroutine command
* after particular kinds of [yield].
*/
#define CORO_ACTIVATE_YIELD NULL
#define CORO_ACTIVATE_YIELDM INT2PTR(1)
#define COROUTINE_ARGUMENTS_SINGLE_OPTIONAL (-1)
#define COROUTINE_ARGUMENTS_ARBITRARY (-2)
enum CoroutineArgumentTypes {
COROUTINE_ARGUMENTS_SINGLE_OPTIONAL = -1,
COROUTINE_ARGUMENTS_ARBITRARY = -2
};
/*
* The following structure define the commands in the Tcl core.
@@ -299,7 +296,7 @@ typedef struct {
*/
static int
procObjCmd(
ProcObjCmd(
void *clientData,
Tcl_Interp *interp,
int objc,
@@ -310,7 +307,7 @@ procObjCmd(
static const CmdInfo builtInCmds[] = {
/*
* Commands in the generic core.
* Commands in the generic core. All are safe.
*/
{"append", Tcl_AppendObjCmd, TclCompileAppendCmd, NULL, CMD_IS_SAFE},
@@ -334,26 +331,26 @@ static const CmdInfo builtInCmds[] = {
{"if", Tcl_IfObjCmd, TclCompileIfCmd, TclNRIfObjCmd, CMD_IS_SAFE},
{"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, NULL, CMD_IS_SAFE},
{"join", Tcl_JoinObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE},
{"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE|CMD_COMPILES_EXPANDED},
{"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, NULL, CMD_IS_SAFE},
{"ledit", Tcl_LeditObjCmd, NULL, NULL, CMD_IS_SAFE},
{"ledit", Tcl_LeditObjCmd, TclCompileLeditCmd, NULL, CMD_IS_SAFE},
{"lindex", Tcl_LindexObjCmd, TclCompileLindexCmd, NULL, CMD_IS_SAFE},
{"linsert", Tcl_LinsertObjCmd, TclCompileLinsertCmd, NULL, CMD_IS_SAFE},
{"list", Tcl_ListObjCmd, TclCompileListCmd, NULL, CMD_IS_SAFE|CMD_COMPILES_EXPANDED},
{"llength", Tcl_LlengthObjCmd, TclCompileLlengthCmd, NULL, CMD_IS_SAFE},
{"lmap", Tcl_LmapObjCmd, TclCompileLmapCmd, TclNRLmapCmd, CMD_IS_SAFE},
{"lpop", Tcl_LpopObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lpop", Tcl_LpopObjCmd, TclCompileLpopCmd, NULL, CMD_IS_SAFE},
{"lrange", Tcl_LrangeObjCmd, TclCompileLrangeCmd, NULL, CMD_IS_SAFE},
{"lremove", Tcl_LremoveObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lrepeat", Tcl_LrepeatObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lreplace", Tcl_LreplaceObjCmd, TclCompileLreplaceCmd, NULL, CMD_IS_SAFE},
{"lreverse", Tcl_LreverseObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lsearch", Tcl_LsearchObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lseq", Tcl_LseqObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lseq", Tcl_LseqObjCmd, TclCompileLseqCmd, NULL, CMD_IS_SAFE},
{"lset", Tcl_LsetObjCmd, TclCompileLsetCmd, NULL, CMD_IS_SAFE},
{"lsort", Tcl_LsortObjCmd, NULL, NULL, CMD_IS_SAFE},
{"package", Tcl_PackageObjCmd, NULL, TclNRPackageObjCmd, CMD_IS_SAFE},
{"proc", procObjCmd, NULL, NULL, CMD_IS_SAFE},
{"proc", ProcObjCmd, NULL, NULL, CMD_IS_SAFE},
{"regexp", Tcl_RegexpObjCmd, TclCompileRegexpCmd, NULL, CMD_IS_SAFE},
{"regsub", Tcl_RegsubObjCmd, TclCompileRegsubCmd, NULL, CMD_IS_SAFE},
{"rename", Tcl_RenameObjCmd, NULL, NULL, CMD_IS_SAFE},
@@ -363,17 +360,17 @@ static const CmdInfo builtInCmds[] = {
{"split", Tcl_SplitObjCmd, NULL, NULL, CMD_IS_SAFE},
{"subst", Tcl_SubstObjCmd, TclCompileSubstCmd, TclNRSubstObjCmd, CMD_IS_SAFE},
{"switch", Tcl_SwitchObjCmd, TclCompileSwitchCmd, TclNRSwitchObjCmd, CMD_IS_SAFE},
{"tailcall", NULL, TclCompileTailcallCmd, TclNRTailcallObjCmd, CMD_IS_SAFE},
{"tailcall", NULL, TclCompileTailcallCmd, TclNRTailcallObjCmd, CMD_IS_SAFE|CMD_COMPILES_EXPANDED},
{"throw", Tcl_ThrowObjCmd, TclCompileThrowCmd, NULL, CMD_IS_SAFE},
{"trace", Tcl_TraceObjCmd, NULL, NULL, CMD_IS_SAFE},
{"try", Tcl_TryObjCmd, TclCompileTryCmd, TclNRTryObjCmd, CMD_IS_SAFE},
{"unset", Tcl_UnsetObjCmd, TclCompileUnsetCmd, NULL, CMD_IS_SAFE},
{"uplevel", Tcl_UplevelObjCmd, NULL, TclNRUplevelObjCmd, CMD_IS_SAFE},
{"uplevel", Tcl_UplevelObjCmd, TclCompileUplevelCmd, TclNRUplevelObjCmd, CMD_IS_SAFE},
{"upvar", Tcl_UpvarObjCmd, TclCompileUpvarCmd, NULL, CMD_IS_SAFE},
{"variable", Tcl_VariableObjCmd, TclCompileVariableCmd, NULL, CMD_IS_SAFE},
{"while", Tcl_WhileObjCmd, TclCompileWhileCmd, TclNRWhileObjCmd, CMD_IS_SAFE},
{"yield", NULL, TclCompileYieldCmd, TclNRYieldObjCmd, CMD_IS_SAFE},
{"yieldto", NULL, TclCompileYieldToCmd, TclNRYieldToObjCmd, CMD_IS_SAFE},
{"yieldto", NULL, TclCompileYieldToCmd, TclNRYieldToObjCmd, CMD_IS_SAFE|CMD_COMPILES_EXPANDED},
/*
* Commands in the OS-interface. Note that many of these are unsafe.
@@ -650,7 +647,7 @@ TclFinalizeEvaluation(void)
/*
*----------------------------------------------------------------------
*
* buildInfoObjCmd --
* BuildInfoObjCmd --
*
* Implements tcl::build-info command.
*
@@ -664,7 +661,7 @@ TclFinalizeEvaluation(void)
*/
static int
buildInfoObjCmd2(
BuildInfoObjCmd2(
void *clientData,
Tcl_Interp *interp, /* Current interpreter. */
Tcl_Size objc, /* Number of arguments. */
@@ -731,7 +728,8 @@ buildInfoObjCmd2(
}
return TCL_OK;
case ID_COMPILER:
for (p = strchr(buildData, '.'); p++; p = strchr(p, '.')) {
for (p = strchr(buildData, '.'); p != NULL; p = strchr(p, '.')) {
p++;
/*
* Does the word begin with one of the standard prefixes?
*/
@@ -752,7 +750,8 @@ buildInfoObjCmd2(
break;
default: /* Boolean test for other identifiers' presence */
arg = TclGetStringFromObj(objv[1], &len);
for (p = strchr(buildData, '.'); p++; p = strchr(p, '.')) {
for (p = strchr(buildData, '.'); p != NULL; p = strchr(p, '.')) {
p++;
if (!strncmp(p, arg, len)
&& ((p[len] == '.') || (p[len] == '-') || (p[len] == '\0'))) {
if (p[len] == '-') {
@@ -776,13 +775,13 @@ buildInfoObjCmd2(
}
static int
buildInfoObjCmd(
BuildInfoObjCmd(
void *clientData,
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
return buildInfoObjCmd2(clientData, interp, objc, objv);
return BuildInfoObjCmd2(clientData, interp, objc, objv);
}
/*
@@ -1163,6 +1162,7 @@ Tcl_CreateInterp(void)
TclInitInfoCmd(interp);
TclInitNamespaceCmd(interp);
TclInitStringCmd(interp);
TclInitUnicodeCmd(interp);
TclInitPrefixCmd(interp);
TclInitProcessCmd(interp);
@@ -1325,9 +1325,9 @@ Tcl_CreateInterp(void)
Tcl_PkgProvideEx(interp, "tcl", TCL_PATCH_LEVEL, &tclStubs);
Tcl_CmdInfo info2;
Tcl_Command buildInfoCmd = Tcl_CreateObjCommand(interp, "::tcl::build-info",
buildInfoObjCmd, (void *)version, NULL);
BuildInfoObjCmd, (void *)version, NULL);
Tcl_GetCommandInfoFromToken(buildInfoCmd, &info2);
info2.objProc2 = buildInfoObjCmd2;
info2.objProc2 = BuildInfoObjCmd2;
info2.objClientData2 = (void *)version;
Tcl_SetCommandInfoFromToken(buildInfoCmd, &info2);
@@ -1385,8 +1385,8 @@ TclRegisterCommandTypeName(
int isNew;
hPtr = Tcl_CreateHashEntry(&commandTypeTable,
implementationProc, &isNew);
Tcl_SetHashValue(hPtr, (void *) nameStr);
(void *)implementationProc, &isNew);
Tcl_SetHashValue(hPtr, nameStr);
} else {
hPtr = Tcl_FindHashEntry(&commandTypeTable,
implementationProc);
@@ -2724,7 +2724,7 @@ typedef struct {
} CmdWrapperInfo;
static int
cmdWrapperProc(
CmdWrapperProc(
void *clientData,
Tcl_Interp *interp,
int objc,
@@ -2738,7 +2738,7 @@ cmdWrapperProc(
}
static void
cmdWrapperDeleteProc(
CmdWrapperDeleteProc(
void *clientData)
{
CmdWrapperInfo *info = (CmdWrapperInfo *) clientData;
@@ -2774,8 +2774,8 @@ Tcl_CreateObjCommand2(
info->deleteData = clientData;
return Tcl_CreateObjCommand(interp, cmdName,
(proc ? cmdWrapperProc : NULL),
info, cmdWrapperDeleteProc);
(proc ? CmdWrapperProc : NULL),
info, CmdWrapperDeleteProc);
}
Tcl_Command
@@ -3293,7 +3293,7 @@ Tcl_SetCommandInfo(
*/
static int
invokeObj2Command(
InvokeObj2Command(
void *clientData, /* Points to command's Command structure. */
Tcl_Interp *interp, /* Current interpreter. */
Tcl_Size objc, /* Number of arguments. */
@@ -3315,7 +3315,7 @@ invokeObj2Command(
}
static int
cmdWrapper2Proc(
CmdWrapper2Proc(
void *clientData,
Tcl_Interp *interp,
Tcl_Size objc,
@@ -3357,10 +3357,10 @@ Tcl_SetCommandInfoFromToken(
}
cmdPtr->objClientData = infoPtr->objClientData;
}
if (cmdPtr->deleteProc == cmdWrapperDeleteProc) {
if (cmdPtr->deleteProc == CmdWrapperDeleteProc) {
CmdWrapperInfo *info = (CmdWrapperInfo *) cmdPtr->deleteData;
if (infoPtr->objProc2 == NULL) {
info->proc = invokeObj2Command;
info->proc = InvokeObj2Command;
info->clientData = cmdPtr;
info->nreProc = NULL;
} else {
@@ -3373,14 +3373,14 @@ Tcl_SetCommandInfoFromToken(
info->deleteProc = infoPtr->deleteProc;
info->deleteData = infoPtr->deleteData;
} else {
if ((infoPtr->objProc2 != NULL) && (infoPtr->objProc2 != cmdWrapper2Proc)) {
if ((infoPtr->objProc2 != NULL) && (infoPtr->objProc2 != CmdWrapper2Proc)) {
CmdWrapperInfo *info = (CmdWrapperInfo *)Tcl_Alloc(sizeof(CmdWrapperInfo));
info->proc = infoPtr->objProc2;
info->clientData = infoPtr->objClientData2;
info->nreProc = NULL;
info->deleteProc = infoPtr->deleteProc;
info->deleteData = infoPtr->deleteData;
cmdPtr->deleteProc = cmdWrapperDeleteProc;
cmdPtr->deleteProc = CmdWrapperDeleteProc;
cmdPtr->deleteData = info;
} else {
cmdPtr->deleteProc = infoPtr->deleteProc;
@@ -3464,19 +3464,19 @@ Tcl_GetCommandInfoFromToken(
infoPtr->objClientData = cmdPtr->objClientData;
infoPtr->proc = cmdPtr->proc;
infoPtr->clientData = cmdPtr->clientData;
if (cmdPtr->deleteProc == cmdWrapperDeleteProc) {
if (cmdPtr->deleteProc == CmdWrapperDeleteProc) {
CmdWrapperInfo *info = (CmdWrapperInfo *)cmdPtr->deleteData;
infoPtr->deleteProc = info->deleteProc;
infoPtr->deleteData = info->deleteData;
infoPtr->objProc2 = info->proc;
infoPtr->objClientData2 = info->clientData;
if (cmdPtr->objProc == cmdWrapperProc) {
if (cmdPtr->objProc == CmdWrapperProc) {
infoPtr->isNativeObjectProc = 2;
}
} else {
infoPtr->deleteProc = cmdPtr->deleteProc;
infoPtr->deleteData = cmdPtr->deleteData;
infoPtr->objProc2 = cmdWrapper2Proc;
infoPtr->objProc2 = CmdWrapper2Proc;
infoPtr->objClientData2 = cmdPtr;
}
infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;
@@ -4619,7 +4619,8 @@ Dispatch(
}
if (TCL_DTRACE_CMD_INFO_ENABLED() && iPtr->cmdFramePtr) {
Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr);
const char *a[6]; Tcl_Size i[2];
const char *a[6];
Tcl_Size i[2];
TclDTraceInfo(info, a, i);
TCL_DTRACE_CMD_INFO(a[0], a[1], a[2], a[3], i[0], i[1], a[4], a[5]);
@@ -5574,7 +5575,7 @@ TclEvalEx(
Tcl_LogCommandInfo(interp, script, parsePtr->commandStart,
commandLength);
}
posterror:
posterror:
iPtr->flags &= ~ERR_ALREADY_LOGGED;
/*
@@ -5596,7 +5597,7 @@ TclEvalEx(
}
iPtr->varFramePtr = savedVarFramePtr;
cleanup_return:
cleanup_return:
/*
* TIP #280. Release the local CmdFrame, and its contents.
*/
@@ -6547,7 +6548,7 @@ Tcl_ExprLongObj(
}
resultPtr = Tcl_NewBignumObj(&big);
}
/* FALLTHRU */
TCL_FALLTHROUGH();
case TCL_NUMBER_INT:
case TCL_NUMBER_BIG:
result = TclGetLongFromObj(interp, resultPtr, ptr);
@@ -6739,7 +6740,7 @@ TclNRInvoke(
*/
iPtr->numLevels++;
Tcl_NRAddCallback(interp, NRPostInvoke, NULL, NULL, NULL, NULL);
Tcl_NRAddCallback(interp, TclNRPostInvoke, NULL, NULL, NULL, NULL);
/*
* Normal command resolution of objv[0] isn't going to find cmdPtr.
@@ -6750,8 +6751,8 @@ TclNRInvoke(
return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NORESOLVE, cmdPtr);
}
static int
NRPostInvoke(
int
TclNRPostInvoke(
TCL_UNUSED(void **),
Tcl_Interp *interp,
int result)
@@ -8063,16 +8064,16 @@ DoubleObjClass(
return TCL_ERROR;
}
switch (type) {
case TCL_NUMBER_NAN:
case TCL_NUMBER_NAN:
*fpClsPtr = FP_NAN;
return TCL_OK;
case TCL_NUMBER_DOUBLE:
case TCL_NUMBER_DOUBLE:
d = *((const double *) ptr);
break;
case TCL_NUMBER_INT:
case TCL_NUMBER_INT:
d = (double)*((const Tcl_WideInt *) ptr);
break;
default:
default:
if (Tcl_GetDoubleFromObj(interp, objPtr, &d) != TCL_OK) {
return TCL_ERROR;
}
@@ -8459,7 +8460,7 @@ Tcl_NRCallObjProc(
}
static int
wrapperNRObjProc(
WrapperNRObjProc(
void *clientData,
Tcl_Interp *interp,
int objc,
@@ -8493,7 +8494,7 @@ Tcl_NRCallObjProc2(
info->clientData = clientData;
info->proc = objProc;
TclNRAddCallback(interp, Dispatch, wrapperNRObjProc, info,
TclNRAddCallback(interp, Dispatch, WrapperNRObjProc, info,
INT2PTR(objc), objv);
return TclNRRunCallbacks(interp, TCL_OK, rootPtr);
}
@@ -8527,7 +8528,7 @@ Tcl_NRCallObjProc2(
*/
static int
cmdWrapperNreProc(
CmdWrapperNreProc(
void *clientData,
Tcl_Interp *interp,
int objc,
@@ -8568,9 +8569,9 @@ Tcl_NRCreateCommand2(
info->deleteProc = deleteProc;
info->deleteData = clientData;
return Tcl_NRCreateCommand(interp, cmdName,
(proc ? cmdWrapperProc : NULL),
(nreProc ? cmdWrapperNreProc : NULL),
info, cmdWrapperDeleteProc);
(proc ? CmdWrapperProc : NULL),
(nreProc ? CmdWrapperNreProc : NULL),
info, CmdWrapperDeleteProc);
}
Tcl_Command
@@ -8816,6 +8817,7 @@ TclNRTailcallObjCmd(
listPtr = Tcl_NewListObj(objc, objv);
TclListObjSetElement(NULL, listPtr, 0, TclNewNamespaceObj(nsPtr));
Tcl_IncrRefCount(listPtr);
iPtr->varFramePtr->tailcallPtr = listPtr;
}
@@ -9607,13 +9609,13 @@ TclNRInterpCoroutine(
break;
default:
if (corPtr->nargs + 1 != objc) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("wrong coro nargs; how did we get here? "
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"wrong coro nargs; how did we get here? "
"not implemented!", TCL_INDEX_NONE));
Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL);
return TCL_ERROR;
}
/* fallthrough */
TCL_FALLTHROUGH();
case COROUTINE_ARGUMENTS_ARBITRARY:
if (objc > 1) {
Tcl_SetObjResult(interp, Tcl_NewListObj(objc - 1, objv + 1));
@@ -9707,11 +9709,10 @@ TclNRCoroutineObjCmd(
for (hePtr = Tcl_FirstHashEntry(iPtr->lineLABCPtr,&hSearch);
hePtr; hePtr = Tcl_NextHashEntry(&hSearch)) {
int isNew;
Tcl_HashEntry *newPtr =
Tcl_CreateHashEntry(corPtr->lineLABCPtr,
Tcl_GetHashKey(iPtr->lineLABCPtr, hePtr),
&isNew);
NULL);
Tcl_SetHashValue(newPtr, Tcl_GetHashValue(hePtr));
}
+47 -44
View File
@@ -384,7 +384,7 @@ Tcl_GetBytesFromObj(
return baPtr->bytes;
}
#if !defined(TCL_NO_DEPRECATED)
#ifndef TCL_NO_DEPRECATED
unsigned char *
TclGetBytesFromObj(
Tcl_Interp *interp, /* For error reporting */
@@ -770,12 +770,9 @@ TclAppendBytesToByteArray(
needed = byteArrayPtr->used + len;
if (needed > byteArrayPtr->allocated) {
Tcl_Size newCapacity;
byteArrayPtr =
(ByteArray *)TclReallocElemsEx(byteArrayPtr,
needed,
1,
offsetof(ByteArray, bytes),
&newCapacity);
byteArrayPtr = (ByteArray *)
TclReallocElemsEx(byteArrayPtr, needed, 1,
offsetof(ByteArray, bytes), &newCapacity);
byteArrayPtr->allocated = newCapacity;
SET_BYTEARRAY(irPtr, byteArrayPtr);
}
@@ -1296,22 +1293,22 @@ BinaryFormatCmd(
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
badValue:
badValue:
Tcl_ResetResult(interp);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected %s string but got \"%s\" instead",
errorString, errorValue));
return TCL_ERROR;
badCount:
badCount:
errorString = "missing count for \"@\" field specifier";
goto error;
badIndex:
badIndex:
errorString = "not enough arguments for all format specifiers";
goto error;
badField:
badField:
{
Tcl_UniChar ch = 0;
char buf[5] = "";
@@ -1323,7 +1320,7 @@ BinaryFormatCmd(
return TCL_ERROR;
}
error:
error:
Tcl_SetObjResult(interp, Tcl_NewStringObj(errorString, -1));
return TCL_ERROR;
}
@@ -1678,21 +1675,21 @@ BinaryScanCmd(
* Set the result to the last position of the cursor.
*/
done:
done:
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(arg - 3));
DeleteScanNumberCache(numberCachePtr);
return TCL_OK;
badCount:
badCount:
errorString = "missing count for \"@\" field specifier";
goto error;
badIndex:
badIndex:
errorString = "not enough arguments for all format specifiers";
goto error;
badField:
badField:
{
Tcl_UniChar ch = 0;
char buf[5] = "";
@@ -1704,7 +1701,7 @@ BinaryScanCmd(
return TCL_ERROR;
}
error:
error:
Tcl_SetObjResult(interp, Tcl_NewStringObj(errorString, -1));
return TCL_ERROR;
}
@@ -2505,6 +2502,8 @@ BinaryDecodeHex(
case OPT_STRICT:
strict = 1;
break;
default:
TCL_UNREACHABLE();
}
}
@@ -2649,6 +2648,8 @@ BinaryEncode64(
wrapchar = TclGetStringFromObj(objv[i + 1], &wrapcharlen);
}
break;
default:
TCL_UNREACHABLE();
}
}
if (wrapcharlen == 0) {
@@ -2736,13 +2737,13 @@ BinaryEncodeUu(
{
Tcl_Obj *resultObj;
unsigned char *data, *start, *cursor;
int i, bits, index;
int i, bits;
unsigned int n;
int lineLength = 61;
const unsigned char SingleNewline[] = { UCHAR('\n') };
const unsigned char *wrapchar = SingleNewline;
Tcl_Size j, rawLength, offset, count = 0, wrapcharlen = sizeof(SingleNewline);
enum { OPT_MAXLEN, OPT_WRAPCHAR };
enum { OPT_MAXLEN, OPT_WRAPCHAR } index;
static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL };
if (objc < 2 || objc % 2 != 0) {
@@ -2773,35 +2774,33 @@ BinaryEncodeUu(
case OPT_WRAPCHAR:
wrapchar = (const unsigned char *)TclGetStringFromObj(
objv[i + 1], &wrapcharlen);
{
const unsigned char *p = wrapchar;
Tcl_Size numBytes = wrapcharlen;
const unsigned char *p = wrapchar;
Tcl_Size numBytes = wrapcharlen;
while (numBytes) {
switch (*p) {
case '\t':
case '\v':
case '\f':
case '\r':
p++; numBytes--;
continue;
case '\n':
numBytes--;
break;
default:
badwrap:
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"invalid wrapchar; will defeat decoding",
-1));
Tcl_SetErrorCode(interp, "TCL", "BINARY",
"ENCODE", "WRAPCHAR", (char *)NULL);
return TCL_ERROR;
}
}
if (numBytes) {
while (numBytes) {
switch (*p) {
case '\t':
case '\v':
case '\f':
case '\r':
p++;
numBytes--;
continue;
case '\n':
numBytes--;
break;
default:
goto badwrap;
}
}
if (numBytes) {
badwrap:
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"invalid wrapchar; will defeat decoding", -1));
Tcl_SetErrorCode(interp, "TCL", "BINARY",
"ENCODE", "WRAPCHAR", (char *)NULL);
return TCL_ERROR;
}
break;
}
}
@@ -2909,6 +2908,8 @@ BinaryDecodeUu(
case OPT_STRICT:
strict = 1;
break;
default:
TCL_UNREACHABLE();
}
}
@@ -3084,6 +3085,8 @@ BinaryDecode64(
case OPT_STRICT:
strict = 1;
break;
default:
TCL_UNREACHABLE();
}
}
+8 -9
View File
@@ -812,7 +812,8 @@ MemoryCmd(
return TCL_ERROR;
}
if (strcmp(TclGetString(objv[1]), "active") == 0 || strcmp(TclGetString(objv[1]), "display") == 0) {
if (strcmp(TclGetString(objv[1]), "active") == 0 ||
strcmp(TclGetString(objv[1]), "display") == 0) {
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "file");
return TCL_ERROR;
@@ -1256,12 +1257,11 @@ TclAllocElemsEx(
* non-NULL. Only modified on success */
{
void *ptr = TclAttemptReallocElemsEx(
NULL, elemCount, elemSize, leadSize, capacityPtr);
NULL, elemCount, elemSize, leadSize, capacityPtr);
if (ptr == NULL) {
Tcl_Panic("Failed to allocate %" TCL_SIZE_MODIFIER
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
elemCount,
elemSize);
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
elemCount, elemSize);
}
return ptr;
}
@@ -1362,12 +1362,11 @@ TclReallocElemsEx(
* non-NULL. Only modified on success */
{
void *ptr = TclAttemptReallocElemsEx(
oldPtr, elemCount, elemSize, leadSize, capacityPtr);
oldPtr, elemCount, elemSize, leadSize, capacityPtr);
if (ptr == NULL) {
Tcl_Panic("Failed to reallocate %" TCL_SIZE_MODIFIER
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
elemCount,
elemSize);
"d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
elemCount, elemSize);
}
return ptr;
}
+22 -9
View File
@@ -129,10 +129,10 @@ static const struct ClockCommand clockCommands[] = {
{"clicks", ClockClicksObjCmd, TclCompileClockClicksCmd, NULL},
{"format", ClockFormatObjCmd, TclCompileBasicMin1ArgCmd, NULL},
{"getenv", ClockGetenvObjCmd, TclCompileBasicMin1ArgCmd, NULL},
{"microseconds", ClockMicrosecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(1)},
{"milliseconds", ClockMillisecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(2)},
{"microseconds", ClockMicrosecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(CLOCK_READ_MICROS)},
{"milliseconds", ClockMillisecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(CLOCK_READ_MILLIS)},
{"scan", ClockScanObjCmd, TclCompileBasicMin1ArgCmd, NULL},
{"seconds", ClockSecondsObjCmd, TclCompileClockReadingCmd, INT2PTR(3)},
{"seconds", ClockSecondsObjCmd, TclCompileClockReadingCmd, INT2PTR(CLOCK_READ_SECS)},
{"ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd, NULL, NULL},
{"GetDateFields", ClockGetdatefieldsObjCmd, NULL, NULL},
{"GetJulianDayFromEraYearMonthDay",
@@ -988,7 +988,11 @@ ClockConfigureObjCmd(
TclSetObjRef(dataPtr->systemTimeZone, objv[i]);
TclUnsetObjRef(dataPtr->systemSetupTZData);
}
dataPtr->lastTZEpoch = lastTZEpoch;
if (dataPtr->lastTZEpoch != lastTZEpoch) {
dataPtr->lastTZEpoch = lastTZEpoch;
/* TZ epoch changed - invalidate base-cache */
TclUnsetObjRef(dataPtr->lastBase.timezoneObj);
}
}
if (i + 1 >= objc && dataPtr->systemTimeZone != NULL
&& dataPtr->lastTZEpoch == lastTZEpoch) {
@@ -1154,6 +1158,8 @@ ClockConfigureObjCmd(
}
break;
}
default:
TCL_UNREACHABLE();
}
}
@@ -3159,6 +3165,8 @@ ClockClicksObjCmd(
case CLICKS_MICROS:
clicks = TclpGetMicroseconds();
break;
default:
TCL_UNREACHABLE();
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(clicks));
@@ -3371,6 +3379,8 @@ ClockParseFmtScnArgs(
}
}
break;
default:
TCL_UNREACHABLE();
}
saw |= 1 << optionIndex;
}
@@ -3431,8 +3441,8 @@ ClockParseFmtScnArgs(
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad seconds \"%s\": must be now or integer",
TclGetString(baseObj)));
"bad seconds \"%s\": must be now or integer",
TclGetString(baseObj)));
i = baseIdx;
goto badOption;
}
@@ -3474,7 +3484,7 @@ ClockParseFmtScnArgs(
/* extact fields from base */
date->seconds = baseVal;
if (ClockGetDateFields(dataPtr, interp, date, opts->timezoneObj,
GREGORIAN_CHANGE_DATE) != TCL_OK) {
GREGORIAN_CHANGE_DATE) != TCL_OK) {
/* TODO - GREGORIAN_CHANGE_DATE should be locale-dependent */
return TCL_ERROR;
}
@@ -3624,7 +3634,8 @@ ClockScanObjCmd(
}
/* seconds are in localSeconds (relative base date), so reset time here */
yyHour = yyMinutes = yySeconds = yySecondOfDay = 0; yyMeridian = MER24;
yyHour = yyMinutes = yySeconds = yySecondOfDay = 0;
yyMeridian = MER24;
/* If free scan */
if (opts.formatObj == NULL) {
@@ -4265,7 +4276,7 @@ ClockCalcRelTime(
yyRelSeconds = 0;
/* Convert it back */
if (ClockGetDateFields(opts->dataPtr, opts->interp, &yydate,
opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) {
opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) {
/* TODO - GREGORIAN_CHANGE_DATE should be locale-dependent */
return TCL_ERROR;
}
@@ -4537,6 +4548,8 @@ ClockAddObjCmd(
case CLC_ADD_SECONDS:
yyRelSeconds += offs;
break;
default:
TCL_UNREACHABLE();
}
if (unitIndex < CLC_ADD_HOURS) { /* date units only */
info->flags |= CLF_RELCONV;
+43 -30
View File
@@ -565,7 +565,10 @@ ClockFmtScnStorageAllocProc(
allocsize -= sizeof(hPtr->key);
}
fss = (ClockFmtScnStorage *)Tcl_Alloc(allocsize);
fss = (ClockFmtScnStorage *)Tcl_AttemptAlloc(allocsize);
if (!fss) {
return NULL;
}
/* initialize */
memset(fss, 0, sizeof(*fss));
@@ -841,7 +844,7 @@ FindOrCreateFmtScnStorage(
}
/* get or create entry (and alocate storage) */
hPtr = Tcl_CreateHashEntry(&FmtScnHashTable, strFmt, &isNew);
hPtr = Tcl_AttemptCreateHashEntry(&FmtScnHashTable, strFmt, &isNew);
if (hPtr != NULL) {
fss = FmtScn4HashEntry(hPtr);
@@ -1024,7 +1027,7 @@ static const char *
FindTokenBegin(
const char *p,
const char *end,
ClockScanToken *tok,
const ClockScanToken *tok,
int flags)
{
if (p < end) {
@@ -1037,10 +1040,14 @@ FindTokenBegin(
if (!(flags & CLF_STRICT)) {
/* should match at least one digit or space */
while (!isdigit(UCHAR(*p)) && !isspace(UCHAR(*p)) &&
(p = Tcl_UtfNext(p)) < end) {}
(p = Tcl_UtfNext(p)) < end) {
// Empty
}
} else {
/* should match at least one digit */
while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {}
while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {
// Empty
}
}
return p;
@@ -1049,19 +1056,25 @@ FindTokenBegin(
goto findChar;
case CTOKT_SPACE:
while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {}
while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {
// Empty
}
return p;
case CTOKT_CHAR:
c = *((char *)tok->map->data);
findChar:
findChar:
if (!(flags & CLF_STRICT)) {
/* should match the char or space */
while (*p != c && !isspace(UCHAR(*p)) &&
(p = Tcl_UtfNext(p)) < end) {}
(p = Tcl_UtfNext(p)) < end) {
// Empty
}
} else {
/* should match the char */
while (*p != c && (p = Tcl_UtfNext(p)) < end) {}
while (*p != c && (p = Tcl_UtfNext(p)) < end) {
// Empty
}
}
return p;
}
@@ -1089,7 +1102,7 @@ static void
DetermineGreedySearchLen(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok,
const ClockScanToken *tok,
int *minLenPtr,
int *maxLenPtr)
{
@@ -1141,7 +1154,7 @@ DetermineGreedySearchLen(
/* try to get max length more precise for greedy match,
* check the next ahead token available there */
if (minLen < maxLen && tok->lookAhTok) {
ClockScanToken *laTok = tok + tok->lookAhTok + 1;
const ClockScanToken *laTok = tok + tok->lookAhTok + 1;
p = yyInput + maxLen;
/* regards all possible spaces here (because they are optional) */
@@ -1155,7 +1168,7 @@ DetermineGreedySearchLen(
/* try to find laTok between [lookAhMin, lookAhMax] */
while (minLen < maxLen) {
const char *f = FindTokenBegin(p, end, laTok,
TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT);
TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT);
/* if found (not below lookAhMax) */
if (f < end) {
break;
@@ -1491,7 +1504,7 @@ StaticListSearch(
static inline const char *
FindWordEnd(
ClockScanToken *tok,
const ClockScanToken *tok,
const char *p,
const char *end)
{
@@ -1516,7 +1529,7 @@ static int
ClockScnToken_Month_Proc(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok)
const ClockScanToken *tok)
{
#if 0
/* currently unused, test purposes only */
@@ -1566,7 +1579,7 @@ static int
ClockScnToken_DayOfWeek_Proc(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok)
const ClockScanToken *tok)
{
static int dowKeys[] = {MCLIT_DAYS_OF_WEEK_ABBREV, MCLIT_DAYS_OF_WEEK_FULL, 0};
@@ -1640,7 +1653,7 @@ static int
ClockScnToken_amPmInd_Proc(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok)
const ClockScanToken *tok)
{
int ret, val;
int minLen, maxLen;
@@ -1673,7 +1686,7 @@ static int
ClockScnToken_LocaleERA_Proc(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok)
const ClockScanToken *tok)
{
ClockClientData *dataPtr = opts->dataPtr;
@@ -1712,7 +1725,7 @@ static int
ClockScnToken_LocaleListMatcher_Proc(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok)
const ClockScanToken *tok)
{
int ret, val;
int minLen, maxLen;
@@ -1743,7 +1756,7 @@ static int
ClockScnToken_JDN_Proc(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok)
const ClockScanToken *tok)
{
int minLen, maxLen;
const char *p = yyInput, *end, *s;
@@ -1814,7 +1827,7 @@ static int
ClockScnToken_TimeZone_Proc(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok)
const ClockScanToken *tok)
{
int minLen, maxLen;
int len = 0;
@@ -1906,7 +1919,7 @@ static int
ClockScnToken_StarDate_Proc(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok)
const ClockScanToken *tok)
{
int minLen, maxLen;
const char *p = yyInput, *end, *s;
@@ -2300,8 +2313,7 @@ ClockGetOrParseScanFormat(
tokCnt++;
continue;
}
word_tok:
{
word_tok: {
/* try continue with previous word token */
ClockScanToken *wordTok = tok - 1;
@@ -2324,9 +2336,9 @@ ClockGetOrParseScanFormat(
AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *);
tokCnt++;
}
}
break;
}
}
}
/* calculate end distance value for each tokens */
@@ -2373,8 +2385,8 @@ ClockScan(
ClockFmtScnCmdArgs *opts) /* Command options */
{
ClockClientData *dataPtr = opts->dataPtr;
ClockFmtScnStorage *fss;
ClockScanToken *tok;
const ClockFmtScnStorage *fss;
const ClockScanToken *tok;
const ClockScanTokenMap *map;
const char *p, *x, *end;
unsigned short flags = 0;
@@ -2554,6 +2566,8 @@ ClockScan(
}
p++;
break;
default:
TCL_UNREACHABLE();
}
}
/* check end was reached */
@@ -2602,7 +2616,7 @@ ClockScan(
case (CLF_DAYOFYEAR | CLF_DAYOFMONTH):
/* miss month: ddd over dd (without month) */
flags &= ~CLF_DAYOFMONTH;
/* fallthrough */
TCL_FALLTHROUGH();
case CLF_DAYOFYEAR:
/* ddd over naked weekday */
if (!(flags & CLF_ISO8601YEAR)) {
@@ -3343,8 +3357,7 @@ ClockGetOrParseFmtFormat(
continue;
}
default:
word_tok:
{
word_tok: {
/* try continue with previous word token */
ClockFormatToken *wordTok = tok - 1;
@@ -3363,9 +3376,9 @@ ClockGetOrParseFmtFormat(
AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *);
tokCnt++;
}
}
break;
}
}
}
/* correct count of real used tokens and free mem if desired
+101 -65
View File
@@ -53,6 +53,7 @@ static Tcl_ObjCmdProc EncodingDirsObjCmd;
static Tcl_ObjCmdProc EncodingNamesObjCmd;
static Tcl_ObjCmdProc EncodingProfilesObjCmd;
static Tcl_ObjCmdProc EncodingSystemObjCmd;
static Tcl_ObjCmdProc EncodingUserObjCmd;
static inline int ForeachAssignments(Tcl_Interp *interp,
struct ForeachState *statePtr);
static inline void ForeachCleanup(Tcl_Interp *interp,
@@ -394,6 +395,7 @@ TclInitEncodingCmd(
{"names", EncodingNamesObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
{"profiles", EncodingProfilesObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0},
{"system", EncodingSystemObjCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 1},
{"user", EncodingUserObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 1},
{NULL, NULL, NULL, NULL, NULL, 0}
};
@@ -483,6 +485,8 @@ EncodingConvertParseOptions(
case FAILINDEX:
failVarObj = objv[argIndex];
break;
default:
TCL_UNREACHABLE();
}
}
/* Get encoding after opts so no need to free it on option error */
@@ -547,14 +551,14 @@ EncodingConvertfromObjCmd(
result = Tcl_ExternalToUtfDStringEx(interp, encoding, bytesPtr, length, flags,
&ds, failVarObj ? &errorLocation : NULL);
/* NOTE: ds must be freed beyond this point even on error */
switch (result) {
case TCL_OK:
errorLocation = TCL_INDEX_NONE;
break;
case TCL_ERROR:
/* Error in parameters. Should not happen. interp will have error */
Tcl_DStringFree(&ds);
return TCL_ERROR;
goto done;
default:
/*
* One of the TCL_CONVERT_* errors. If we were not interested in the
@@ -563,8 +567,8 @@ EncodingConvertfromObjCmd(
* what could be decoded and the returned error location.
*/
if (failVarObj == NULL) {
Tcl_DStringFree(&ds);
return TCL_ERROR;
result = TCL_ERROR;
goto done;
}
break;
}
@@ -578,8 +582,8 @@ EncodingConvertfromObjCmd(
TclNewIndexObj(failIndex, errorLocation);
if (Tcl_ObjSetVar2(interp, failVarObj, NULL, failIndex,
TCL_LEAVE_ERR_MSG) == NULL) {
Tcl_DStringFree(&ds);
return TCL_ERROR;
result = TCL_ERROR;
goto done;
}
}
/*
@@ -588,11 +592,14 @@ EncodingConvertfromObjCmd(
*/
Tcl_SetObjResult(interp, Tcl_DStringToObj(&ds));
result = TCL_OK;
/* We're done with the encoding */
Tcl_FreeEncoding(encoding);
return TCL_OK;
done:
Tcl_DStringFree(&ds);
if (encoding) {
Tcl_FreeEncoding(encoding);
}
return result;
}
/*
@@ -646,8 +653,7 @@ EncodingConverttoObjCmd(
break;
case TCL_ERROR:
/* Error in parameters. Should not happen. interp will have error */
Tcl_DStringFree(&ds);
return TCL_ERROR;
goto done;
default:
/*
* One of the TCL_CONVERT_* errors. If we were not interested in the
@@ -656,8 +662,8 @@ EncodingConverttoObjCmd(
* what could be decoded and the returned error location.
*/
if (failVarObj == NULL) {
Tcl_DStringFree(&ds);
return TCL_ERROR;
result = TCL_ERROR;
goto done;
}
break;
}
@@ -671,20 +677,23 @@ EncodingConverttoObjCmd(
TclNewIndexObj(failIndex, errorLocation);
if (Tcl_ObjSetVar2(interp, failVarObj, NULL, failIndex,
TCL_LEAVE_ERR_MSG) == NULL) {
Tcl_DStringFree(&ds);
return TCL_ERROR;
result = TCL_ERROR;
goto done;
}
}
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
(unsigned char*) Tcl_DStringValue(&ds),
Tcl_DStringLength(&ds)));
result = TCL_OK;
done:
Tcl_DStringFree(&ds);
/* We're done with the encoding */
Tcl_FreeEncoding(encoding);
return TCL_OK;
if (encoding) {
Tcl_FreeEncoding(encoding);
}
return result;
}
/*
@@ -826,6 +835,36 @@ EncodingSystemObjCmd(
return TCL_OK;
}
/*
*-----------------------------------------------------------------------------
*
* EncodingUserObjCmd --
*
* This command retrieves the encoding as per the user settings.
*
* Results:
* Returns a standard Tcl result
*
*-----------------------------------------------------------------------------
*/
int
EncodingUserObjCmd(
TCL_UNUSED(void *),
Tcl_Interp* interp, /* Tcl interpreter */
int objc, /* Number of command line args */
Tcl_Obj* const objv[]) /* Vector of command line args */
{
if (objc > 1) {
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
Tcl_DString ds;
Tcl_GetEncodingNameForUser(&ds);
Tcl_DStringResult(interp, &ds);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
@@ -2118,8 +2157,7 @@ PathTypeCmd(
TclNewLiteralStringObj(typeName, "volumerelative");
break;
default:
/* Should be unreachable */
return TCL_OK;
TCL_UNREACHABLE();
}
Tcl_SetObjResult(interp, typeName);
return TCL_OK;
@@ -2339,34 +2377,30 @@ StoreStatData(
* store in varName. */
{
Tcl_Obj *field, *value, *result;
unsigned short mode;
unsigned short modeVal = (unsigned short) statPtr->st_mode;
if (varName == NULL) {
TclNewObj(result);
Tcl_IncrRefCount(result);
#define DOBJPUT(key, objValue) \
Tcl_DictObjPut(NULL, result, \
Tcl_NewStringObj((key), -1), \
(objValue));
DOBJPUT("dev", Tcl_NewWideIntObj((long)statPtr->st_dev));
DOBJPUT("ino", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino));
DOBJPUT("nlink", Tcl_NewWideIntObj((long)statPtr->st_nlink));
DOBJPUT("uid", Tcl_NewWideIntObj((long)statPtr->st_uid));
DOBJPUT("gid", Tcl_NewWideIntObj((long)statPtr->st_gid));
DOBJPUT("size", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
#define D_PUT(key, objValue) TclDictPut(NULL, result, #key, (objValue))
D_PUT(dev, Tcl_NewWideIntObj((long)statPtr->st_dev));
D_PUT(ino, Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino));
D_PUT(nlink, Tcl_NewWideIntObj((long)statPtr->st_nlink));
D_PUT(uid, Tcl_NewWideIntObj((long)statPtr->st_uid));
D_PUT(gid, Tcl_NewWideIntObj((long)statPtr->st_gid));
D_PUT(size, Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
DOBJPUT("blocks", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
D_PUT(blocks, Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
DOBJPUT("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
D_PUT(blksize, Tcl_NewWideIntObj((long)statPtr->st_blksize));
#endif
DOBJPUT("atime", Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
DOBJPUT("mtime", Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr)));
DOBJPUT("ctime", Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
mode = (unsigned short) statPtr->st_mode;
DOBJPUT("mode", Tcl_NewWideIntObj(mode));
DOBJPUT("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1));
#undef DOBJPUT
D_PUT(atime, Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
D_PUT(mtime, Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr)));
D_PUT(ctime, Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
D_PUT(mode, Tcl_NewWideIntObj(modeVal));
D_PUT(type, Tcl_NewStringObj(GetTypeFromMode(modeVal), -1));
#undef D_PUT
Tcl_SetObjResult(interp, result);
Tcl_DecrRefCount(result);
return TCL_OK;
@@ -2379,44 +2413,45 @@ StoreStatData(
*/
#define STORE_ARY(fieldName, object) \
TclNewLiteralStringObj(field, fieldName); \
Tcl_IncrRefCount(field); \
value = (object); \
if (Tcl_ObjSetVar2(interp,varName,field,value,TCL_LEAVE_ERR_MSG)==NULL) { \
do { \
TclNewLiteralStringObj(field, #fieldName); \
Tcl_IncrRefCount(field); \
value = (object); \
if (Tcl_ObjSetVar2(interp, varName, field, value, \
TCL_LEAVE_ERR_MSG) == NULL) { \
TclDecrRefCount(field); \
return TCL_ERROR; \
} \
TclDecrRefCount(field); \
return TCL_ERROR; \
} \
TclDecrRefCount(field);
} while (0)
/*
* Watch out porters; the inode is meant to be an *unsigned* value, so the
* cast might fail when there isn't a real arithmetic 'long long' type...
*/
STORE_ARY("dev", Tcl_NewWideIntObj((long)statPtr->st_dev));
STORE_ARY("ino", Tcl_NewWideIntObj(statPtr->st_ino));
STORE_ARY("nlink", Tcl_NewWideIntObj((long)statPtr->st_nlink));
STORE_ARY("uid", Tcl_NewWideIntObj((long)statPtr->st_uid));
STORE_ARY("gid", Tcl_NewWideIntObj((long)statPtr->st_gid));
STORE_ARY("size", Tcl_NewWideIntObj(statPtr->st_size));
STORE_ARY(dev, Tcl_NewWideIntObj((long)statPtr->st_dev));
STORE_ARY(ino, Tcl_NewWideIntObj(statPtr->st_ino));
STORE_ARY(nlink, Tcl_NewWideIntObj((long)statPtr->st_nlink));
STORE_ARY(uid, Tcl_NewWideIntObj((long)statPtr->st_uid));
STORE_ARY(gid, Tcl_NewWideIntObj((long)statPtr->st_gid));
STORE_ARY(size, Tcl_NewWideIntObj(statPtr->st_size));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
STORE_ARY("blocks", Tcl_NewWideIntObj(statPtr->st_blocks));
STORE_ARY(blocks, Tcl_NewWideIntObj(statPtr->st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
STORE_ARY("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
STORE_ARY(blksize, Tcl_NewWideIntObj((long)statPtr->st_blksize));
#endif
#ifdef HAVE_STRUCT_STAT_ST_RDEV
if (S_ISCHR(statPtr->st_mode) || S_ISBLK(statPtr->st_mode)) {
STORE_ARY("rdev", Tcl_NewWideIntObj((long) statPtr->st_rdev));
}
#endif
STORE_ARY("atime", Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
STORE_ARY("mtime", Tcl_NewWideIntObj(
Tcl_GetModificationTimeFromStat(statPtr)));
STORE_ARY("ctime", Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
mode = (unsigned short) statPtr->st_mode;
STORE_ARY("mode", Tcl_NewWideIntObj(mode));
STORE_ARY("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1));
STORE_ARY(atime, Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
STORE_ARY(mtime, Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr)));
STORE_ARY(ctime, Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
STORE_ARY(mode, Tcl_NewWideIntObj(modeVal));
STORE_ARY(type, Tcl_NewStringObj(GetTypeFromMode(modeVal), -1));
#undef STORE_ARY
return TCL_OK;
@@ -2928,6 +2963,7 @@ ForeachLoopStep(
"\n (\"%s\" body line %d)",
(statePtr->resultList != NULL ? "lmap" : "foreach"),
Tcl_GetErrorLine(interp)));
TCL_FALLTHROUGH();
default:
goto done;
}
+58 -212
View File
@@ -106,7 +106,7 @@ typedef enum {
LSEQ_DOTS, LSEQ_TO, LSEQ_COUNT, LSEQ_BY
} SequenceOperators;
typedef enum {
NoneArg, NumericArg, RangeKeywordArg, ErrArg, LastArg = 8
NoneArg, NumericArg, RangeKeywordArg, ErrArg, LastArg = 8
} SequenceDecoded;
/*
@@ -818,7 +818,7 @@ InfoCommandsCmd(
elemObjPtr = Tcl_NewStringObj(cmdName, -1);
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
(void) Tcl_CreateHashEntry(&addedCommandsTable,
elemObjPtr, &isNew);
elemObjPtr, NULL);
}
entryPtr = Tcl_NextHashEntry(&search);
}
@@ -1304,7 +1304,7 @@ TclInfoFrame(
break;
case TCL_LOCATION_PREBC:
precompiled:
precompiled:
/*
* Precompiled. Result contains the type as signal, nothing else.
*/
@@ -1607,7 +1607,7 @@ InfoLevelCmd(
}
for (framePtr=iPtr->varFramePtr ; framePtr!=rootFramePtr;
framePtr=framePtr->callerVarPtr) {
if ((int)framePtr->level == level) {
if (framePtr->level == level) {
break;
}
}
@@ -2327,22 +2327,14 @@ Tcl_LassignObjCmd(
}
if (listObjc > 0) {
Tcl_Obj *resultObjPtr = NULL;
Tcl_Size fromIdx = origListObjc - listObjc;
Tcl_Size toIdx = origListObjc - 1;
if (TclObjTypeHasProc(listPtr, sliceProc)) {
if (TclObjTypeSlice(
interp, listPtr, fromIdx, toIdx, &resultObjPtr) != TCL_OK) {
return TCL_ERROR;
}
} else {
resultObjPtr = TclListObjRange(
interp, listPtr, origListObjc - listObjc, origListObjc - 1);
if (resultObjPtr == NULL) {
return TCL_ERROR;
}
Tcl_Obj *resultObj = NULL;
Tcl_Size first = origListObjc - listObjc;
Tcl_Size last = origListObjc - 1;
int result = Tcl_ListObjRange(interp, listPtr, first, last, &resultObj);
if (result != TCL_OK) {
return result;
}
Tcl_SetObjResult(interp, resultObjPtr);
Tcl_SetObjResult(interp, resultObj);
}
return TCL_OK;
@@ -2748,22 +2740,12 @@ Tcl_LrangeObjCmd(
return result;
}
if (TclObjTypeHasProc(objv[1], sliceProc)) {
Tcl_Obj *resultObj;
int status = TclObjTypeSlice(interp, objv[1], first, last, &resultObj);
if (status == TCL_OK) {
Tcl_SetObjResult(interp, resultObj);
} else {
return TCL_ERROR;
}
} else {
Tcl_Obj *resultObj = TclListObjRange(interp, objv[1], first, last);
if (resultObj == NULL) {
return TCL_ERROR;
}
Tcl_Obj *resultObj;
result = Tcl_ListObjRange(interp, objv[1], first, last, &resultObj);
if (result == TCL_OK) {
Tcl_SetObjResult(interp, resultObj);
}
return TCL_OK;
return result;
}
/*
@@ -2936,92 +2918,24 @@ Tcl_LrepeatObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* The argument objects. */
{
Tcl_WideInt elementCount, i;
Tcl_Size totalElems;
Tcl_Obj *listPtr, **dataArray = NULL;
/*
* Check arguments for legality:
* lrepeat count ?value ...?
*/
Tcl_Size repeatCount;
Tcl_Obj *resultPtr;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "count ?value ...?");
return TCL_ERROR;
}
if (TCL_OK != TclGetWideIntFromObj(interp, objv[1], &elementCount)) {
return TCL_ERROR;
}
if (elementCount < 0) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad count \"%" TCL_LL_MODIFIER "d\": must be integer >= 0", elementCount));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPEAT", "NEGARG",
(char *)NULL);
if (Tcl_GetSizeIntFromObj(interp, objv[1], &repeatCount) != TCL_OK) {
return TCL_ERROR;
}
/*
* Skip forward to the interesting arguments now we've finished parsing.
*/
objc -= 2;
objv += 2;
/* Final sanity check. Do not exceed limits on max list length. */
if (elementCount && objc > LIST_MAX/elementCount) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"max length of a Tcl list (%" TCL_SIZE_MODIFIER "d elements) exceeded", LIST_MAX));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
if (Tcl_ListObjRepeat(
interp, repeatCount, objc - 2, objv + 2, &resultPtr) != TCL_OK) {
return TCL_ERROR;
}
totalElems = objc * elementCount;
/*
* Get an empty list object that is allocated large enough to hold each
* init value elementCount times.
*/
listPtr = Tcl_NewListObj(totalElems, NULL);
if (totalElems) {
ListRep listRep;
ListObjGetRep(listPtr, &listRep);
dataArray = ListRepElementsBase(&listRep);
listRep.storePtr->numUsed = totalElems;
if (listRep.spanPtr) {
/* Future proofing in case Tcl_NewListObj returns a span */
listRep.spanPtr->spanStart = listRep.storePtr->firstUsed;
listRep.spanPtr->spanLength = listRep.storePtr->numUsed;
}
}
/*
* Set the elements. Note that we handle the common degenerate case of a
* single value being repeated separately to permit the compiler as much
* room as possible to optimize a loop that might be run a very large
* number of times.
*/
CLANG_ASSERT(dataArray || totalElems == 0 );
if (objc == 1) {
Tcl_Obj *tmpPtr = objv[0];
tmpPtr->refCount += elementCount;
for (i=0 ; i<elementCount ; i++) {
dataArray[i] = tmpPtr;
}
} else {
Tcl_Size j, k = 0;
for (i=0 ; i<elementCount ; i++) {
for (j=0 ; j<objc ; j++) {
Tcl_IncrRefCount(objv[j]);
dataArray[k++] = objv[j];
}
}
}
Tcl_SetObjResult(interp, listPtr);
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
@@ -3152,82 +3066,16 @@ Tcl_LreverseObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument values. */
{
Tcl_Obj **elemv;
Tcl_Size elemc, i, j;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "list");
return TCL_ERROR;
}
/*
* Handle AbstractList special case - do not shimmer into a list, if it
* supports a private Reverse function, just to reverse it.
*/
if (TclObjTypeHasProc(objv[1], reverseProc)) {
Tcl_Obj *resultObj;
if (TclObjTypeReverse(interp, objv[1], &resultObj) == TCL_OK) {
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
}
} /* end Abstract List */
if (TclListObjLength(interp, objv[1], &elemc) != TCL_OK) {
Tcl_Obj *resultObj = NULL;
if (Tcl_ListObjReverse(interp, objv[1], &resultObj) != TCL_OK) {
return TCL_ERROR;
}
/*
* If the list is empty, just return it. [Bug 1876793]
*/
if (!elemc) {
Tcl_SetObjResult(interp, objv[1]);
return TCL_OK;
}
if (TclListObjGetElements(interp, objv[1], &elemc, &elemv) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_IsShared(objv[1])
|| ListObjRepIsShared(objv[1])) { /* Bug 1675044 */
Tcl_Obj *resultObj, **dataArray;
ListRep listRep;
resultObj = Tcl_NewListObj(elemc, NULL);
/* Modify the internal rep in-place */
ListObjGetRep(resultObj, &listRep);
listRep.storePtr->numUsed = elemc;
dataArray = ListRepElementsBase(&listRep);
if (listRep.spanPtr) {
/* Future proofing */
listRep.spanPtr->spanStart = listRep.storePtr->firstUsed;
listRep.spanPtr->spanLength = listRep.storePtr->numUsed;
}
for (i=0,j=elemc-1 ; i<elemc ; i++,j--) {
dataArray[j] = elemv[i];
Tcl_IncrRefCount(elemv[i]);
}
Tcl_SetObjResult(interp, resultObj);
} else {
/*
* Not shared, so swap "in place". This relies on Tcl_LOGE above
* returning a pointer to the live array of Tcl_Obj values.
*/
for (i=0,j=elemc-1 ; i<j ; i++,j--) {
Tcl_Obj *tmp = elemv[i];
elemv[i] = elemv[j];
elemv[j] = tmp;
}
TclInvalidateStringRep(objv[1]);
Tcl_SetObjResult(interp, objv[1]);
}
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
}
@@ -3504,6 +3352,8 @@ Tcl_LsearchObjCmd(
}
break;
}
default:
TCL_UNREACHABLE();
}
}
@@ -3924,7 +3774,7 @@ Tcl_LsearchObjCmd(
} else if (returnSubindices && (sortInfo.indexc == 0) && (groupSize > 1)) {
Tcl_BounceRefCount(itemPtr);
itemPtr = listv[i + groupOffset];
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
} else if (groupSize > 1) {
Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0,
groupSize, &listv[i]);
@@ -3972,8 +3822,8 @@ Tcl_LsearchObjCmd(
}
Tcl_SetObjResult(interp, itemPtr);
} else {
Tcl_Obj *elObj;
TclNewIndexObj(elObj, index);
Tcl_Obj *elObj;
TclNewIndexObj(elObj, index);
Tcl_SetObjResult(interp, elObj);
}
} else if (index < 0) {
@@ -4032,11 +3882,11 @@ Tcl_LsearchObjCmd(
static SequenceDecoded
SequenceIdentifyArgument(
Tcl_Interp *interp, /* for error reporting */
Tcl_Obj *argPtr, /* Argument to decode */
int allowedArgs, /* Flags if keyword or numeric allowed. */
Tcl_Obj **numValuePtr, /* Return numeric value */
int *keywordIndexPtr) /* Return keyword enum */
Tcl_Interp *interp, /* for error reporting */
Tcl_Obj *argPtr, /* Argument to decode */
int allowedArgs, /* Flags if keyword or numeric allowed. */
Tcl_Obj **numValuePtr, /* Return numeric value */
int *keywordIndexPtr) /* Return keyword enum */
{
int result = TCL_ERROR;
SequenceOperators opmode;
@@ -4045,7 +3895,7 @@ SequenceIdentifyArgument(
if (allowedArgs & NumericArg) {
/* speed-up a bit (and avoid shimmer for compiled expressions) */
if (TclHasInternalRep(argPtr, &tclExprCodeType)) {
goto doExpr;
goto doExpr;
}
result = Tcl_GetNumberFromObj(NULL, argPtr, &internalPtr, keywordIndexPtr);
if (result == TCL_OK) {
@@ -4056,13 +3906,13 @@ SequenceIdentifyArgument(
}
if (allowedArgs & RangeKeywordArg) {
result = Tcl_GetIndexFromObj(NULL, argPtr, seq_operations,
"range operation", 0, &opmode);
"range operation", 0, &opmode);
}
if (result == TCL_OK) {
if (allowedArgs & LastArg) {
/* keyword found, but no followed number */
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"missing \"%s\" value.", TclGetString(argPtr)));
"missing \"%s\" value.", TclGetString(argPtr)));
return ErrArg;
}
*keywordIndexPtr = opmode;
@@ -4145,8 +3995,8 @@ Tcl_LseqObjCmd(
SequenceDecoded decoded;
int i, arg_key = 0, value_i = 0;
/* Default constants */
#define zero ((Interp *)interp)->execEnvPtr->constants[0];
#define one ((Interp *)interp)->execEnvPtr->constants[1];
#define zero ((Interp *)interp)->execEnvPtr->constants[0];
#define one ((Interp *)interp)->execEnvPtr->constants[1];
/*
* Create a decoding key by looping through the arguments and identify
@@ -4161,19 +4011,19 @@ Tcl_LseqObjCmd(
arg_key = (arg_key * 10);
numValues[value_i] = NULL;
decoded = SequenceIdentifyArgument(interp, objv[i],
allowedArgs | (i == objc-1 ? LastArg : 0),
&numberObj, &keyword);
allowedArgs | (i == objc-1 ? LastArg : 0),
&numberObj, &keyword);
switch (decoded) {
case NoneArg:
case NoneArg:
/*
* Unrecognizable argument
* Reproduce operation error message
*/
status = Tcl_GetIndexFromObj(interp, objv[i], seq_operations,
"operation", 0, &opmode);
"operation", 0, &opmode);
goto done;
case NumericArg:
case NumericArg:
remNums--;
arg_key += NumericArg;
allowedArgs = RangeKeywordArg;
@@ -4189,14 +4039,14 @@ Tcl_LseqObjCmd(
value_i++;
break;
case RangeKeywordArg:
case RangeKeywordArg:
arg_key += RangeKeywordArg;
allowedArgs = NumericArg; /* after keyword always numeric only */
values[value_i] = keyword; /* SequenceOperators */
value_i++;
break;
default: /* Error state */
default: /* Error state */
status = TCL_ERROR;
goto done;
}
@@ -4278,10 +4128,8 @@ Tcl_LseqObjCmd(
case LSEQ_BY:
/* Error case */
goto syntax;
break;
default:
goto syntax;
break;
}
break;
@@ -4299,7 +4147,6 @@ Tcl_LseqObjCmd(
case LSEQ_COUNT:
default:
goto syntax;
break;
}
break;
@@ -4314,7 +4161,6 @@ Tcl_LseqObjCmd(
break;
default:
goto syntax;
break;
}
opmode = (SequenceOperators)values[1];
switch (opmode) {
@@ -4329,16 +4175,14 @@ Tcl_LseqObjCmd(
break;
default:
goto syntax;
break;
}
break;
/* All other argument errors */
default:
syntax:
Tcl_WrongNumArgs(interp, 1, objv, "n ??op? n ??by? n??");
goto done;
break;
syntax:
Tcl_WrongNumArgs(interp, 1, objv, "n ??op? n ??by? n??");
goto done;
}
/* Count needs to be integer, so try to convert if possible */
@@ -4367,7 +4211,7 @@ Tcl_LseqObjCmd(
* Success! Now lets create the series object.
*/
arithSeriesPtr = TclNewArithSeriesObj(interp,
useDoubles, start, end, step, elementCount);
useDoubles, start, end, step, elementCount);
status = TCL_ERROR;
if (arithSeriesPtr) {
@@ -4375,7 +4219,7 @@ Tcl_LseqObjCmd(
Tcl_SetObjResult(interp, arithSeriesPtr);
}
done:
done:
// Free number arguments.
while (--value_i>=0) {
if (numValues[value_i]) {
@@ -4390,8 +4234,8 @@ Tcl_LseqObjCmd(
}
/* Undef constants */
#undef zero
#undef one
#undef zero
#undef one
return status;
}
@@ -4452,13 +4296,13 @@ Tcl_LsetObjCmd(
} else {
if (TclObjTypeHasProc(listPtr, setElementProc)) {
finalValuePtr = TclObjTypeSetElement(interp, listPtr,
objc-3, objv+2, objv[objc-1]);
objc-3, objv+2, objv[objc-1]);
if (finalValuePtr) {
Tcl_IncrRefCount(finalValuePtr);
}
} else {
finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
objv[objc-1]);
objv[objc-1]);
}
}
@@ -4684,6 +4528,8 @@ Tcl_LsortObjCmd(
group = 1;
i++;
break;
default:
TCL_UNREACHABLE();
}
}
if (nocase && (sortInfo.sortMode == SORTMODE_ASCII)) {
+158 -20
View File
@@ -21,6 +21,7 @@
#include "tclRegexp.h"
#include "tclStringTrim.h"
#include "tclTomMath.h"
#include "../utf8proc/utf8proc.h"
static inline Tcl_Obj * During(Tcl_Interp *interp, int resultCode,
Tcl_Obj *oldOptions, Tcl_Obj *errorInfo);
@@ -132,7 +133,8 @@ Tcl_RegexpObjCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Size offset, stringLength, matchLength, cflags, eflags;
int i, indices, match, about, all, doinline, numMatchesSaved;
Tcl_Size i;
int indices, match, about, all, doinline, numMatchesSaved;
Tcl_RegExp regExpr;
Tcl_Obj *objPtr, *startIndex = NULL, *resultPtr = NULL;
Tcl_RegExpInfo info;
@@ -211,6 +213,8 @@ Tcl_RegexpObjCmd(
case REGEXP_LAST:
i++;
goto endOfForLoop;
default:
TCL_UNREACHABLE();
}
}
@@ -375,7 +379,7 @@ Tcl_RegexpObjCmd(
* area. (Scriptics Bug 4391/SF Bug #219232)
*/
if (i <= (int)info.nsubs && info.matches[i].start >= 0) {
if (i <= info.nsubs && info.matches[i].start >= 0) {
start = offset + info.matches[i].start;
end = offset + info.matches[i].end;
@@ -397,7 +401,7 @@ Tcl_RegexpObjCmd(
newPtr = Tcl_NewListObj(2, objs);
} else {
if ((i <= (int)info.nsubs) && (info.matches[i].end > 0)) {
if ((i <= info.nsubs) && (info.matches[i].end > 0)) {
newPtr = Tcl_GetRange(objPtr,
offset + info.matches[i].start,
offset + info.matches[i].end - 1);
@@ -566,6 +570,8 @@ Tcl_RegsubObjCmd(
case REGSUB_LAST:
idx++;
goto endOfForLoop;
default:
TCL_UNREACHABLE();
}
}
@@ -1319,13 +1325,20 @@ StringFirstCmd(
}
if (objc == 4) {
Tcl_Size end = Tcl_GetCharLength(objv[2]) - 1;
Tcl_Size end = Tcl_AttemptGetCharLength(objv[2]) - 1;
if (end == -1) {
return TclCannotAllocateError(interp, objv[2]);
}
if (TCL_OK != TclGetIntForIndexM(interp, objv[3], end, &start)) {
return TCL_ERROR;
}
}
Tcl_SetObjResult(interp, TclStringFirst(objv[1], objv[2], start));
Tcl_Obj *objPtr = TclStringFirst(objv[1], objv[2], start);
if (!objPtr) {
return TclCannotAllocateError(interp, objPtr);
}
Tcl_SetObjResult(interp, objPtr);
return TCL_OK;
}
@@ -1580,6 +1593,8 @@ StringIsCmd(
}
failVarObj = objv[++i];
break;
default:
TCL_UNREACHABLE();
}
}
}
@@ -1877,6 +1892,8 @@ StringIsCmd(
case STR_IS_XDIGIT:
chcomp = UniCharIsHexDigit;
break;
default:
TCL_UNREACHABLE();
}
if (chcomp != NULL) {
@@ -1904,7 +1921,7 @@ StringIsCmd(
* valid fail index (>= 0).
*/
str_is_done:
str_is_done:
if ((result == 0) && (failVarObj != NULL)) {
TclNewIndexObj(objPtr, failat);
if (Tcl_ObjSetVar2(interp, failVarObj, NULL, objPtr, TCL_LEAVE_ERR_MSG) == NULL) {
@@ -2040,8 +2057,8 @@ StringMapCmd(
* The charMap must be an even number of key/value items.
*/
Tcl_SetObjResult(interp,
Tcl_NewStringObj("char map list unbalanced", -1));
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"char map list unbalanced", -1));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "MAP",
"UNBALANCED", (char *)NULL);
return TCL_ERROR;
@@ -2293,7 +2310,11 @@ StringRangeCmd(
* 'end' refers to the last character, not one past it.
*/
end = Tcl_GetCharLength(objv[1]) - 1;
end = Tcl_AttemptGetCharLength(objv[1]);
if (end < 0) {
return TclCannotAllocateError(interp, objv[1]);
}
end--;
if (TclGetIntForIndexM(interp, objv[2], end, &first) != TCL_OK ||
TclGetIntForIndexM(interp, objv[3], end, &last) != TCL_OK) {
@@ -2469,7 +2490,11 @@ StringRevCmd(
return TCL_ERROR;
}
Tcl_SetObjResult(interp, TclStringReverse(objv[1], TCL_STRING_IN_PLACE));
Tcl_Obj *objPtr = TclStringReverse(objv[1], TCL_STRING_IN_PLACE);
if (!objPtr) {
return TclCannotAllocateError(interp, objv[1]);
}
Tcl_SetObjResult(interp, objPtr);
return TCL_OK;
}
@@ -2681,6 +2706,10 @@ StringEqualCmd(
objv += objc-2;
match = TclStringCmp(objv[0], objv[1], 1, nocase, reqlength);
if (match == INT_MIN) {
Tcl_AppendResult(interp, "memory allocation error", (char *)NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match ? 0 : 1));
return TCL_OK;
}
@@ -2726,6 +2755,10 @@ StringCmpCmd(
objv += objc-2;
match = TclStringCmp(objv[0], objv[1], 0, nocase, reqlength);
if (match == INT_MIN) {
Tcl_AppendResult(interp, "memory allocation error", (char *)NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(match));
return TCL_OK;
}
@@ -3337,12 +3370,18 @@ TclSubstOptions(
int *flagPtr)
{
static const char *const substOptions[] = {
"-backslashes", "-commands", "-variables",
"-nobackslashes", "-nocommands", "-novariables", NULL
};
static const int optionFlags[] = {
TCL_SUBST_BACKSLASHES, TCL_SUBST_COMMANDS, TCL_SUBST_VARIABLES
TCL_SUBST_BACKSLASHES, /* -backslashes */
TCL_SUBST_COMMANDS, /* -commands */
TCL_SUBST_VARIABLES, /* -variables */
TCL_SUBST_BACKSLASHES << 16, /* -nobackslashes */
TCL_SUBST_COMMANDS << 16, /* -nocommands */
TCL_SUBST_VARIABLES << 16 /* -novariables */
};
int flags = TCL_SUBST_ALL;
int flags = numOpts ? 0 : TCL_SUBST_ALL;
for (Tcl_Size i = 0; i < numOpts; i++) {
int optionIndex;
@@ -3351,7 +3390,18 @@ TclSubstOptions(
&optionIndex) != TCL_OK) {
return TCL_ERROR;
}
flags &= ~optionFlags[optionIndex];
flags |= optionFlags[optionIndex];
}
if (flags >> 16) { /* negative options specified */
if (flags & 0xFFFF) { /* positive options specified too */
if (interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"cannot combine positive and negative options", -1));
}
return TCL_ERROR;
}
/* mask default flags using negative options */
flags = TCL_SUBST_ALL & ~(flags >> 16);
}
*flagPtr = flags;
return TCL_OK;
@@ -3378,6 +3428,7 @@ TclNRSubstObjCmd(
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv,
"?-backslashes? ?-commands? ?-variables? "
"?-nobackslashes? ?-nocommands? ?-novariables? string");
return TCL_ERROR;
}
@@ -4186,6 +4237,8 @@ Tcl_TimeRateObjCmd(
break;
case TMRT_LAST:
break;
default:
TCL_UNREACHABLE();
}
}
@@ -4271,7 +4324,7 @@ Tcl_TimeRateObjCmd(
maxms = -1000;
do {
lastMeasureOverhead = measureOverhead;
TclNewIntObj(clobjv[i], (int) maxms);
TclNewIntObj(clobjv[i], maxms);
Tcl_IncrRefCount(clobjv[i]);
result = Tcl_TimeRateObjCmd(NULL, interp, i + 1, clobjv);
Tcl_DecrRefCount(clobjv[i]);
@@ -4410,7 +4463,7 @@ Tcl_TimeRateObjCmd(
*/
threshold = 1;
maxcnt = 0;
/* FALLTHRU */
TCL_FALLTHROUGH();
case TCL_CONTINUE:
result = TCL_OK;
break;
@@ -4499,7 +4552,8 @@ Tcl_TimeRateObjCmd(
lastIterTm = avgIterTm;
}
estIterTm *= lastIterTm;
last = middle; lastCount = count;
last = middle;
lastCount = count;
/*
* Calculate next threshold to check.
@@ -4507,10 +4561,10 @@ Tcl_TimeRateObjCmd(
* considering last known iteration growth factor.
*/
threshold = (Tcl_WideUInt)(stop - middle) * TR_SCALE;
/*
* Estimated count of iteration til the end of execution.
* Thereby 2.5% longer execution time would be OK.
*/
/*
* Estimated count of iteration til the end of execution.
* Thereby 2.5% longer execution time would be OK.
*/
if (threshold / estIterTm < 0.975) {
/* estimated time for next iteration is too large */
break;
@@ -4836,6 +4890,8 @@ TclNRTryObjCmd(
haveHandlers = 1;
i += 3;
break;
default:
TCL_UNREACHABLE();
}
}
if (bodyShared) {
@@ -5371,6 +5427,88 @@ TclListLines(
}
}
}
/*
* TclUnicodeNormalizeCmd --
*
* This procedure implements the "unicode tonfc|tonfd|tonfkc|tonfkd"
* commands. See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* Stores the normalized string in the interpreter result.
*/
static int
TclUnicodeNormalizeCmd(
void *clientData, /* TCL_{NFC,NFD,NFKC,NFKD} */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
static const char *optNames[] = {"-profile", NULL};
enum { OPT_PROFILE } opt;
int profile = TCL_ENCODING_PROFILE_STRICT;
if (objc == 4) {
if (Tcl_GetIndexFromObj(interp, objv[1], optNames, "option", 0, &opt) !=
TCL_OK) {
return TCL_ERROR;
}
const char *s = Tcl_GetString(objv[2]);
if (!strcmp(s, "replace")) {
profile = TCL_ENCODING_PROFILE_REPLACE;
} else if (!strcmp(s, "strict")) {
profile = TCL_ENCODING_PROFILE_STRICT;
} else {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"Invalid value \"%s\" supplied for option \"-profile\". "
"Must be \"strict\" or \"replace\".", s));
return TCL_ERROR;
}
} else if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "?-profile PROFILE? STRING");
return TCL_ERROR;
}
Tcl_DString ds;
if (Tcl_UtfToNormalizedDString(interp, Tcl_GetString(objv[objc - 1]),
TCL_INDEX_NONE, (Tcl_UnicodeNormalizationForm)PTR2INT(clientData), profile,
&ds) != TCL_OK) {
return TCL_ERROR;
}
Tcl_DStringResult(interp, &ds);
return TCL_OK;
}
/*
* TclInitUnicodeCmd --
*
* This procedure creates the "unicode" Tcl ensemble command. See user
* documentation for details on implemented commands.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* Stores the result in the interpreter result.
*/
Tcl_Command
TclInitUnicodeCmd(
Tcl_Interp *interp)
{
static const EnsembleImplMap unicodeImplMap[] = {
{"tonfc", TclUnicodeNormalizeCmd, NULL, NULL, (void *)TCL_NFC, 0},
{"tonfd", TclUnicodeNormalizeCmd, NULL, NULL, (void *)TCL_NFD, 0},
{"tonfkc", TclUnicodeNormalizeCmd, NULL, NULL, (void *)TCL_NFKC, 0},
{"tonfkd", TclUnicodeNormalizeCmd, NULL, NULL, (void *)TCL_NFKD, 0},
{NULL, NULL, NULL, NULL, NULL, 0}
};
return TclMakeEnsemble(interp, "unicode", unicodeImplMap);
}
/*
* Local Variables:
+799 -1051
View File
File diff suppressed because it is too large Load Diff
+1015 -483
View File
File diff suppressed because it is too large Load Diff
+1960 -1271
View File
File diff suppressed because it is too large Load Diff
+175 -184
View File
@@ -61,11 +61,11 @@ typedef struct {
*/
enum OperandTypes {
OT_LITERAL = -3, /* Operand is a literal in the literal list */
OT_TOKENS = -2, /* Operand is sequence of Tcl_Tokens */
OT_EMPTY = -1 /* "Operand" is an empty string. This is a special
* case used only to represent the EMPTY lexeme. See
* below. */
OT_LITERAL = -3, /* Operand is a literal in the literal list */
OT_TOKENS = -2, /* Operand is sequence of Tcl_Tokens */
OT_EMPTY = -1 /* "Operand" is an empty string. This is a
* special case used only to represent the
* EMPTY lexeme. See below. */
};
/*
@@ -106,9 +106,9 @@ enum OperandTypes {
*/
enum Marks {
MARK_LEFT, /* Next step of traversal is to visit left subtree */
MARK_RIGHT, /* Next step of traversal is to visit right subtree */
MARK_PARENT /* Next step of traversal is to return to parent */
MARK_LEFT, /* Next step of traversal is to visit left subtree */
MARK_RIGHT, /* Next step of traversal is to visit right subtree */
MARK_PARENT /* Next step of traversal is to return to parent */
};
/*
@@ -292,24 +292,24 @@ enum LexemeCodes {
*/
enum Precedence {
PREC_END = 1, /* END */
PREC_START, /* START */
PREC_CLOSE_PAREN, /* ")" */
PREC_OPEN_PAREN, /* "(" */
PREC_COMMA, /* "," */
PREC_CONDITIONAL, /* "?", ":" */
PREC_OR, /* "||" */
PREC_AND, /* "&&" */
PREC_BIT_OR, /* "|" */
PREC_BIT_XOR, /* "^" */
PREC_BIT_AND, /* "&" */
PREC_EQUAL, /* "==", "!=", "eq", "ne", "in", "ni" */
PREC_COMPARE, /* "<", ">", "<=", ">=" */
PREC_SHIFT, /* "<<", ">>" */
PREC_ADD, /* "+", "-" */
PREC_MULT, /* "*", "/", "%" */
PREC_EXPON, /* "**" */
PREC_UNARY /* "+", "-", FUNCTION, "!", "~" */
PREC_END = 1, /* END */
PREC_START, /* START */
PREC_CLOSE_PAREN, /* ")" */
PREC_OPEN_PAREN, /* "(" */
PREC_COMMA, /* "," */
PREC_CONDITIONAL, /* "?", ":" */
PREC_OR, /* "||" */
PREC_AND, /* "&&" */
PREC_BIT_OR, /* "|" */
PREC_BIT_XOR, /* "^" */
PREC_BIT_AND, /* "&" */
PREC_EQUAL, /* "==", "!=", "eq", "ne", "in", "ni" */
PREC_COMPARE, /* "<", ">", "<=", ">=" */
PREC_SHIFT, /* "<<", ">>" */
PREC_ADD, /* "+", "-" */
PREC_MULT, /* "*", "/", "%" */
PREC_EXPON, /* "**" */
PREC_UNARY /* "+", "-", FUNCTION, "!", "~" */
};
/*
@@ -326,49 +326,49 @@ static const unsigned char prec[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
/* Binary operator lexemes */
PREC_ADD, /* BINARY_PLUS */
PREC_ADD, /* BINARY_MINUS */
PREC_COMMA, /* COMMA */
PREC_MULT, /* MULT */
PREC_MULT, /* DIVIDE */
PREC_MULT, /* MOD */
PREC_COMPARE, /* LESS */
PREC_COMPARE, /* GREATER */
PREC_BIT_AND, /* BIT_AND */
PREC_BIT_XOR, /* BIT_XOR */
PREC_BIT_OR, /* BIT_OR */
PREC_CONDITIONAL, /* QUESTION */
PREC_CONDITIONAL, /* COLON */
PREC_SHIFT, /* LEFT_SHIFT */
PREC_SHIFT, /* RIGHT_SHIFT */
PREC_COMPARE, /* LEQ */
PREC_COMPARE, /* GEQ */
PREC_EQUAL, /* EQUAL */
PREC_EQUAL, /* NEQ */
PREC_AND, /* AND */
PREC_OR, /* OR */
PREC_EQUAL, /* STREQ */
PREC_EQUAL, /* STRNEQ */
PREC_EXPON, /* EXPON */
PREC_EQUAL, /* IN_LIST */
PREC_EQUAL, /* NOT_IN_LIST */
PREC_CLOSE_PAREN, /* CLOSE_PAREN */
PREC_COMPARE, /* STR_LT */
PREC_COMPARE, /* STR_GT */
PREC_COMPARE, /* STR_LEQ */
PREC_COMPARE, /* STR_GEQ */
PREC_END, /* END */
PREC_ADD, /* BINARY_PLUS */
PREC_ADD, /* BINARY_MINUS */
PREC_COMMA, /* COMMA */
PREC_MULT, /* MULT */
PREC_MULT, /* DIVIDE */
PREC_MULT, /* MOD */
PREC_COMPARE, /* LESS */
PREC_COMPARE, /* GREATER */
PREC_BIT_AND, /* BIT_AND */
PREC_BIT_XOR, /* BIT_XOR */
PREC_BIT_OR, /* BIT_OR */
PREC_CONDITIONAL, /* QUESTION */
PREC_CONDITIONAL, /* COLON */
PREC_SHIFT, /* LEFT_SHIFT */
PREC_SHIFT, /* RIGHT_SHIFT */
PREC_COMPARE, /* LEQ */
PREC_COMPARE, /* GEQ */
PREC_EQUAL, /* EQUAL */
PREC_EQUAL, /* NEQ */
PREC_AND, /* AND */
PREC_OR, /* OR */
PREC_EQUAL, /* STREQ */
PREC_EQUAL, /* STRNEQ */
PREC_EXPON, /* EXPON */
PREC_EQUAL, /* IN_LIST */
PREC_EQUAL, /* NOT_IN_LIST */
PREC_CLOSE_PAREN, /* CLOSE_PAREN */
PREC_COMPARE, /* STR_LT */
PREC_COMPARE, /* STR_GT */
PREC_COMPARE, /* STR_LEQ */
PREC_COMPARE, /* STR_GEQ */
PREC_END, /* END */
/* Expansion room for more binary operators */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* Unary operator lexemes */
PREC_UNARY, /* UNARY_PLUS */
PREC_UNARY, /* UNARY_MINUS */
PREC_UNARY, /* FUNCTION */
PREC_START, /* START */
PREC_OPEN_PAREN, /* OPEN_PAREN */
PREC_UNARY, /* NOT*/
PREC_UNARY, /* BIT_NOT*/
PREC_UNARY, /* UNARY_PLUS */
PREC_UNARY, /* UNARY_MINUS */
PREC_UNARY, /* FUNCTION */
PREC_START, /* START */
PREC_OPEN_PAREN, /* OPEN_PAREN */
PREC_UNARY, /* NOT*/
PREC_UNARY, /* BIT_NOT*/
};
/*
@@ -383,49 +383,49 @@ static const unsigned char instruction[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
/* Binary operator lexemes */
INST_ADD, /* BINARY_PLUS */
INST_SUB, /* BINARY_MINUS */
0, /* COMMA */
INST_MULT, /* MULT */
INST_DIV, /* DIVIDE */
INST_MOD, /* MOD */
INST_LT, /* LESS */
INST_GT, /* GREATER */
INST_BITAND, /* BIT_AND */
INST_BITXOR, /* BIT_XOR */
INST_BITOR, /* BIT_OR */
0, /* QUESTION */
0, /* COLON */
INST_LSHIFT, /* LEFT_SHIFT */
INST_RSHIFT, /* RIGHT_SHIFT */
INST_LE, /* LEQ */
INST_GE, /* GEQ */
INST_EQ, /* EQUAL */
INST_NEQ, /* NEQ */
0, /* AND */
0, /* OR */
INST_STR_EQ, /* STREQ */
INST_STR_NEQ, /* STRNEQ */
INST_EXPON, /* EXPON */
INST_LIST_IN, /* IN_LIST */
INST_LIST_NOT_IN, /* NOT_IN_LIST */
0, /* CLOSE_PAREN */
INST_STR_LT, /* STR_LT */
INST_STR_GT, /* STR_GT */
INST_STR_LE, /* STR_LEQ */
INST_STR_GE, /* STR_GEQ */
0, /* END */
INST_ADD, /* BINARY_PLUS */
INST_SUB, /* BINARY_MINUS */
0, /* COMMA */
INST_MULT, /* MULT */
INST_DIV, /* DIVIDE */
INST_MOD, /* MOD */
INST_LT, /* LESS */
INST_GT, /* GREATER */
INST_BITAND, /* BIT_AND */
INST_BITXOR, /* BIT_XOR */
INST_BITOR, /* BIT_OR */
0, /* QUESTION */
0, /* COLON */
INST_LSHIFT, /* LEFT_SHIFT */
INST_RSHIFT, /* RIGHT_SHIFT */
INST_LE, /* LEQ */
INST_GE, /* GEQ */
INST_EQ, /* EQUAL */
INST_NEQ, /* NEQ */
0, /* AND */
0, /* OR */
INST_STR_EQ, /* STREQ */
INST_STR_NEQ, /* STRNEQ */
INST_EXPON, /* EXPON */
INST_LIST_IN, /* IN_LIST */
INST_LIST_NOT_IN, /* NOT_IN_LIST */
0, /* CLOSE_PAREN */
INST_STR_LT, /* STR_LT */
INST_STR_GT, /* STR_GT */
INST_STR_LE, /* STR_LEQ */
INST_STR_GE, /* STR_GEQ */
0, /* END */
/* Expansion room for more binary operators */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* Unary operator lexemes */
INST_UPLUS, /* UNARY_PLUS */
INST_UMINUS, /* UNARY_MINUS */
0, /* FUNCTION */
0, /* START */
0, /* OPEN_PAREN */
INST_LNOT, /* NOT*/
INST_BITNOT, /* BIT_NOT*/
INST_UPLUS, /* UNARY_PLUS */
INST_UMINUS, /* UNARY_MINUS */
0, /* FUNCTION */
0, /* START */
0, /* OPEN_PAREN */
INST_LNOT, /* NOT*/
INST_BITNOT, /* BIT_NOT*/
};
/*
@@ -721,7 +721,7 @@ ParseExpr(
* is a legal literal boolean value, we accept that as well.
*/
if (start[scanned+TclParseAllWhiteSpace(
if (literal && start[scanned+TclParseAllWhiteSpace(
start+scanned, numBytes-scanned)] == '(') {
lexeme = FUNCTION;
@@ -733,7 +733,7 @@ ParseExpr(
*/
Tcl_ListObjAppendElement(NULL, funcList, literal);
} else if (Tcl_GetBooleanFromObj(NULL,literal,&b) == TCL_OK) {
} else if (literal && Tcl_GetBooleanFromObj(NULL,literal,&b) == TCL_OK) {
lexeme = BOOL_LIT;
} else {
/*
@@ -748,7 +748,7 @@ ParseExpr(
start + scanned2, numBytes - scanned2, &lexeme,
NULL);
} while (lexeme == COMMENT);
if (lexeme == OPEN_PAREN) {
if (literal && lexeme == OPEN_PAREN) {
/*
* Actually a function call, but with obscuring
* comments. Skip to the start of the parentheses.
@@ -762,7 +762,9 @@ ParseExpr(
break;
}
Tcl_DecrRefCount(literal);
if (literal) {
Tcl_DecrRefCount(literal);
}
msg = Tcl_ObjPrintf("invalid bareword \"%.*s%s\"",
(int)((scanned < limit) ? scanned : limit - 3), start,
(scanned < limit) ? "" : "...");
@@ -785,14 +787,16 @@ ParseExpr(
switch (start[1]) {
case 'b':
Tcl_AppendToObj(post,
" (invalid binary number?)", -1);
" (invalid binary number?)",
TCL_AUTO_LENGTH);
parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
errCode = "BADNUMBER";
subErrCode = "BINARY";
break;
case 'o':
Tcl_AppendToObj(post,
" (invalid octal number?)", -1);
" (invalid octal number?)",
TCL_AUTO_LENGTH);
parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
errCode = "BADNUMBER";
subErrCode = "OCTAL";
@@ -800,7 +804,8 @@ ParseExpr(
default:
if (isdigit(UCHAR(start[1]))) {
Tcl_AppendToObj(post,
" (invalid octal number?)", -1);
" (invalid octal number?)",
TCL_AUTO_LENGTH);
parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
errCode = "BADNUMBER";
subErrCode = "OCTAL";
@@ -1449,7 +1454,7 @@ ParseExpr(
*/
if (post != NULL) {
Tcl_AppendToObj(msg, ";\n", -1);
Tcl_AppendToObj(msg, ";\n", TCL_AUTO_LENGTH);
Tcl_AppendObjToObj(msg, post);
Tcl_DecrRefCount(post);
}
@@ -1793,7 +1798,7 @@ ConvertTreeToTokens(
*/
subExprTokenPtr->numComponents =
((int)parsePtr->numTokens - subExprTokenIdx) - 1;
(parsePtr->numTokens - subExprTokenIdx) - 1;
/*
* Finally, as we return up the tree to our parent, pop the
@@ -1856,10 +1861,10 @@ Tcl_ParseExpr(
{
int code;
OpNode *opTree = NULL; /* Will point to the tree of operators. */
Tcl_Obj *litList; /* List to hold the literals. */
Tcl_Obj *funcList; /* List to hold the functon names. */
Tcl_Parse *exprParsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse));
/* Holds the Tcl_Tokens of substitutions. */
Tcl_Obj *litList; /* List to hold the literals. */
Tcl_Obj *funcList; /* List to hold the functon names. */
Tcl_Parse *exprParsePtr = (Tcl_Parse *)TclStackAlloc(interp,
sizeof(Tcl_Parse)); /* Holds the Tcl_Tokens of substitutions. */
TclNewObj(litList);
TclNewObj(funcList);
@@ -2082,7 +2087,10 @@ ParseLexeme(
number:
*lexemePtr = NUMBER;
if (literalPtr) {
TclInitStringRep(literal, start, end-start);
if(!TclAttemptInitStringRep(literal, start, end-start)) {
Tcl_DecrRefCount(literal);
literal = NULL;
}
*literalPtr = literal;
} else {
Tcl_DecrRefCount(literal);
@@ -2268,7 +2276,7 @@ ExecConstantExprTree(
TclInitCompileEnv(interp, envPtr, NULL, 0, NULL, 0);
CompileExprTree(interp, nodes, index, litObjvPtr, NULL, NULL, envPtr,
0 /* optimize */);
TclEmitOpcode(INST_DONE, envPtr);
OP( DONE);
byteCodePtr = TclInitByteCode(envPtr);
TclFreeCompileEnv(envPtr);
TclStackFree(interp, envPtr);
@@ -2333,19 +2341,12 @@ CompileExprTree(
switch (nodePtr->lexeme) {
case FUNCTION: {
Tcl_DString cmdName;
const char *p;
Tcl_Size length;
Tcl_Obj *cmdName;
Tcl_DStringInit(&cmdName);
TclDStringAppendLiteral(&cmdName, "tcl::mathfunc::");
p = TclGetStringFromObj(*funcObjv, &length);
TclNewLiteralStringObj(cmdName, "tcl::mathfunc::");
Tcl_AppendObjToObj(cmdName, *funcObjv);
funcObjv++;
Tcl_DStringAppend(&cmdName, p, length);
TclEmitPush(TclRegisterLiteral(envPtr,
Tcl_DStringValue(&cmdName),
Tcl_DStringLength(&cmdName), LITERAL_CMD_NAME), envPtr);
Tcl_DStringFree(&cmdName);
PUSH_OBJ_FLAGS(cmdName, LITERAL_CMD_NAME);
/*
* Start a count of the number of words in this function
@@ -2370,7 +2371,7 @@ CompileExprTree(
jumpPtr = newJump;
TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
&jumpPtr->jump);
TclAdjustStackDepth(-1, envPtr);
STKDELTA(-1);
if (convert) {
jumpPtr->jump.jumpType = TCL_TRUE_JUMP;
}
@@ -2386,13 +2387,14 @@ CompileExprTree(
break;
}
} else {
Tcl_Size pc1, pc2, target;
Tcl_Size target;
Tcl_BytecodeLabel pc1, pc2;
switch (nodePtr->lexeme) {
case START:
case QUESTION:
if (convert && (nodePtr == rootPtr)) {
TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
OP( TRY_CVT_TO_NUMERIC);
}
break;
case OPEN_PAREN:
@@ -2405,11 +2407,7 @@ CompileExprTree(
* command with the correct number of arguments.
*/
if (numWords < 255) {
TclEmitInvoke(envPtr, INST_INVOKE_STK1, numWords);
} else {
TclEmitInvoke(envPtr, INST_INVOKE_STK4, numWords);
}
INVOKE4( INVOKE_STK, numWords);
/*
* Restore any saved numWords value.
@@ -2431,15 +2429,13 @@ CompileExprTree(
jumpPtr->jump.jumpType = TCL_UNCONDITIONAL_JUMP;
convert = 1;
}
target = jumpPtr->jump.codeOffset + 2;
if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) {
target += 3;
}
target = jumpPtr->jump.codeOffset + 5;
TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump);
freePtr = jumpPtr;
jumpPtr = jumpPtr->next;
TclStackFree(interp, freePtr);
TclFixupForwardJump(envPtr, &jumpPtr->jump,
target - jumpPtr->jump.codeOffset, 127);
target - jumpPtr->jump.codeOffset);
freePtr = jumpPtr;
jumpPtr = jumpPtr->next;
@@ -2448,23 +2444,18 @@ CompileExprTree(
case AND:
case OR:
CLANG_ASSERT(jumpPtr);
pc1 = CurrentOffset(envPtr);
TclEmitInstInt1((nodePtr->lexeme == AND) ? INST_JUMP_FALSE1
: INST_JUMP_TRUE1, 0, envPtr);
TclEmitPush(TclRegisterLiteral(envPtr,
(nodePtr->lexeme == AND) ? "1" : "0", 1, 0), envPtr);
pc2 = CurrentOffset(envPtr);
TclEmitInstInt1(INST_JUMP1, 0, envPtr);
TclAdjustStackDepth(-1, envPtr);
TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc1,
envPtr->codeStart + pc1 + 1);
if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) {
pc2 += 3;
if (nodePtr->lexeme == AND) {
FWDJUMP( JUMP_FALSE, pc1);
} else {
FWDJUMP( JUMP_TRUE, pc1);
}
TclEmitPush(TclRegisterLiteral(envPtr,
(nodePtr->lexeme == AND) ? "0" : "1", 1, 0), envPtr);
TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc2,
envPtr->codeStart + pc2 + 1);
PUSH_STRING( (nodePtr->lexeme == AND) ? "1" : "0");
FWDJUMP( JUMP, pc2);
STKDELTA(-1);
FWDLABEL(pc1);
TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump);
PUSH_STRING( (nodePtr->lexeme == AND) ? "0" : "1");
FWDLABEL(pc2);
convert = 0;
freePtr = jumpPtr;
jumpPtr = jumpPtr->next;
@@ -2494,9 +2485,7 @@ CompileExprTree(
Tcl_Obj *literal = *litObjv;
if (optimize) {
Tcl_Size length;
const char *bytes = TclGetStringFromObj(literal, &length);
int idx = TclRegisterLiteral(envPtr, bytes, length, 0);
int idx = PUSH_OBJ_FLAGS(literal, 0);
Tcl_Obj *objPtr = TclFetchLiteral(envPtr, idx);
if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) {
@@ -2517,7 +2506,6 @@ CompileExprTree(
objPtr->internalRep = literal->internalRep;
literal->typePtr = NULL;
}
TclEmitPush(idx, envPtr);
} else {
/*
* When optimize==0, we know the expression is a one-off and
@@ -2528,7 +2516,7 @@ CompileExprTree(
* that preserves internalreps.
*/
TclEmitPush(TclAddLiteralObj(envPtr, literal, NULL), envPtr);
PUSH_OBJ( literal);
}
(*litObjvPtr)++;
break;
@@ -2672,7 +2660,8 @@ TclSortingOpCmd(
TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;
Tcl_Obj **litObjv = (Tcl_Obj **)TclStackAlloc(interp,
2 * (objc-2) * sizeof(Tcl_Obj *));
OpNode *nodes = (OpNode *)TclStackAlloc(interp, 2 * (objc-2) * sizeof(OpNode));
OpNode *nodes = (OpNode *)TclStackAlloc(interp,
2 * (objc-2) * sizeof(OpNode));
unsigned char lexeme;
int i, lastAnd = 1;
Tcl_Obj *const *litObjPtrPtr = litObjv;
@@ -2683,29 +2672,30 @@ TclSortingOpCmd(
nodes[0].lexeme = START;
nodes[0].mark = MARK_RIGHT;
for (i=2; i<objc-1; i++) {
litObjv[2*(i-1)-1] = objv[i];
nodes[2*(i-1)-1].lexeme = lexeme;
nodes[2*(i-1)-1].mark = MARK_LEFT;
nodes[2*(i-1)-1].left = OT_LITERAL;
nodes[2*(i-1)-1].right = OT_LITERAL;
int j = 2 * (i - 1);
litObjv[j - 1] = objv[i];
nodes[j - 1].lexeme = lexeme;
nodes[j - 1].mark = MARK_LEFT;
nodes[j - 1].left = OT_LITERAL;
nodes[j - 1].right = OT_LITERAL;
litObjv[2*(i-1)] = objv[i];
nodes[2*(i-1)].lexeme = AND;
nodes[2*(i-1)].mark = MARK_LEFT;
nodes[2*(i-1)].left = lastAnd;
nodes[lastAnd].p.parent = 2*(i-1);
litObjv[j] = objv[i];
nodes[j].lexeme = AND;
nodes[j].mark = MARK_LEFT;
nodes[j].left = lastAnd;
nodes[lastAnd].p.parent = j;
nodes[2*(i-1)].right = 2*(i-1)+1;
nodes[2*(i-1)+1].p.parent= 2*(i-1);
nodes[j].right = j + 1;
nodes[j + 1].p.parent= j;
lastAnd = 2*(i-1);
lastAnd = j;
}
litObjv[2*(objc-2)-1] = objv[objc-1];
litObjv[2 * (objc - 2) - 1] = objv[objc - 1];
nodes[2*(objc-2)-1].lexeme = lexeme;
nodes[2*(objc-2)-1].mark = MARK_LEFT;
nodes[2*(objc-2)-1].left = OT_LITERAL;
nodes[2*(objc-2)-1].right = OT_LITERAL;
nodes[2 * (objc - 2) - 1].lexeme = lexeme;
nodes[2 * (objc - 2) - 1].mark = MARK_LEFT;
nodes[2 * (objc - 2) - 1].left = OT_LITERAL;
nodes[2 * (objc - 2) - 1].right = OT_LITERAL;
nodes[0].right = lastAnd;
nodes[lastAnd].p.parent = 0;
@@ -2799,7 +2789,8 @@ TclVariadicOpCmd(
return code;
} else {
Tcl_Obj *const *litObjv = objv + 1;
OpNode *nodes = (OpNode *)TclStackAlloc(interp, (objc-1) * sizeof(OpNode));
OpNode *nodes = (OpNode *)TclStackAlloc(interp,
(objc - 1) * sizeof(OpNode));
int i, lastOp = OT_LITERAL;
nodes[0].lexeme = START;
+1082 -493
View File
File diff suppressed because it is too large Load Diff
+809 -306
View File
File diff suppressed because it is too large Load Diff
+1 -2
View File
@@ -299,8 +299,7 @@ QueryConfigObjCmd(
return TCL_OK;
default:
Tcl_Panic("QueryConfigObjCmd: Unknown subcommand to 'pkgconfig'. This can't happen");
break;
TCL_UNREACHABLE();
}
return TCL_ERROR;
}
+1 -1
View File
@@ -393,7 +393,7 @@ typedef struct ClockScanToken ClockScanToken;
typedef int ClockScanTokenProc(
ClockFmtScnCmdArgs *opts,
DateInfo *info,
ClockScanToken *tok);
const ClockScanToken *tok);
typedef enum _CLCKTOK_TYPE {
CTOKT_INT = 1, CTOKT_WIDE, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD, CTOKT_CHAR,
+97 -29
View File
@@ -107,7 +107,10 @@ EXTERN void Tcl_DbIncrRefCount(Tcl_Obj *objPtr, const char *file,
/* 21 */
EXTERN int Tcl_DbIsShared(Tcl_Obj *objPtr, const char *file,
int line);
/* Slot 22 is reserved */
/* 22 */
EXTERN char * Tcl_DbGetStringFromObj(Tcl_Obj *objPtr,
Tcl_Size *lengthPtr, const char *file,
int line);
/* 23 */
EXTERN Tcl_Obj * Tcl_DbNewByteArrayObj(const unsigned char *bytes,
Tcl_Size numBytes, const char *file,
@@ -189,7 +192,9 @@ EXTERN Tcl_Obj * Tcl_NewListObj(Tcl_Size objc, Tcl_Obj *const objv[]);
EXTERN Tcl_Obj * Tcl_NewObj(void);
/* 56 */
EXTERN Tcl_Obj * Tcl_NewStringObj(const char *bytes, Tcl_Size length);
/* Slot 57 is reserved */
/* 57 */
EXTERN Tcl_Obj * Tcl_AttemptNewStringObj(const char *bytes,
Tcl_Size length);
/* 58 */
EXTERN unsigned char * Tcl_SetByteArrayLength(Tcl_Obj *objPtr,
Tcl_Size numBytes);
@@ -199,7 +204,8 @@ EXTERN void Tcl_SetByteArrayObj(Tcl_Obj *objPtr,
Tcl_Size numBytes);
/* 60 */
EXTERN void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue);
/* Slot 61 is reserved */
/* 61 */
EXTERN Tcl_Size Tcl_AttemptGetCharLength(Tcl_Obj *objPtr);
/* 62 */
EXTERN void Tcl_SetListObj(Tcl_Obj *objPtr, Tcl_Size objc,
Tcl_Obj *const objv[]);
@@ -895,9 +901,13 @@ EXTERN Tcl_Size Tcl_WriteChars(Tcl_Channel chan, const char *src,
/* 339 */
EXTERN Tcl_Size Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr);
/* 340 */
EXTERN char * Tcl_GetString(Tcl_Obj *objPtr);
/* Slot 341 is reserved */
/* Slot 342 is reserved */
EXTERN char * Tcl_AttemptGetStringFromObj(Tcl_Obj *objPtr,
Tcl_Size *lengthPtr);
/* 341 */
EXTERN char * Tcl_AttemptSetStringObj(Tcl_Obj *objPtr,
const char *bytes, Tcl_Size length);
/* 342 */
EXTERN Tcl_Obj * Tcl_AttemptDuplicateObj(Tcl_Obj *objPtr);
/* 343 */
EXTERN void Tcl_AlertNotifier(void *clientData);
/* 344 */
@@ -1094,8 +1104,13 @@ EXTERN void Tcl_ClearChannelHandlers(Tcl_Channel channel);
EXTERN int Tcl_IsChannelExisting(const char *channelName);
/* Slot 419 is reserved */
/* Slot 420 is reserved */
/* Slot 421 is reserved */
/* Slot 422 is reserved */
/* 421 */
EXTERN Tcl_HashEntry * Tcl_DbCreateHashEntry(Tcl_HashTable *tablePtr,
const void *key, int *newPtr,
const char *file, int line);
/* 422 */
EXTERN Tcl_HashEntry * Tcl_CreateHashEntry(Tcl_HashTable *tablePtr,
const void *key, int *newPtr);
/* 423 */
EXTERN void Tcl_InitCustomHashTable(Tcl_HashTable *tablePtr,
int keyType, const Tcl_HashKeyType *typePtr);
@@ -1869,6 +1884,31 @@ EXTERN void Tcl_SetWideUIntObj(Tcl_Obj *objPtr,
/* 690 */
EXTERN int Tcl_IsEmpty(Tcl_Obj *obj);
/* 691 */
EXTERN const char * Tcl_GetEncodingNameForUser(Tcl_DString *bufPtr);
/* 692 */
EXTERN int Tcl_ListObjReverse(Tcl_Interp *interp,
Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr);
/* 693 */
EXTERN int Tcl_ListObjRepeat(Tcl_Interp *interp,
Tcl_Size repeatCount, Tcl_Size objc,
Tcl_Obj *const objv[],
Tcl_Obj **resultPtrPtr);
/* 694 */
EXTERN int Tcl_ListObjRange(Tcl_Interp *interp, Tcl_Obj *objPtr,
Tcl_Size start, Tcl_Size end,
Tcl_Obj **resultPtrPtr);
/* 695 */
EXTERN int Tcl_UtfToNormalizedDString(Tcl_Interp *interp,
const char *bytes, Tcl_Size length,
Tcl_UnicodeNormalizationForm normForm,
int profile, Tcl_DString *dsPtr);
/* 696 */
EXTERN int Tcl_UtfToNormalized(Tcl_Interp *interp,
const char *bytes, Tcl_Size length,
Tcl_UnicodeNormalizationForm normForm,
int profile, char *bufPtr, Tcl_Size bufLen,
Tcl_Size *lengthPtr);
/* 697 */
EXTERN void TclUnusedStubEntry(void);
typedef struct {
@@ -1903,7 +1943,7 @@ typedef struct TclStubs {
void (*tcl_DbDecrRefCount) (Tcl_Obj *objPtr, const char *file, int line); /* 19 */
void (*tcl_DbIncrRefCount) (Tcl_Obj *objPtr, const char *file, int line); /* 20 */
int (*tcl_DbIsShared) (Tcl_Obj *objPtr, const char *file, int line); /* 21 */
void (*reserved22)(void);
char * (*tcl_DbGetStringFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr, const char *file, int line); /* 22 */
Tcl_Obj * (*tcl_DbNewByteArrayObj) (const unsigned char *bytes, Tcl_Size numBytes, const char *file, int line); /* 23 */
Tcl_Obj * (*tcl_DbNewDoubleObj) (double doubleValue, const char *file, int line); /* 24 */
Tcl_Obj * (*tcl_DbNewListObj) (Tcl_Size objc, Tcl_Obj *const *objv, const char *file, int line); /* 25 */
@@ -1938,11 +1978,11 @@ typedef struct TclStubs {
void (*reserved54)(void);
Tcl_Obj * (*tcl_NewObj) (void); /* 55 */
Tcl_Obj * (*tcl_NewStringObj) (const char *bytes, Tcl_Size length); /* 56 */
void (*reserved57)(void);
Tcl_Obj * (*tcl_AttemptNewStringObj) (const char *bytes, Tcl_Size length); /* 57 */
unsigned char * (*tcl_SetByteArrayLength) (Tcl_Obj *objPtr, Tcl_Size numBytes); /* 58 */
void (*tcl_SetByteArrayObj) (Tcl_Obj *objPtr, const unsigned char *bytes, Tcl_Size numBytes); /* 59 */
void (*tcl_SetDoubleObj) (Tcl_Obj *objPtr, double doubleValue); /* 60 */
void (*reserved61)(void);
Tcl_Size (*tcl_AttemptGetCharLength) (Tcl_Obj *objPtr); /* 61 */
void (*tcl_SetListObj) (Tcl_Obj *objPtr, Tcl_Size objc, Tcl_Obj *const objv[]); /* 62 */
void (*reserved63)(void);
void (*tcl_SetObjLength) (Tcl_Obj *objPtr, Tcl_Size length); /* 64 */
@@ -2221,9 +2261,9 @@ typedef struct TclStubs {
Tcl_Size (*tcl_UtfToUpper) (char *src); /* 337 */
Tcl_Size (*tcl_WriteChars) (Tcl_Channel chan, const char *src, Tcl_Size srcLen); /* 338 */
Tcl_Size (*tcl_WriteObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 339 */
char * (*tcl_GetString) (Tcl_Obj *objPtr); /* 340 */
void (*reserved341)(void);
void (*reserved342)(void);
char * (*tcl_AttemptGetStringFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr); /* 340 */
char * (*tcl_AttemptSetStringObj) (Tcl_Obj *objPtr, const char *bytes, Tcl_Size length); /* 341 */
Tcl_Obj * (*tcl_AttemptDuplicateObj) (Tcl_Obj *objPtr); /* 342 */
void (*tcl_AlertNotifier) (void *clientData); /* 343 */
void (*tcl_ServiceModeHook) (int mode); /* 344 */
int (*tcl_UniCharIsAlnum) (int ch); /* 345 */
@@ -2302,8 +2342,8 @@ typedef struct TclStubs {
int (*tcl_IsChannelExisting) (const char *channelName); /* 418 */
void (*reserved419)(void);
void (*reserved420)(void);
void (*reserved421)(void);
void (*reserved422)(void);
Tcl_HashEntry * (*tcl_DbCreateHashEntry) (Tcl_HashTable *tablePtr, const void *key, int *newPtr, const char *file, int line); /* 421 */
Tcl_HashEntry * (*tcl_CreateHashEntry) (Tcl_HashTable *tablePtr, const void *key, int *newPtr); /* 422 */
void (*tcl_InitCustomHashTable) (Tcl_HashTable *tablePtr, int keyType, const Tcl_HashKeyType *typePtr); /* 423 */
void (*tcl_InitObjHashTable) (Tcl_HashTable *tablePtr); /* 424 */
void * (*tcl_CommandTraceInfo) (Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *procPtr, void *prevClientData); /* 425 */
@@ -2572,7 +2612,13 @@ typedef struct TclStubs {
Tcl_Obj * (*tcl_NewWideUIntObj) (Tcl_WideUInt wideValue); /* 688 */
void (*tcl_SetWideUIntObj) (Tcl_Obj *objPtr, Tcl_WideUInt uwideValue); /* 689 */
int (*tcl_IsEmpty) (Tcl_Obj *obj); /* 690 */
void (*tclUnusedStubEntry) (void); /* 691 */
const char * (*tcl_GetEncodingNameForUser) (Tcl_DString *bufPtr); /* 691 */
int (*tcl_ListObjReverse) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr); /* 692 */
int (*tcl_ListObjRepeat) (Tcl_Interp *interp, Tcl_Size repeatCount, Tcl_Size objc, Tcl_Obj *const objv[], Tcl_Obj **resultPtrPtr); /* 693 */
int (*tcl_ListObjRange) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Size start, Tcl_Size end, Tcl_Obj **resultPtrPtr); /* 694 */
int (*tcl_UtfToNormalizedDString) (Tcl_Interp *interp, const char *bytes, Tcl_Size length, Tcl_UnicodeNormalizationForm normForm, int profile, Tcl_DString *dsPtr); /* 695 */
int (*tcl_UtfToNormalized) (Tcl_Interp *interp, const char *bytes, Tcl_Size length, Tcl_UnicodeNormalizationForm normForm, int profile, char *bufPtr, Tcl_Size bufLen, Tcl_Size *lengthPtr); /* 696 */
void (*tclUnusedStubEntry) (void); /* 697 */
} TclStubs;
extern const TclStubs *tclStubsPtr;
@@ -2631,7 +2677,8 @@ extern const TclStubs *tclStubsPtr;
(tclStubsPtr->tcl_DbIncrRefCount) /* 20 */
#define Tcl_DbIsShared \
(tclStubsPtr->tcl_DbIsShared) /* 21 */
/* Slot 22 is reserved */
#define Tcl_DbGetStringFromObj \
(tclStubsPtr->tcl_DbGetStringFromObj) /* 22 */
#define Tcl_DbNewByteArrayObj \
(tclStubsPtr->tcl_DbNewByteArrayObj) /* 23 */
#define Tcl_DbNewDoubleObj \
@@ -2692,14 +2739,16 @@ extern const TclStubs *tclStubsPtr;
(tclStubsPtr->tcl_NewObj) /* 55 */
#define Tcl_NewStringObj \
(tclStubsPtr->tcl_NewStringObj) /* 56 */
/* Slot 57 is reserved */
#define Tcl_AttemptNewStringObj \
(tclStubsPtr->tcl_AttemptNewStringObj) /* 57 */
#define Tcl_SetByteArrayLength \
(tclStubsPtr->tcl_SetByteArrayLength) /* 58 */
#define Tcl_SetByteArrayObj \
(tclStubsPtr->tcl_SetByteArrayObj) /* 59 */
#define Tcl_SetDoubleObj \
(tclStubsPtr->tcl_SetDoubleObj) /* 60 */
/* Slot 61 is reserved */
#define Tcl_AttemptGetCharLength \
(tclStubsPtr->tcl_AttemptGetCharLength) /* 61 */
#define Tcl_SetListObj \
(tclStubsPtr->tcl_SetListObj) /* 62 */
/* Slot 63 is reserved */
@@ -3215,10 +3264,12 @@ extern const TclStubs *tclStubsPtr;
(tclStubsPtr->tcl_WriteChars) /* 338 */
#define Tcl_WriteObj \
(tclStubsPtr->tcl_WriteObj) /* 339 */
#define Tcl_GetString \
(tclStubsPtr->tcl_GetString) /* 340 */
/* Slot 341 is reserved */
/* Slot 342 is reserved */
#define Tcl_AttemptGetStringFromObj \
(tclStubsPtr->tcl_AttemptGetStringFromObj) /* 340 */
#define Tcl_AttemptSetStringObj \
(tclStubsPtr->tcl_AttemptSetStringObj) /* 341 */
#define Tcl_AttemptDuplicateObj \
(tclStubsPtr->tcl_AttemptDuplicateObj) /* 342 */
#define Tcl_AlertNotifier \
(tclStubsPtr->tcl_AlertNotifier) /* 343 */
#define Tcl_ServiceModeHook \
@@ -3368,8 +3419,10 @@ extern const TclStubs *tclStubsPtr;
(tclStubsPtr->tcl_IsChannelExisting) /* 418 */
/* Slot 419 is reserved */
/* Slot 420 is reserved */
/* Slot 421 is reserved */
/* Slot 422 is reserved */
#define Tcl_DbCreateHashEntry \
(tclStubsPtr->tcl_DbCreateHashEntry) /* 421 */
#define Tcl_CreateHashEntry \
(tclStubsPtr->tcl_CreateHashEntry) /* 422 */
#define Tcl_InitCustomHashTable \
(tclStubsPtr->tcl_InitCustomHashTable) /* 423 */
#define Tcl_InitObjHashTable \
@@ -3903,8 +3956,20 @@ extern const TclStubs *tclStubsPtr;
(tclStubsPtr->tcl_SetWideUIntObj) /* 689 */
#define Tcl_IsEmpty \
(tclStubsPtr->tcl_IsEmpty) /* 690 */
#define Tcl_GetEncodingNameForUser \
(tclStubsPtr->tcl_GetEncodingNameForUser) /* 691 */
#define Tcl_ListObjReverse \
(tclStubsPtr->tcl_ListObjReverse) /* 692 */
#define Tcl_ListObjRepeat \
(tclStubsPtr->tcl_ListObjRepeat) /* 693 */
#define Tcl_ListObjRange \
(tclStubsPtr->tcl_ListObjRange) /* 694 */
#define Tcl_UtfToNormalizedDString \
(tclStubsPtr->tcl_UtfToNormalizedDString) /* 695 */
#define Tcl_UtfToNormalized \
(tclStubsPtr->tcl_UtfToNormalized) /* 696 */
#define TclUnusedStubEntry \
(tclStubsPtr->tclUnusedStubEntry) /* 691 */
(tclStubsPtr->tclUnusedStubEntry) /* 697 */
#endif /* defined(USE_TCL_STUBS) */
@@ -4003,10 +4068,10 @@ extern const TclStubs *tclStubsPtr;
# endif
#endif
#undef Tcl_GetString
#undef Tcl_GetUnicode
#define Tcl_GetString(objPtr) \
Tcl_GetStringFromObj(objPtr, (Tcl_Size *)NULL)
#define Tcl_AttemptGetString(objPtr) \
Tcl_AttemptGetStringFromObj(objPtr, (Tcl_Size *)NULL)
#define Tcl_GetUnicode(objPtr) \
Tcl_GetUnicodeFromObj(objPtr, (Tcl_Size *)NULL)
#undef Tcl_GetIndexFromObjStruct
@@ -4060,6 +4125,9 @@ extern const TclStubs *tclStubsPtr;
# undef Tcl_AttemptRealloc
# define Tcl_AttemptRealloc(x,y) \
(Tcl_AttemptDbCkrealloc((x), (y), __FILE__, __LINE__))
# undef Tcl_GetStringFromObj
# define Tcl_GetStringFromObj(x,y) \
(Tcl_DbGetStringFromObj((x), (y), __FILE__, __LINE__))
#endif /* !TCL_MEM_DEBUG */
#define Tcl_NewLongObj(value) Tcl_NewWideIntObj((long)(value))
+42 -22
View File
@@ -82,8 +82,8 @@ static const EnsembleImplMap implementationMap[] = {
{"lappend", DictLappendCmd, TclCompileDictLappendCmd, NULL, NULL, 0 },
{"map", NULL, TclCompileDictMapCmd, DictMapNRCmd, NULL, 0 },
{"merge", DictMergeCmd, TclCompileDictMergeCmd, NULL, NULL, 0 },
{"remove", DictRemoveCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0 },
{"replace", DictReplaceCmd, NULL, NULL, NULL, 0 },
{"remove", DictRemoveCmd, TclCompileDictRemoveCmd, NULL, NULL, 0 },
{"replace", DictReplaceCmd, TclCompileDictReplaceCmd, NULL, NULL, 0 },
{"set", DictSetCmd, TclCompileDictSetCmd, NULL, NULL, 0 },
{"size", DictSizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 },
{"unset", DictUnsetCmd, TclCompileDictUnsetCmd, NULL, NULL, 0 },
@@ -520,7 +520,17 @@ UpdateStringOfDict(
if (numElems <= LOCAL_SIZE) {
flagPtr = localFlags;
} else {
flagPtr = (char *)Tcl_Alloc(numElems);
flagPtr = (char *)Tcl_AttemptAlloc(numElems);
if (!flagPtr) {
dictPtr->length = numElems - 1;
allocError:
/* Allocation error. Just give up. */
if (dictPtr->bytes) {
Tcl_Free(dictPtr->bytes);
dictPtr->bytes = NULL;
}
return;
}
}
for (i=0,cPtr=dict->entryChainHead; i<numElems; i+=2,cPtr=cPtr->nextPtr) {
/*
@@ -530,11 +540,19 @@ UpdateStringOfDict(
flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 );
keyPtr = (Tcl_Obj *)Tcl_GetHashKey(&dict->table, &cPtr->entry);
elem = TclGetStringFromObj(keyPtr, &length);
elem = TclAttemptGetStringFromObj(keyPtr, &length);
if (!elem) {
dictPtr->length = keyPtr->length;
goto allocError;
}
bytesNeeded += TclScanElement(elem, length, flagPtr+i);
flagPtr[i+1] = TCL_DONT_QUOTE_HASH;
valuePtr = (Tcl_Obj *)Tcl_GetHashValue(&cPtr->entry);
elem = TclGetStringFromObj(valuePtr, &length);
elem = TclAttemptGetStringFromObj(valuePtr, &length);
if (!elem) {
dictPtr->length = valuePtr->length;
goto allocError;
}
bytesNeeded += TclScanElement(elem, length, flagPtr+i+1);
}
bytesNeeded += numElems;
@@ -544,7 +562,10 @@ UpdateStringOfDict(
*/
dst = Tcl_InitStringRep(dictPtr, NULL, bytesNeeded - 1);
TclOOM(dst, bytesNeeded);
if (!dst) {
dictPtr->length = bytesNeeded;
goto allocError;
}
for (i=0,cPtr=dict->entryChainHead; i<numElems; i+=2,cPtr=cPtr->nextPtr) {
if (i) {
flagPtr[i] |= TCL_DONT_QUOTE_HASH;
@@ -1472,7 +1493,7 @@ Tcl_DbNewDictObj(
TclDbNewObj(dictPtr, file, line);
TclInvalidateStringRep(dictPtr);
dict = (Dict *)Tcl_Alloc(sizeof(Dict));
dict = (Dict *)Tcl_DbCkalloc(sizeof(Dict), file, line);
InitChainTable(dict);
dict->epoch = 1;
dict->chain = NULL;
@@ -3231,7 +3252,7 @@ DictFilterCmd(
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[2], filters, "filterType",
0, &index) != TCL_OK) {
0, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -3424,7 +3445,7 @@ DictFilterCmd(
Tcl_ResetResult(interp);
Tcl_DictObjDone(&search);
/* FALLTHRU */
TCL_FALLTHROUGH();
case TCL_CONTINUE:
result = TCL_OK;
break;
@@ -3432,6 +3453,7 @@ DictFilterCmd(
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (\"dict filter\" script line %d)",
Tcl_GetErrorLine(interp)));
TCL_FALLTHROUGH();
default:
goto abnormalResult;
}
@@ -3457,20 +3479,18 @@ DictFilterCmd(
TclDecrRefCount(resultObj);
}
return result;
abnormalResult:
Tcl_DictObjDone(&search);
TclDecrRefCount(keyObj);
TclDecrRefCount(valueObj);
TclDecrRefCount(keyVarObj);
TclDecrRefCount(valueVarObj);
TclDecrRefCount(scriptObj);
TclDecrRefCount(resultObj);
return result;
}
Tcl_Panic("unexpected fallthrough");
/* Control never reaches this point. */
return TCL_ERROR;
TCL_UNREACHABLE();
abnormalResult:
Tcl_DictObjDone(&search);
TclDecrRefCount(keyObj);
TclDecrRefCount(valueObj);
TclDecrRefCount(keyVarObj);
TclDecrRefCount(valueVarObj);
TclDecrRefCount(scriptObj);
TclDecrRefCount(resultObj);
return result;
}
/*
+159 -120
View File
@@ -13,6 +13,7 @@
*/
#include "tclInt.h"
#define ALLOW_DEPRECATED_OPCODES
#include "tclCompile.h"
#include "tclOOInt.h"
#include <assert.h>
@@ -132,7 +133,7 @@ void
TclDebugPrintByteCodeObj(
Tcl_Obj *objPtr) /* The bytecode object to disassemble. */
{
if (tclTraceCompile >= 2) {
if (tclTraceCompile >= TCL_TRACE_BYTECODE_COMPILE_DETAIL) {
Tcl_Obj *bufPtr = DisassembleByteCodeObj(objPtr);
fprintf(stdout, "\n%s", TclGetString(bufPtr));
@@ -280,8 +281,11 @@ DisassembleByteCodeObj(
*/
Tcl_AppendPrintfToObj(bufferObj,
"ByteCode %p, refCt %" TCL_SIZE_MODIFIER "d, epoch %" TCL_SIZE_MODIFIER "d, interp %p (epoch %" TCL_SIZE_MODIFIER "d)\n",
codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr, iPtr->compileEpoch);
"ByteCode %p, refCt %" TCL_SIZE_MODIFIER "d, "
"epoch %" TCL_SIZE_MODIFIER "d, interp %p "
"(epoch %" TCL_SIZE_MODIFIER "d)\n",
codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr,
iPtr->compileEpoch);
Tcl_AppendToObj(bufferObj, " Source ", -1);
PrintSourceToObj(bufferObj, codePtr->source,
TclMin(codePtr->numSrcBytes, 55));
@@ -291,7 +295,10 @@ DisassembleByteCodeObj(
TclGetString(fileObj), line);
}
Tcl_AppendPrintfToObj(bufferObj,
"\n Cmds %d, src %" TCL_SIZE_MODIFIER "d, inst %" TCL_SIZE_MODIFIER "d, litObjs %" TCL_SIZE_MODIFIER "d, aux %" TCL_SIZE_MODIFIER "d, stkDepth %" TCL_SIZE_MODIFIER "d, code/src %.2f\n",
"\n Cmds %d, src %" TCL_SIZE_MODIFIER "d, "
"inst %" TCL_SIZE_MODIFIER "d, litObjs %" TCL_SIZE_MODIFIER "d, "
"aux %" TCL_SIZE_MODIFIER "d, stkDepth %" TCL_SIZE_MODIFIER "d, "
"code/src %.2f\n",
numCmds, codePtr->numSrcBytes, codePtr->numCodeBytes,
codePtr->numLitObjects, codePtr->numAuxDataItems,
codePtr->maxStackDepth,
@@ -303,8 +310,10 @@ DisassembleByteCodeObj(
#ifdef TCL_COMPILE_STATS
Tcl_AppendPrintfToObj(bufferObj,
" Code %" TCL_Z_MODIFIER "u = header %" TCL_Z_MODIFIER "u+inst %" TCL_SIZE_MODIFIER "d+litObj %"
TCL_Z_MODIFIER "u+exc %" TCL_Z_MODIFIER "u+aux %" TCL_Z_MODIFIER "u+cmdMap %" TCL_SIZE_MODIFIER "d\n",
" Code %" TCL_Z_MODIFIER "u = header %" TCL_Z_MODIFIER "u+"
"inst %" TCL_SIZE_MODIFIER "d+litObj %" TCL_Z_MODIFIER "u+"
"exc %" TCL_Z_MODIFIER "u+aux %" TCL_Z_MODIFIER "u+"
"cmdMap %" TCL_SIZE_MODIFIER "d\n",
codePtr->structureSize,
offsetof(ByteCode, localCachePtr),
codePtr->numCodeBytes,
@@ -325,7 +334,9 @@ DisassembleByteCodeObj(
Tcl_Size numCompiledLocals = procPtr->numCompiledLocals;
Tcl_AppendPrintfToObj(bufferObj,
" Proc %p, refCt %" TCL_SIZE_MODIFIER "d, args %" TCL_SIZE_MODIFIER "d, compiled locals %" TCL_SIZE_MODIFIER "d\n",
" Proc %p, refCt %" TCL_SIZE_MODIFIER "d, "
"args %" TCL_SIZE_MODIFIER "d, "
"compiled locals %" TCL_SIZE_MODIFIER "d\n",
procPtr, procPtr->refCount, procPtr->numArgs,
numCompiledLocals);
if (numCompiledLocals > 0) {
@@ -356,24 +367,31 @@ DisassembleByteCodeObj(
*/
if ((int)codePtr->numExceptRanges > 0) {
Tcl_AppendPrintfToObj(bufferObj, " Exception ranges %" TCL_SIZE_MODIFIER "d, depth %" TCL_SIZE_MODIFIER "d:\n",
Tcl_AppendPrintfToObj(bufferObj,
" Exception ranges %" TCL_SIZE_MODIFIER "d, "
"depth %" TCL_SIZE_MODIFIER "d:\n",
codePtr->numExceptRanges, codePtr->maxExceptDepth);
for (i = 0; i < (int)codePtr->numExceptRanges; i++) {
ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i];
Tcl_AppendPrintfToObj(bufferObj,
" %" TCL_SIZE_MODIFIER "d: level %" TCL_SIZE_MODIFIER "d, %s, pc %" TCL_SIZE_MODIFIER "d-%" TCL_SIZE_MODIFIER "d, ",
" %" TCL_SIZE_MODIFIER "d: "
"level %" TCL_SIZE_MODIFIER "d, %s, "
"pc %" TCL_SIZE_MODIFIER "d-%" TCL_SIZE_MODIFIER "d, ",
i, rangePtr->nestingLevel,
(rangePtr->type==LOOP_EXCEPTION_RANGE ? "loop" : "catch"),
rangePtr->codeOffset,
(rangePtr->codeOffset + rangePtr->numCodeBytes - 1));
switch (rangePtr->type) {
case LOOP_EXCEPTION_RANGE:
Tcl_AppendPrintfToObj(bufferObj, "continue %" TCL_SIZE_MODIFIER "d, break %" TCL_SIZE_MODIFIER "d\n",
Tcl_AppendPrintfToObj(bufferObj,
"continue %" TCL_SIZE_MODIFIER "d, "
"break %" TCL_SIZE_MODIFIER "d\n",
rangePtr->continueOffset, rangePtr->breakOffset);
break;
case CATCH_EXCEPTION_RANGE:
Tcl_AppendPrintfToObj(bufferObj, "catch %" TCL_SIZE_MODIFIER "d\n",
Tcl_AppendPrintfToObj(bufferObj,
"catch %" TCL_SIZE_MODIFIER "d\n",
rangePtr->catchOffset);
break;
default:
@@ -447,7 +465,8 @@ DisassembleByteCodeObj(
srcLengthNext++;
}
Tcl_AppendPrintfToObj(bufferObj, "%s%4" TCL_SIZE_MODIFIER "d: pc %d-%d, src %d-%d",
Tcl_AppendPrintfToObj(bufferObj,
"%s%4" TCL_SIZE_MODIFIER "d: pc %d-%d, src %d-%d",
((i % 2)? " " : "\n "),
(i+1), codeOffset, (codeOffset + codeLen - 1),
srcOffset, (srcOffset + srcLen - 1));
@@ -559,56 +578,69 @@ FormatInstruction(
for (i = 0; i < instDesc->numOperands; i++) {
switch (instDesc->opTypes[i]) {
case OPERAND_INT1:
opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++;
opnd = TclGetInt1AtPtr(pc+numBytes);
numBytes++;
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
break;
case OPERAND_INT4:
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
opnd = TclGetInt4AtPtr(pc+numBytes);
numBytes += 4;
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
break;
case OPERAND_UINT1:
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
opnd = TclGetUInt1AtPtr(pc+numBytes);
numBytes++;
Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
break;
case OPERAND_UINT4:
opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
opnd = TclGetUInt4AtPtr(pc+numBytes);
numBytes += 4;
if (opCode == INST_START_CMD) {
snprintf(suffixBuffer+strlen(suffixBuffer), sizeof(suffixBuffer) - strlen(suffixBuffer),
snprintf(suffixBuffer+strlen(suffixBuffer),
sizeof(suffixBuffer) - strlen(suffixBuffer),
", %u cmds start here", opnd);
}
Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
break;
case OPERAND_OFFSET1:
opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++;
opnd = TclGetInt1AtPtr(pc+numBytes);
numBytes++;
snprintf(suffixBuffer, sizeof(suffixBuffer), "pc %u", pcOffset+opnd);
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
break;
case OPERAND_OFFSET4:
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
opnd = TclGetInt4AtPtr(pc+numBytes);
numBytes += 4;
if (opCode == INST_START_CMD) {
snprintf(suffixBuffer, sizeof(suffixBuffer), "next cmd at pc %u", pcOffset+opnd);
snprintf(suffixBuffer, sizeof(suffixBuffer),
"next cmd at pc %u", pcOffset+opnd);
} else {
snprintf(suffixBuffer, sizeof(suffixBuffer), "pc %u", pcOffset+opnd);
snprintf(suffixBuffer, sizeof(suffixBuffer),
"pc %u", pcOffset+opnd);
}
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
break;
case OPERAND_LIT1:
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
opnd = TclGetUInt1AtPtr(pc+numBytes);
numBytes++;
suffixObj = codePtr->objArrayPtr[opnd];
Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
break;
case OPERAND_LIT4:
opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
opnd = TclGetUInt4AtPtr(pc+numBytes);
numBytes += 4;
suffixObj = codePtr->objArrayPtr[opnd];
Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
break;
case OPERAND_AUX4:
opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
opnd = TclGetUInt4AtPtr(pc+numBytes);
numBytes += 4;
Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
auxPtr = &codePtr->auxDataArrayPtr[opnd];
break;
case OPERAND_IDX4:
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
opnd = TclGetInt4AtPtr(pc+numBytes);
numBytes += 4;
if (opnd >= -1) {
Tcl_AppendPrintfToObj(bufferObj, "%d ", opnd);
} else if (opnd == -2) {
@@ -627,14 +659,16 @@ FormatInstruction(
printLVTindex:
if (localPtr != NULL) {
if (opnd >= localCt) {
Tcl_Panic("FormatInstruction: bad local var index %u (%" TCL_SIZE_MODIFIER "d locals)",
Tcl_Panic("FormatInstruction: bad local var index %u "
"(%" TCL_SIZE_MODIFIER "d locals)",
opnd, localCt);
}
for (j = 0; j < opnd; j++) {
localPtr = localPtr->nextPtr;
}
if (TclIsVarTemporary(localPtr)) {
snprintf(suffixBuffer, sizeof(suffixBuffer), "temp var %u", opnd);
snprintf(suffixBuffer, sizeof(suffixBuffer),
"temp var %u", opnd);
} else {
snprintf(suffixBuffer, sizeof(suffixBuffer), "var ");
suffixSrc = localPtr->name;
@@ -643,10 +677,57 @@ FormatInstruction(
Tcl_AppendPrintfToObj(bufferObj, "%%v%u ", opnd);
break;
case OPERAND_SCLS1:
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
opnd = TclGetUInt1AtPtr(pc+numBytes);
numBytes++;
Tcl_AppendPrintfToObj(bufferObj, "%s ",
tclStringClassTable[opnd].name);
break;
case OPERAND_UNSF1:
opnd = TclGetUInt1AtPtr(pc+numBytes);
numBytes++;
Tcl_AppendPrintfToObj(bufferObj, "silent=%s ", opnd?"no":"yes");
break;
case OPERAND_CLK1:
opnd = TclGetUInt1AtPtr(pc+numBytes);
numBytes++;
switch (opnd) {
case CLOCK_READ_CLICKS:
Tcl_AppendPrintfToObj(bufferObj, "clicks " );
break;
case CLOCK_READ_MICROS:
Tcl_AppendPrintfToObj(bufferObj, "micros " );
break;
case CLOCK_READ_MILLIS:
Tcl_AppendPrintfToObj(bufferObj, "millis " );
break;
case CLOCK_READ_SECS:
Tcl_AppendPrintfToObj(bufferObj, "secs " );
break;
default:
Tcl_Panic("unknown clock type");
}
break;
case OPERAND_LRPL1:
opnd = TclGetUInt1AtPtr(pc+numBytes);
numBytes++;
switch (opnd) {
case 0:
Tcl_AppendPrintfToObj(bufferObj, "0 ");
break;
case TCL_LREPLACE_END_IS_LAST:
Tcl_AppendPrintfToObj(bufferObj, "endLast ");
break;
case TCL_LREPLACE_SINGLE_INDEX:
Tcl_AppendPrintfToObj(bufferObj, "singleIdx ");
break;
case TCL_LREPLACE_END_IS_LAST | TCL_LREPLACE_NEED_IN_RANGE:
Tcl_AppendPrintfToObj(bufferObj, "endLast,indexTest ");
break;
default:
Tcl_AppendPrintfToObj(bufferObj, "endLast,singleIdx ");
break;
}
break;
case OPERAND_NONE:
default:
break;
@@ -746,13 +827,15 @@ TclGetInnerContext(
objc = 2;
break;
case INST_INVOKE_STK4:
objc = TclGetUInt4AtPtr(pc+1);
case INST_INVOKE_STK:
objc = TclGetUInt4AtPtr(pc + 1);
break;
#ifndef REMOVE_DEPRECATED_OPCODES
case INST_INVOKE_STK1:
objc = TclGetUInt1AtPtr(pc+1);
objc = TclGetUInt1AtPtr(pc + 1);
break;
#endif
}
result = iPtr->innerContext;
@@ -1026,6 +1109,9 @@ DisassembleByteCodeAsDicts(
val = TclGetInt1AtPtr(opnd);
opnd += 1;
goto formatNumber;
case OPERAND_UNSF1: // TODO: decode
case OPERAND_CLK1: // TODO: decode
case OPERAND_LRPL1: // TODO: decode
case OPERAND_UINT1:
val = TclGetUInt1AtPtr(opnd);
opnd += 1;
@@ -1148,14 +1234,19 @@ DisassembleByteCodeAsDicts(
switch (rangePtr->type) {
case LOOP_EXCEPTION_RANGE:
Tcl_ListObjAppendElement(NULL, exn, Tcl_ObjPrintf(
"type %s level %" TCL_SIZE_MODIFIER "d from %" TCL_SIZE_MODIFIER "d to %" TCL_SIZE_MODIFIER "d break %" TCL_SIZE_MODIFIER "d continue %" TCL_SIZE_MODIFIER "d",
"type %s level %" TCL_SIZE_MODIFIER "d "
"from %" TCL_SIZE_MODIFIER "d to %" TCL_SIZE_MODIFIER "d "
"break %" TCL_SIZE_MODIFIER "d "
"continue %" TCL_SIZE_MODIFIER "d",
"loop", rangePtr->nestingLevel, rangePtr->codeOffset,
rangePtr->codeOffset + rangePtr->numCodeBytes - 1,
rangePtr->breakOffset, rangePtr->continueOffset));
break;
case CATCH_EXCEPTION_RANGE:
Tcl_ListObjAppendElement(NULL, exn, Tcl_ObjPrintf(
"type %s level %" TCL_SIZE_MODIFIER "d from %" TCL_SIZE_MODIFIER "d to %" TCL_SIZE_MODIFIER "d catch %" TCL_SIZE_MODIFIER "d",
"type %s level %" TCL_SIZE_MODIFIER "d "
"from %" TCL_SIZE_MODIFIER "d to %" TCL_SIZE_MODIFIER "d "
"catch %" TCL_SIZE_MODIFIER "d",
"catch", rangePtr->nestingLevel, rangePtr->codeOffset,
rangePtr->codeOffset + rangePtr->numCodeBytes - 1,
rangePtr->catchOffset));
@@ -1279,9 +1370,12 @@ Tcl_DisassembleObjCmd(
Tcl_Obj *codeObjPtr = NULL;
Proc *procPtr = NULL;
Tcl_HashEntry *hPtr;
Tcl_Obj *ooWhat = NULL;
Object *oPtr;
Class *classPtr;
ByteCode *codePtr;
Method *methodPtr;
const char *bodyType;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "type ...");
@@ -1379,23 +1473,17 @@ Tcl_DisassembleObjCmd(
* 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]), (char *)NULL);
ooWhat = objv[2];
classPtr = TclOOGetClassFromObj(interp, ooWhat);
if (classPtr == NULL) {
return TCL_ERROR;
}
methodPtr = oPtr->classPtr->constructorPtr;
methodPtr = classPtr->constructorPtr;
if (methodPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" has no defined constructor",
TclGetString(objv[2])));
TclGetString(ooWhat)));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
"CONSRUCTOR", (char *)NULL);
return TCL_ERROR;
@@ -1409,30 +1497,9 @@ Tcl_DisassembleObjCmd(
return TCL_ERROR;
}
/*
* Compile if necessary.
*/
if (!TclHasInternalRep(procPtr->bodyPtr, &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;
oPtr = classPtr->thisPtr;
bodyType = "body of constructor";
goto compileMethodIfNeeded;
case DISAS_CLASS_DESTRUCTOR:
if (objc != 3) {
@@ -1444,23 +1511,17 @@ Tcl_DisassembleObjCmd(
* 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]), (char *)NULL);
ooWhat = objv[2];
classPtr = TclOOGetClassFromObj(interp, ooWhat);
if (classPtr == NULL) {
return TCL_ERROR;
}
methodPtr = oPtr->classPtr->destructorPtr;
methodPtr = classPtr->destructorPtr;
if (methodPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" has no defined destructor",
TclGetString(objv[2])));
TclGetString(ooWhat)));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
"DESRUCTOR", (char *)NULL);
return TCL_ERROR;
@@ -1474,30 +1535,9 @@ Tcl_DisassembleObjCmd(
return TCL_ERROR;
}
/*
* Compile if necessary.
*/
if (!TclHasInternalRep(procPtr->bodyPtr, &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;
oPtr = classPtr->thisPtr;
bodyType = "body of destructor";
goto compileMethodIfNeeded;
case DISAS_CLASS_METHOD:
if (objc != 4) {
@@ -1509,19 +1549,13 @@ Tcl_DisassembleObjCmd(
* Look up the body of a class method.
*/
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
if (oPtr == NULL) {
ooWhat = objv[3];
classPtr = TclOOGetClassFromObj(interp, objv[2]);
if (classPtr == 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]), (char *)NULL);
return TCL_ERROR;
}
hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods,
objv[3]);
oPtr = classPtr->thisPtr;
hPtr = Tcl_FindHashEntry(&classPtr->classMethods, ooWhat);
goto methodBody;
case DISAS_OBJECT_METHOD:
if (objc != 4) {
@@ -1533,14 +1567,16 @@ Tcl_DisassembleObjCmd(
* Look up the body of an instance method.
*/
ooWhat = objv[3];
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
if (oPtr == NULL) {
return TCL_ERROR;
}
ooWhat = objv[3];
if (oPtr->methodsPtr == NULL) {
goto unknownMethod;
}
hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, objv[3]);
hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, ooWhat);
/*
* Compile (if necessary) and disassemble a method body.
@@ -1550,9 +1586,9 @@ Tcl_DisassembleObjCmd(
if (hPtr == NULL) {
unknownMethod:
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"unknown method \"%s\"", TclGetString(objv[3])));
"unknown method \"%s\"", TclGetString(ooWhat)));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
TclGetString(objv[3]), (char *)NULL);
TclGetString(ooWhat), (char *)NULL);
return TCL_ERROR;
}
procPtr = TclOOGetProcFromMethod((Method *)Tcl_GetHashValue(hPtr));
@@ -1563,6 +1599,9 @@ Tcl_DisassembleObjCmd(
"METHODTYPE", (char *)NULL);
return TCL_ERROR;
}
bodyType = "body of method";
compileMethodIfNeeded:
if (!TclHasInternalRep(procPtr->bodyPtr, &tclByteCodeType)) {
Command cmd;
@@ -1574,8 +1613,8 @@ Tcl_DisassembleObjCmd(
cmd.nsPtr = (Namespace *) oPtr->namespacePtr;
procPtr->cmdPtr = &cmd;
result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr,
(Namespace *) oPtr->namespacePtr, "body of method",
TclGetString(objv[3]));
(Namespace *) oPtr->namespacePtr, bodyType,
TclGetString(ooWhat));
procPtr->cmdPtr = NULL;
if (result != TCL_OK) {
return result;
@@ -1584,7 +1623,7 @@ Tcl_DisassembleObjCmd(
codeObjPtr = procPtr->bodyPtr;
break;
default:
CLANG_ASSERT(0);
TCL_UNREACHABLE();
}
/*
+304 -70
View File
@@ -11,6 +11,7 @@
#include "tclInt.h"
#include <assert.h>
#include "../utf8proc/utf8proc.h" /* Relative path to ignore system include */
typedef size_t (LengthProc)(const char *src);
@@ -881,7 +882,7 @@ Tcl_GetEncodingNames(
Tcl_HashEntry *hPtr;
Tcl_Obj *map, *name, *result;
Tcl_DictSearch mapSearch;
int dummy, done = 0;
int done = 0;
TclNewObj(result);
Tcl_InitObjHashTable(&table);
@@ -896,7 +897,7 @@ Tcl_GetEncodingNames(
Encoding *encodingPtr = (Encoding *)Tcl_GetHashValue(hPtr);
Tcl_CreateHashEntry(&table,
Tcl_NewStringObj(encodingPtr->name, TCL_INDEX_NONE), &dummy);
Tcl_NewStringObj(encodingPtr->name, TCL_INDEX_NONE), NULL);
}
Tcl_MutexUnlock(&encodingMutex);
@@ -909,7 +910,7 @@ Tcl_GetEncodingNames(
Tcl_DictObjFirst(NULL, map, &mapSearch, &name, NULL, &done);
for (; !done; Tcl_DictObjNext(&mapSearch, &name, NULL, &done)) {
Tcl_CreateHashEntry(&table, name, &dummy);
Tcl_CreateHashEntry(&table, name, NULL);
}
/*
@@ -969,9 +970,11 @@ Tcl_GetEncodingNulLength(
* unless interp was NULL.
*
* Side effects:
* The reference count of the new system encoding is incremented. The
* reference count of the old system encoding is decremented and it may
* be freed. All VFS cached information is invalidated.
* If the passed encoding is the same as the current system
* encoding, the call is effectively a no-op. Otherwise, the reference
* count of the new system encoding is incremented. The reference count
* of the old system encoding is decremented and it may be freed. All
* VFS cached information is invalidated.
*
*------------------------------------------------------------------------
*/
@@ -983,25 +986,34 @@ Tcl_SetSystemEncoding(
* to reset to default encoding. */
{
Tcl_Encoding encoding;
Encoding *encodingPtr;
if (!name || !*name) {
Tcl_MutexLock(&encodingMutex);
Tcl_MutexLock(&encodingMutex);
if (name == NULL || name[0] == '\0') {
if (defaultEncoding == systemEncoding) {
Tcl_MutexUnlock(&encodingMutex);
return TCL_OK;
}
encoding = defaultEncoding;
encodingPtr = (Encoding *) encoding;
encodingPtr->refCount++;
Tcl_MutexUnlock(&encodingMutex);
((Encoding *)encoding)->refCount += 1;
} else {
encoding = Tcl_GetEncoding(interp, name);
if (encoding == NULL) {
Tcl_MutexUnlock(&encodingMutex);
return TCL_ERROR;
}
if (encoding == systemEncoding) {
FreeEncoding(encoding);
Tcl_MutexUnlock(&encodingMutex);
return TCL_OK;
}
}
Tcl_MutexLock(&encodingMutex);
assert(encoding != systemEncoding);
FreeEncoding(systemEncoding);
systemEncoding = encoding;
Tcl_MutexUnlock(&encodingMutex);
/* Checks above ensure this is only called when system encoding changes */
Tcl_FSMountsChanged(NULL);
return TCL_OK;
@@ -1228,7 +1240,7 @@ Tcl_ExternalToUtfDStringEx(
* and loop. Otherwise, return the result we got.
*/
if ((result != TCL_CONVERT_NOSPACE) &&
!(result == TCL_CONVERT_MULTIBYTE && (flags & TCL_ENCODING_END))) {
(result != TCL_CONVERT_MULTIBYTE || (flags & TCL_ENCODING_END))) {
Tcl_Size nBytesProcessed = (src - srcStart);
Tcl_DStringSetLength(dstPtr, soFar);
@@ -1544,7 +1556,7 @@ Tcl_UtfToExternalDStringEx(
* and loop. Otherwise, return the result we got.
*/
if ((result != TCL_CONVERT_NOSPACE) &&
!(result == TCL_CONVERT_MULTIBYTE && (flags & TCL_ENCODING_END))) {
(result != TCL_CONVERT_MULTIBYTE || (flags & TCL_ENCODING_END))) {
Tcl_Size nBytesProcessed = (src - srcStart);
Tcl_Size i = soFar + encodingPtr->nullSize - 1;
/* Loop as DStringSetLength only stores one nul byte at a time */
@@ -1953,22 +1965,22 @@ LoadTableEncoding(
*/
static const char staticHex[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 ... 15 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 ... 31 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32 ... 47 */
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 48 ... 63 */
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 64 ... 79 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 ... 95 */
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 96 ... 111 */
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 112 ... 127 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128 ... 143 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144 ... 159 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 160 ... 175 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 176 ... 191 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192 ... 207 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 208 ... 223 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 224 ... 239 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 240 ... 255 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 ... 15 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 ... 31 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32 ... 47 */
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 48 ... 63 */
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 64 ... 79 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 ... 95 */
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 96 ... 111 */
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 112 ... 127 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128 ... 143 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144 ... 159 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 160 ... 175 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 176 ... 191 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192 ... 207 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 208 ... 223 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 224 ... 239 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 240 ... 255 */
};
Tcl_DStringInit(&lineString);
@@ -2481,19 +2493,19 @@ UtfToUtfProc(
* by a low surrogate. NOT to be called for strict profile since
* that should raise an error.
*/
#define OUTPUT_ISOLATEDSURROGATE \
do { \
Tcl_UniChar high; \
if (PROFILE_REPLACE(profile)) { \
high = UNICODE_REPLACE_CHAR; \
} else { \
high = (Tcl_UniChar)(ptrdiff_t) *statePtr; \
} \
assert(!(flags & ENCODING_UTF)); /* Must be CESU-8 */ \
assert(HIGH_SURROGATE(high)); \
assert(!PROFILE_STRICT(profile)); \
dst += Tcl_UniCharToUtf(high, dst); \
*statePtr = 0; /* Reset state */ \
#define OUTPUT_ISOLATEDSURROGATE() \
do { \
Tcl_UniChar high; \
if (PROFILE_REPLACE(profile)) { \
high = UNICODE_REPLACE_CHAR; \
} else { \
high = (Tcl_UniChar)(ptrdiff_t) *statePtr; \
} \
assert(!(flags & ENCODING_UTF)); /* Must be CESU-8 */ \
assert(HIGH_SURROGATE(high)); \
assert(!PROFILE_STRICT(profile)); \
dst += Tcl_UniCharToUtf(high, dst); \
*statePtr = 0; /* Reset state */ \
} while (0)
/*
@@ -2501,20 +2513,19 @@ UtfToUtfProc(
* an error if profile is strict, or output an appropriate
* character for replace and tcl8 profiles and continue.
*/
#define CHECK_ISOLATEDSURROGATE \
if (*statePtr) { \
if (PROFILE_STRICT(profile)) { \
result = TCL_CONVERT_SYNTAX; \
break; \
} \
OUTPUT_ISOLATEDSURROGATE; \
continue; /* Rerun loop so length checks etc. repeated */ \
} else \
#define CHECK_ISOLATEDSURROGATE() \
if (*statePtr) { \
if (PROFILE_STRICT(profile)) { \
result = TCL_CONVERT_SYNTAX; \
break; \
} \
OUTPUT_ISOLATEDSURROGATE(); \
continue; /* Rerun loop so length checks etc. repeated */ \
} else \
(void) 0
profile = ENCODING_PROFILE_GET(flags);
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
/*
* If there is more string to follow, this will ensure that the
@@ -2529,19 +2540,18 @@ UtfToUtfProc(
break;
}
if (UCHAR(*src) < 0x80 && !((UCHAR(*src) == 0) && (flags & ENCODING_INPUT))) {
CHECK_ISOLATEDSURROGATE;
CHECK_ISOLATEDSURROGATE();
/*
* Copy 7bit characters, but skip null-bytes when we are in input
* mode, so that they get converted to \xC0\x80.
*/
*dst++ = *src++;
} else if ((UCHAR(*src) == 0xC0) && (src + 1 < srcEnd) &&
(UCHAR(src[1]) == 0x80) &&
(!(flags & ENCODING_INPUT) || !PROFILE_TCL8(profile))) {
(UCHAR(src[1]) == 0x80) &&
(!(flags & ENCODING_INPUT) || !PROFILE_TCL8(profile))) {
/* Special sequence \xC0\x80 */
CHECK_ISOLATEDSURROGATE;
CHECK_ISOLATEDSURROGATE();
if (!PROFILE_TCL8(profile) && (flags & ENCODING_INPUT)) {
if (PROFILE_REPLACE(profile)) {
dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst);
@@ -2567,7 +2577,7 @@ UtfToUtfProc(
* because the UTF-8 sequence is truncated.
*/
CHECK_ISOLATEDSURROGATE;
CHECK_ISOLATEDSURROGATE();
if (flags & ENCODING_INPUT) {
/* Incomplete bytes for modified UTF-8 target */
@@ -2584,7 +2594,8 @@ UtfToUtfProc(
} else {
/* TCL_ENCODING_PROFILE_TCL8 */
char chbuf[2];
chbuf[0] = UCHAR(*src++); chbuf[1] = 0;
chbuf[0] = UCHAR(*src++);
chbuf[1] = 0;
TclUtfToUniChar(chbuf, &ch);
}
dst += Tcl_UniCharToUtf(ch, dst);
@@ -2610,8 +2621,8 @@ UtfToUtfProc(
src += len;
if (!(flags & ENCODING_UTF) && !(flags & ENCODING_INPUT)
&& (ch > 0x7FF)) {
assert(savedSurrogate == 0); /* Since this flag combo
will never set *statePtr */
assert(savedSurrogate == 0); /* Since this flag combo
* will never set *statePtr */
if (ch > 0xFFFF) {
/* CESU-8 6-byte sequence for chars > U+FFFF */
ch -= 0x10000;
@@ -2629,7 +2640,7 @@ UtfToUtfProc(
/* UTF-8, not CESU-8, so surrogates should not appear */
if (PROFILE_STRICT(profile)) {
result = (flags & ENCODING_INPUT)
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
src = saveSrc;
break;
} else if (PROFILE_REPLACE(profile)) {
@@ -2647,7 +2658,7 @@ UtfToUtfProc(
/* Isolated low surrogate */
if (PROFILE_STRICT(profile)) {
result = (flags & ENCODING_INPUT)
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
src = saveSrc;
break;
} else if (PROFILE_REPLACE(profile)) {
@@ -2664,7 +2675,7 @@ UtfToUtfProc(
assert(HIGH_SURROGATE(savedSurrogate));
if (PROFILE_STRICT(profile)) {
result = (flags & ENCODING_INPUT)
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
src = saveSrc;
break;
} else if (PROFILE_REPLACE(profile)) {
@@ -2682,7 +2693,7 @@ UtfToUtfProc(
}
} else {
/* Normal character */
CHECK_ISOLATEDSURROGATE;
CHECK_ISOLATEDSURROGATE();
}
dst += Tcl_UniCharToUtf(ch, dst);
@@ -2698,7 +2709,7 @@ UtfToUtfProc(
/* No more data coming */
if (PROFILE_STRICT(profile)) {
result = (flags & ENCODING_INPUT)
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
} else {
if (PROFILE_REPLACE(profile)) {
ch = UNICODE_REPLACE_CHAR;
@@ -3510,7 +3521,8 @@ TableToUtfProc(
ch = UNICODE_REPLACE_CHAR;
} else {
char chbuf[2];
chbuf[0] = byte; chbuf[1] = 0;
chbuf[0] = byte;
chbuf[1] = 0;
TclUtfToUniChar(chbuf, &ch);
}
}
@@ -4067,6 +4079,30 @@ EscapeToUtfProc(
numChars++;
}
if ((flags & TCL_ENCODING_END) && (result == TCL_CONVERT_MULTIBYTE)) {
/* We have a code fragment left-over at the end */
if (dst > dstEnd) {
result = TCL_CONVERT_NOSPACE;
} else {
/* destination is not full, so we really are at the end now */
if (PROFILE_STRICT(flags)) {
result = TCL_CONVERT_SYNTAX;
} else {
/*
* PROFILE_REPLACE or PROFILE_TCL8. The latter is treated
* similar to former because Tcl8 was broken in this regard
* as it just ignored the byte and truncated which is really
* a no-no as per Unicode recommendations.
*/
result = TCL_OK;
dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst);
numChars++;
/* TCL_CONVERT_MULTIBYTE means all source consumed */
src = srcEnd;
}
}
}
*statePtr = (Tcl_EncodingState) INT2PTR(state);
*srcReadPtr = src - srcStart;
*dstWrotePtr = dst - dstStart;
@@ -4612,7 +4648,205 @@ TclGetEncodingProfiles(
}
Tcl_SetObjResult(interp, objPtr);
}
static utf8proc_ssize_t
TclUtfNormalize(
Tcl_Interp *interp, /* Error messages. May be NULL */
const char *bytes, /* Operand encoded in Tcl internal UTF8 */
Tcl_Size numBytes, /* Length bytes[], or -1 if NUL terminated */
Tcl_Encoding encoding, /* Encoding - must be UTF-8. Caller passed for reuse */
Tcl_UnicodeNormalizationForm normForm, /* TCL_{NFC,NFD,NFKC,NFKC} */
int profile, /* TCL_ENCODING_PROFILE_{STRICT,REPLACE} */
utf8proc_uint8_t **bufPtrPtr) /* On success, output length excluding nul */
{
if (profile != TCL_ENCODING_PROFILE_REPLACE &&
profile != TCL_ENCODING_PROFILE_STRICT) {
if (interp) {
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("Invalid value %d passed for encoding profile.",
profile));
}
return -1;
}
utf8proc_option_t options = UTF8PROC_STABLE;
switch (normForm) {
case TCL_NFC:
options |= UTF8PROC_COMPOSE;
break;
case TCL_NFD:
options |= UTF8PROC_DECOMPOSE;
break;
case TCL_NFKC:
options |= UTF8PROC_COMPOSE | UTF8PROC_COMPAT;
break;
case TCL_NFKD:
options |= UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT;
break;
default:
if (interp) {
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("Invalid value %d passed for normalization form.",
normForm));
}
return -1;
}
if (numBytes < 0) {
numBytes = -1;
}
int result;
Tcl_DString dsExt;
result = Tcl_UtfToExternalDStringEx(interp, encoding, bytes, numBytes,
profile, &dsExt, NULL);
/* !!! dsExt needs to be freed even in case of error returns */
utf8proc_ssize_t normLength = -1;
if (result == TCL_OK) {
normLength =
utf8proc_map_custom((utf8proc_uint8_t *)Tcl_DStringValue(&dsExt),
Tcl_DStringLength(&dsExt), bufPtrPtr, options, NULL, NULL);
if (normLength < 0) {
if (interp) {
const char *errorMsg = utf8proc_errmsg(normLength);
Tcl_SetObjResult(interp,
Tcl_NewStringObj(
errorMsg ? errorMsg : "Unicode normalization failed.",
-1));
}
}
}
Tcl_DStringFree(&dsExt);
return normLength;
}
/*
* Tcl_UtfToNormalizedDString --
*
* Converts the passed string to a Unicode normalization form storing
* it in dsPtr.
*
* Results:
* A standard Tcl error code.
*
* Side effects:
* The output string is stored in dsPtr, which is initialized.
*/
int
Tcl_UtfToNormalizedDString(
Tcl_Interp *interp, /* Used for error messages. May be NULL */
const char *bytes, /* Operand encoded in Tcl internal UTF8 */
Tcl_Size numBytes, /* Length of bytes[], or -1 if NUL terminated */
Tcl_UnicodeNormalizationForm normForm, /* TCL_{NFC,NFD,NFKC,NFKC} */
int profile, /* TCL_ENCODING_PROFILE_{STRICT,REPLACE} */
Tcl_DString *dsPtr) /* Converted output string in Tcl internal
* UTF8 encoding. Init'ed by function */
{
Tcl_DStringInit(dsPtr);
Tcl_Encoding encoding = Tcl_GetEncoding(interp, "utf-8");
if (encoding == NULL) {
return TCL_ERROR;
}
utf8proc_uint8_t *normUtf8;
utf8proc_ssize_t normLength;
normLength = TclUtfNormalize(interp, bytes, numBytes, encoding, normForm,
profile, &normUtf8);
if (normLength >= 0) {
assert(normUtf8);
/* Convert standard UTF8 to internal UTF8 */
int result = Tcl_ExternalToUtfDStringEx(interp, encoding,
(const char *)normUtf8, normLength, profile, dsPtr, NULL);
if (result != TCL_OK) {
normLength = -1;
}
free(normUtf8); /* NOT Tcl_Free! */
}
Tcl_FreeEncoding(encoding);
return normLength >= 0 ? TCL_OK : TCL_ERROR;
}
/*
* Tcl_UtfToNormalized --
*
* Converts the passed string to a Unicode normalization form storing
* it in the caller provided buffer.
*
* Results:
* A standard Tcl error code.
*
* Side effects:
* The output string is stored in bufPtr.
*/
int
Tcl_UtfToNormalized(
Tcl_Interp *interp, /* Used for error messages. May be NULL */
const char *bytes, /* Operand encoded in Tcl internal UTF8 */
Tcl_Size numBytes, /* Length of bytes[], or -1 if NUL terminated */
Tcl_UnicodeNormalizationForm normForm, /* TCL_{NFC,NFD,NFKC,NFKC} */
int profile, /* TCL_ENCODING_PROFILE_{STRICT,REPLACE} */
char *bufPtr, /* Pointer to output buffer. Must not be NULL. */
Tcl_Size bufLen, /* Size of bufPtr storage. */
Tcl_Size *lengthPtr) /* Length of the output string in bytes excluding
* the trailing NUL byte. May be NULL */
{
Tcl_Encoding encoding = Tcl_GetEncoding(interp, "utf-8");
if (encoding == NULL) {
return TCL_ERROR;
}
utf8proc_uint8_t *normUtf8;
utf8proc_ssize_t normLength;
normLength = TclUtfNormalize(interp, bytes, numBytes, encoding, normForm,
profile, &normUtf8);
Tcl_FreeEncoding(encoding);
if (normLength < 0) {
return TCL_ERROR;
}
assert(normUtf8);
/* Convert standard UTF8 to internal UTF8 */
int result;
utf8proc_uint8_t *from = normUtf8;
utf8proc_uint8_t *fromEnd = from + normLength;
char *to = bufPtr;
char *toEnd = to + bufLen - 1; /* -1 for trailing NUL */
while (from < fromEnd && to < toEnd) {
/*
* The only difference between UTF-8 and internal UTF-8 is that
* internal UTF-8 does not allow NUL bytes in the middle of the string.
*/
if (*from) {
*to++ = *from++;
} else {
*to++ = 0xC0; /* NUL byte in internal UTF-8 is encoded as C080 */
if (to == toEnd) {
break;
}
*to++ = 0x80;
from++;
}
}
if (from < fromEnd) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("Output buffer too small.", -1));
result = TCL_CONVERT_NOSPACE;
} else {
assert(to <= toEnd);
*to = '\0'; /* NUL terminate the output */
if (lengthPtr) {
*lengthPtr = to-bufPtr;
}
result = TCL_OK;
}
free(normUtf8); /* NOT Tcl_Free! */
return result;
}
/*
* Local Variables:
* mode: c
+19 -33
View File
@@ -230,9 +230,8 @@ TclNamespaceEnsembleCmd(
}
default:
Tcl_Panic("unexpected ensemble command");
TCL_UNREACHABLE();
}
return TCL_OK;
}
/*
@@ -387,6 +386,8 @@ InitEnsembleFromOptions(
}
unknownObj = (len > 0 ? objv[1] : NULL);
continue;
default:
TCL_UNREACHABLE();
}
}
@@ -485,6 +486,8 @@ ReadOneEnsembleOption(
Tcl_SetObjResult(interp, resultObj);
}
break;
default:
TCL_UNREACHABLE();
}
return TCL_OK;
}
@@ -715,6 +718,8 @@ SetEnsembleConfigOptions(
}
unknownObj = (len > 0 ? objv[1] : NULL);
continue;
default:
TCL_UNREACHABLE();
}
}
@@ -2744,7 +2749,7 @@ BuildEnsembleConfig(
while (!done) {
const char *name = TclGetString(keyObj);
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
hPtr = Tcl_CreateHashEntry(hash, name, NULL);
Tcl_SetHashValue(hPtr, valueObj);
Tcl_IncrRefCount(valueObj);
Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
@@ -3255,18 +3260,7 @@ TclCompileEnsemble(
* Throw out any line information generated by the failed compile attempt.
*/
while (mapPtr->nuloc > eclIndex + 1) {
mapPtr->nuloc--;
Tcl_Free(mapPtr->loc[mapPtr->nuloc].line);
mapPtr->loc[mapPtr->nuloc].line = NULL;
}
/*
* Reset the index of next command. Toss out any from failed nested
* partial compiles.
*/
envPtr->numCommands = mapPtr->nuloc;
ClearFailedCompile(envPtr);
/*
* Failed to do a full compile for some reason. Try to do a direct invoke
@@ -3326,7 +3320,7 @@ TclAttemptCompileProc(
Tcl_Size i;
Tcl_Token *saveTokenPtr = parsePtr->tokenPtr;
Tcl_Size savedStackDepth = envPtr->currStackDepth;
Tcl_Size savedCodeNext = envPtr->codeNext - envPtr->codeStart;
Tcl_Size savedCodeNext = CurrentOffset(envPtr);
Tcl_Size savedAuxDataArrayNext = envPtr->auxDataArrayNext;
Tcl_Size savedExceptArrayNext = envPtr->exceptArrayNext;
#ifdef TCL_COMPILE_DEBUG
@@ -3354,8 +3348,8 @@ TclAttemptCompileProc(
* index values.
*/
mapPtr->loc[eclIndex].line += (depth - 1);
mapPtr->loc[eclIndex].next += (depth - 1);
ExtCmdLocation.line += (depth - 1);
ExtCmdLocation.next += (depth - 1);
/*
* Hand off compilation to the subcommand compiler. At last!
@@ -3367,8 +3361,8 @@ TclAttemptCompileProc(
* Undo the shift.
*/
mapPtr->loc[eclIndex].line -= (depth - 1);
mapPtr->loc[eclIndex].next -= (depth - 1);
ExtCmdLocation.line -= (depth - 1);
ExtCmdLocation.next -= (depth - 1);
parsePtr->numWords += (depth - 1);
parsePtr->tokenPtr = saveTokenPtr;
@@ -3458,9 +3452,8 @@ CompileToInvokedCommand(
DefineLineInformation;
Tcl_Token *tokPtr;
Tcl_Obj *objPtr, **words;
const char *bytes;
int cmdLit, extraLiteralFlags = LITERAL_CMD_NAME;
Tcl_Size i, numWords, length;
Tcl_Size i, numWords;
/*
* Push the words of the command. Take care; the command words may be
@@ -3472,15 +3465,13 @@ CompileToInvokedCommand(
for (i = 0, tokPtr = parsePtr->tokenPtr; i < parsePtr->numWords;
i++, tokPtr = TokenAfter(tokPtr)) {
if (i > 0 && i <= numWords) {
bytes = TclGetStringFromObj(words[i - 1], &length);
PushLiteral(envPtr, bytes, length);
PUSH_OBJ( words[i - 1]);
continue;
}
SetLineInformation(i);
if (tokPtr->type == TCL_TOKEN_SIMPLE_WORD) {
int literal = TclRegisterLiteral(envPtr,
tokPtr[1].start, tokPtr[1].size, 0);
int literal = PUSH_SIMPLE_TOKEN(tokPtr);
if (envPtr->clNext) {
TclContinuationsEnterDerived(
@@ -3488,7 +3479,6 @@ CompileToInvokedCommand(
tokPtr[1].start - envPtr->source,
envPtr->clNext);
}
TclEmitPush(literal, envPtr);
} else {
CompileTokens(envPtr, tokPtr, interp);
}
@@ -3501,21 +3491,17 @@ CompileToInvokedCommand(
TclNewObj(objPtr);
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr);
bytes = TclGetStringFromObj(objPtr, &length);
if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) {
extraLiteralFlags |= LITERAL_UNSHARED;
}
cmdLit = TclRegisterLiteral(envPtr, bytes, length, extraLiteralFlags);
cmdLit = PUSH_OBJ_FLAGS(objPtr, extraLiteralFlags);
TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLit), cmdPtr);
TclEmitPush(cmdLit, envPtr);
TclDecrRefCount(objPtr);
/*
* Do the replacing dispatch.
*/
TclEmitInvoke(envPtr, INST_INVOKE_REPLACE, parsePtr->numWords,
numWords + 1);
INVOKE41( INVOKE_REPLACE, parsePtr->numWords, numWords+1);
}
/*
+16 -7
View File
@@ -35,6 +35,13 @@ typedef struct BgError {
* list. */
} BgError;
/*
* The assoc data key used in this file. The data associated with it is a
* reference to an ErrAssocData structure, and will be deallocated with
* BgErrorDeleteProc at the appropriate time.
*/
#define ASSOC_KEY "tclBgError"
/*
* One of the structures below is associated with the "tclBgError" assoc data
* for each interpreter. It keeps track of the head and tail of the list of
@@ -182,7 +189,7 @@ Tcl_BackgroundException(
errPtr->nextPtr = NULL;
(void) TclGetBgErrorHandler(interp);
assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, "tclBgError", NULL);
assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
if (assocPtr->firstBgPtr == NULL) {
assocPtr->firstBgPtr = errPtr;
Tcl_DoWhenIdle(HandleBgErrors, assocPtr);
@@ -522,7 +529,7 @@ TclSetBgErrorHandler(
Tcl_Interp *interp,
Tcl_Obj *cmdPrefix)
{
ErrAssocData *assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, "tclBgError", NULL);
ErrAssocData *assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
if (cmdPrefix == NULL) {
Tcl_Panic("TclSetBgErrorHandler: NULL cmdPrefix argument");
@@ -537,7 +544,7 @@ TclSetBgErrorHandler(
assocPtr->cmdPrefix = NULL;
assocPtr->firstBgPtr = NULL;
assocPtr->lastBgPtr = NULL;
Tcl_SetAssocData(interp, "tclBgError", BgErrorDeleteProc, assocPtr);
Tcl_SetAssocData(interp, ASSOC_KEY, BgErrorDeleteProc, assocPtr);
}
if (assocPtr->cmdPrefix) {
Tcl_DecrRefCount(assocPtr->cmdPrefix);
@@ -567,14 +574,14 @@ Tcl_Obj *
TclGetBgErrorHandler(
Tcl_Interp *interp)
{
ErrAssocData *assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, "tclBgError", NULL);
ErrAssocData *assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
if (assocPtr == NULL) {
Tcl_Obj *bgerrorObj;
TclNewLiteralStringObj(bgerrorObj, "::tcl::Bgerror");
TclSetBgErrorHandler(interp, bgerrorObj);
assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, "tclBgError", NULL);
assocPtr = (ErrAssocData *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
}
return assocPtr->cmdPrefix;
}
@@ -1650,6 +1657,8 @@ Tcl_VwaitObjCmd(
vwaitItems[numItems].sourceObj = objv[i];
numItems++;
break;
default:
TCL_UNREACHABLE();
}
}
@@ -1725,7 +1734,7 @@ Tcl_VwaitObjCmd(
foundEvent = 1;
while (!timedOut && foundEvent &&
((!any && (done < numItems)) || (any && !done))) {
((!any && (done < numItems)) || (any && !done))) {
foundEvent = Tcl_DoOneEvent(mask);
if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
break;
@@ -1967,7 +1976,7 @@ Tcl_UpdateObjCmd(
flags = TCL_IDLE_EVENTS|TCL_DONT_WAIT;
break;
default:
Tcl_Panic("Tcl_UpdateObjCmd: bad option index to UpdateOptions");
TCL_UNREACHABLE();
}
} else {
Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?");
+1861 -1268
View File
File diff suppressed because it is too large Load Diff
+37 -43
View File
@@ -26,6 +26,34 @@ static int FileCopyRename(Tcl_Interp *interp,
static int FileForceOption(Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[], int *forcePtr);
/*
*---------------------------------------------------------------------------
*
* CheckFilenameEncodable
*
* This checks if a filename can be encoded on the target platform,
* disallowing things like naked surrogates, etc.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* May update the interpreter result with an error message on failure.
*
*---------------------------------------------------------------------------
*/
static inline int
CheckFilenameEncodable(
Tcl_Interp *interp,
Tcl_Obj *fileName)
{
Tcl_DString ds;
int code = Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING,
TclGetString(fileName), TCL_INDEX_NONE, 0, &ds, NULL);
Tcl_DStringFree(&ds);
return code == TCL_OK ? TCL_OK : TCL_ERROR;
}
/*
*---------------------------------------------------------------------------
*
@@ -113,7 +141,6 @@ FileCopyRename(
int i, result, force;
Tcl_StatBuf statBuf;
Tcl_Obj *target;
Tcl_DString ds;
i = FileForceOption(interp, objc - 1, objv + 1, &force);
if (i < 0) {
@@ -135,12 +162,9 @@ FileCopyRename(
if (Tcl_FSConvertToPathType(interp, target) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(target),
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
Tcl_DStringFree(&ds);
if (CheckFilenameEncodable(interp, target) != TCL_OK) {
return TCL_ERROR;
}
Tcl_DStringFree(&ds);
result = TCL_OK;
@@ -232,7 +256,6 @@ TclFileMakeDirsCmd(
Tcl_Obj *split = NULL;
Tcl_Obj *target = NULL;
Tcl_StatBuf statBuf;
Tcl_DString ds;
result = TCL_OK;
for (i = 1; i < objc; i++) {
@@ -240,13 +263,10 @@ TclFileMakeDirsCmd(
result = TCL_ERROR;
break;
}
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[i]),
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
Tcl_DStringFree(&ds);
if (CheckFilenameEncodable(interp, objv[i]) != TCL_OK) {
result = TCL_ERROR;
break;
}
Tcl_DStringFree(&ds);
split = Tcl_FSSplitPath(objv[i], &pobjc);
Tcl_IncrRefCount(split);
@@ -362,7 +382,6 @@ TclFileDeleteCmd(
int i, force, result;
Tcl_Obj *errfile;
Tcl_Obj *errorBuffer = NULL;
Tcl_DString ds;
i = FileForceOption(interp, objc - 1, objv + 1, &force);
if (i < 0) {
@@ -380,13 +399,10 @@ TclFileDeleteCmd(
result = TCL_ERROR;
goto done;
}
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[i]),
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
Tcl_DStringFree(&ds);
if (CheckFilenameEncodable(interp, objv[i]) != TCL_OK) {
result = TCL_ERROR;
goto done;
}
Tcl_DStringFree(&ds);
/*
* Call lstat() to get info so can delete symbolic link itself.
@@ -506,26 +522,19 @@ CopyRenameOneFile(
Tcl_Obj *actualSource=NULL; /* If source is a link, then this is the real
* file/directory. */
Tcl_StatBuf sourceStatBuf, targetStatBuf;
Tcl_DString ds;
if (Tcl_FSConvertToPathType(interp, source) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(source),
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
Tcl_DStringFree(&ds);
if (CheckFilenameEncodable(interp, source) != TCL_OK) {
return TCL_ERROR;
}
Tcl_DStringFree(&ds);
if (Tcl_FSConvertToPathType(interp, target) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(target),
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
Tcl_DStringFree(&ds);
if (CheckFilenameEncodable(interp, target) != TCL_OK) {
return TCL_ERROR;
}
Tcl_DStringFree(&ds);
errfile = NULL;
errorBuffer = NULL;
@@ -985,7 +994,6 @@ TclFileAttrsCmd(
Tcl_Obj *objStrings = NULL;
Tcl_Size numObjStrings = TCL_INDEX_NONE;
Tcl_Obj *filePtr;
Tcl_DString ds;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "name ?-option value ...?");
@@ -996,12 +1004,9 @@ TclFileAttrsCmd(
if (Tcl_FSConvertToPathType(interp, filePtr) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(filePtr),
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
Tcl_DStringFree(&ds);
if (CheckFilenameEncodable(interp, filePtr) != TCL_OK) {
return TCL_ERROR;
}
Tcl_DStringFree(&ds);
objc -= 2;
objv += 2;
@@ -1204,7 +1209,6 @@ TclFileLinkCmd(
{
Tcl_Obj *contents;
int index;
Tcl_DString ds;
if (objc < 2 || objc > 4) {
Tcl_WrongNumArgs(interp, 1, objv, "?-linktype? linkname ?target?");
@@ -1247,12 +1251,9 @@ TclFileLinkCmd(
if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[index]),
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
Tcl_DStringFree(&ds);
if (CheckFilenameEncodable(interp, objv[index]) != TCL_OK) {
return TCL_ERROR;
}
Tcl_DStringFree(&ds);
/*
* Create link from source to target.
@@ -1310,12 +1311,9 @@ TclFileLinkCmd(
if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[index]),
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
Tcl_DStringFree(&ds);
if (CheckFilenameEncodable(interp, objv[index]) != TCL_OK) {
return TCL_ERROR;
}
Tcl_DStringFree(&ds);
/*
* Read link
@@ -1367,7 +1365,6 @@ TclFileReadLinkCmd(
Tcl_Obj *const objv[])
{
Tcl_Obj *contents;
Tcl_DString ds;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "name");
@@ -1377,12 +1374,9 @@ TclFileReadLinkCmd(
if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[1]),
TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
Tcl_DStringFree(&ds);
if (CheckFilenameEncodable(interp, objv[1]) != TCL_OK) {
return TCL_ERROR;
}
Tcl_DStringFree(&ds);
contents = Tcl_FSLink(objv[1], NULL, 0);
+2
View File
@@ -1233,6 +1233,8 @@ Tcl_GlobObjCmd(
case GLOB_LAST: /* -- */
i++;
goto endOfForLoop;
default:
TCL_UNREACHABLE();
}
}
+75 -45
View File
@@ -13,6 +13,12 @@
#include "tclInt.h"
/*
* Prevent macros from clashing with function definitions.
*/
#undef Tcl_CreateHashEntry
/*
* When there are this many entries per bucket, on average, rebuild the hash
* table to make it larger.
@@ -49,12 +55,13 @@ static Tcl_HashEntry * AllocStringEntry(Tcl_HashTable *tablePtr,
* Function prototypes for static functions in this file:
*/
static Tcl_HashEntry * BogusFind(Tcl_HashTable *tablePtr, const char *key);
static Tcl_HashEntry * BogusCreate(Tcl_HashTable *tablePtr, const char *key,
int *newPtr);
static Tcl_HashEntry * CreateHashEntry(Tcl_HashTable *tablePtr, const char *key,
int *newPtr);
#ifndef TCL_NO_DEPRECATED
static Tcl_HashEntry * FindHashEntry(Tcl_HashTable *tablePtr, const char *key);
#endif
static void RebuildTable(Tcl_HashTable *tablePtr);
const Tcl_HashKeyType tclArrayHashKeyType = {
@@ -164,7 +171,9 @@ Tcl_InitCustomHashTable(
tablePtr->downShift = 28;
tablePtr->mask = 3;
tablePtr->keyType = keyType;
#ifndef TCL_NO_DEPRECATED
tablePtr->findProc = FindHashEntry;
#endif
tablePtr->createProc = CreateHashEntry;
if (typePtr == NULL) {
@@ -203,18 +212,20 @@ Tcl_InitCustomHashTable(
*----------------------------------------------------------------------
*/
#ifndef TCL_NO_DEPRECATED
static Tcl_HashEntry *
FindHashEntry(
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
const char *key) /* Key to use to find matching entry. */
{
return CreateHashEntry(tablePtr, key, NULL);
return tablePtr->createProc(tablePtr, key, TCL_HASH_FIND);
}
#endif
/*
*----------------------------------------------------------------------
*
* CreateHashEntry --
* Tcl_CreateHashEntry --
*
* Given a hash table with string keys, and a string key, find the entry
* with a matching key. If there is no matching entry, then create a new
@@ -232,6 +243,38 @@ FindHashEntry(
*----------------------------------------------------------------------
*/
Tcl_HashEntry *
Tcl_CreateHashEntry(
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
const void *key, /* Key to use to find or create matching
* entry. */
int *newPtr) /* Store info here telling whether a new entry
* was created. */
{
Tcl_HashEntry *entry = (*((tablePtr)->createProc))(tablePtr, (const char *)key, newPtr);
if (!entry) {
Tcl_Panic("%s: Memory overflow", "Tcl_CreateHashEntry");
}
return entry;
}
Tcl_HashEntry *
Tcl_DbCreateHashEntry(
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
const void *key, /* Key to use to find or create matching
* entry. */
int *newPtr, /* Store info here telling whether a new entry
* was created. */
const char *file,
int line)
{
Tcl_HashEntry *entry = (*((tablePtr)->createProc))(tablePtr, (const char *)key, newPtr);
if (!entry) {
Tcl_Panic("%s: Memory overflow in file %s:%d", "Tcl_CreateHashEntry", file, line);
}
return entry;
}
static Tcl_HashEntry *
CreateHashEntry(
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
@@ -282,7 +325,7 @@ CreateHashEntry(
/* if keys pointers or values are equal */
if ((key == hPtr->key.oneWordValue)
|| compareKeysProc((void *) key, hPtr)) {
if (newPtr) {
if (newPtr && (newPtr != TCL_HASH_FIND)) {
*newPtr = 0;
}
return hPtr;
@@ -297,7 +340,7 @@ CreateHashEntry(
/* if needle pointer equals content pointer or values equal */
if ((key == hPtr->key.string)
|| compareKeysProc((void *) key, hPtr)) {
if (newPtr) {
if (newPtr && (newPtr != TCL_HASH_FIND)) {
*newPtr = 0;
}
return hPtr;
@@ -311,7 +354,7 @@ CreateHashEntry(
continue;
}
if (key == hPtr->key.oneWordValue) {
if (newPtr) {
if (newPtr && (newPtr != TCL_HASH_FIND)) {
*newPtr = 0;
}
return hPtr;
@@ -319,7 +362,8 @@ CreateHashEntry(
}
}
if (!newPtr) {
if (newPtr == TCL_HASH_FIND) {
/* This is the findProc functionality, so we are done. */
return NULL;
}
@@ -327,11 +371,16 @@ CreateHashEntry(
* Entry not found. Add a new one to the bucket.
*/
*newPtr = 1;
if (newPtr) {
*newPtr = 1;
}
if (typePtr->allocEntryProc) {
hPtr = typePtr->allocEntryProc(tablePtr, (void *) key);
} else {
hPtr = (Tcl_HashEntry *)Tcl_Alloc(sizeof(Tcl_HashEntry));
hPtr = (Tcl_HashEntry *)Tcl_AttemptAlloc(sizeof(Tcl_HashEntry));
if (!hPtr) {
return NULL;
}
hPtr->key.oneWordValue = (char *) key;
Tcl_SetHashValue(hPtr, NULL);
}
@@ -495,7 +544,9 @@ Tcl_DeleteHashTable(
* re-initialization.
*/
tablePtr->findProc = BogusFind;
#ifndef TCL_NO_DEPRECATED
tablePtr->findProc = FindHashEntry;
#endif
tablePtr->createProc = BogusCreate;
}
@@ -675,10 +726,12 @@ AllocArrayEntry(
if (size < sizeof(Tcl_HashEntry)) {
size = sizeof(Tcl_HashEntry);
}
hPtr = (Tcl_HashEntry *)Tcl_Alloc(size);
hPtr = (Tcl_HashEntry *)Tcl_AttemptAlloc(size);
memcpy(hPtr->key.string, keyPtr, count);
Tcl_SetHashValue(hPtr, NULL);
if (hPtr) {
memcpy(hPtr->key.string, keyPtr, count);
Tcl_SetHashValue(hPtr, NULL);
}
return hPtr;
}
@@ -773,10 +826,12 @@ AllocStringEntry(
if (size < sizeof(hPtr->key)) {
allocsize = sizeof(hPtr->key);
}
hPtr = (Tcl_HashEntry *)Tcl_Alloc(offsetof(Tcl_HashEntry, key) + allocsize);
memset(hPtr, 0, offsetof(Tcl_HashEntry, key) + allocsize);
memcpy(hPtr->key.string, string, size);
Tcl_SetHashValue(hPtr, NULL);
hPtr = (Tcl_HashEntry *)Tcl_AttemptAlloc(offsetof(Tcl_HashEntry, key) + allocsize);
if (hPtr) {
memset(hPtr, 0, offsetof(Tcl_HashEntry, key) + allocsize);
memcpy(hPtr->key.string, string, size);
Tcl_SetHashValue(hPtr, NULL);
}
return hPtr;
}
@@ -871,32 +926,6 @@ TclHashStringKey(
return result;
}
/*
*----------------------------------------------------------------------
*
* BogusFind --
*
* This function is invoked when Tcl_FindHashEntry is called on a
* table that has been deleted.
*
* Results:
* If Tcl_Panic returns (which it shouldn't) this function returns NULL.
*
* Side effects:
* Generates a panic.
*
*----------------------------------------------------------------------
*/
static Tcl_HashEntry *
BogusFind(
TCL_UNUSED(Tcl_HashTable *),
TCL_UNUSED(const char *))
{
Tcl_Panic("called %s on deleted table", "Tcl_FindHashEntry");
return NULL;
}
/*
*----------------------------------------------------------------------
*
@@ -918,9 +947,10 @@ static Tcl_HashEntry *
BogusCreate(
TCL_UNUSED(Tcl_HashTable *),
TCL_UNUSED(const char *),
TCL_UNUSED(int *))
int *isNew)
{
Tcl_Panic("called %s on deleted table", "Tcl_CreateHashEntry");
Tcl_Panic("called %s on deleted table",
(isNew != TCL_HASH_FIND)? "Tcl_CreateHashEntry" : "Tcl_FindHashEntry");
return NULL;
}
+32 -20
View File
@@ -137,6 +137,12 @@ typedef struct {
static Tcl_ThreadDataKey dataKey;
/*
* Key for looking up the channel table (a Tcl_HashTable indexed by channel
* name) in the interpreter's associated data table.
*/
#define ASSOC_KEY "tclIO"
/*
* Structure to record a close callback. One such record exists for
* each close callback registered for a channel.
@@ -360,8 +366,8 @@ static const Tcl_ObjType chanObjType = {
} while (0)
#define BUSY_STATE(st, fl) \
((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \
(((st)->csPtrW) && ((fl) & TCL_WRITABLE)))
((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \
(((st)->csPtrW) && ((fl) & TCL_WRITABLE)))
#define MAX_CHANNEL_BUFFER_SIZE (1024*1024)
@@ -738,8 +744,10 @@ Tcl_SetStdChannel(
tsdPtr->stderrInitialized = init;
tsdPtr->stderrChannel = channel;
if (channel) {
ENCODING_PROFILE_SET(((Channel *)channel)->state->inputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
ENCODING_PROFILE_SET(((Channel *)channel)->state->outputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
ENCODING_PROFILE_SET(((Channel *)channel)->state->inputEncodingFlags,
TCL_ENCODING_PROFILE_REPLACE);
ENCODING_PROFILE_SET(((Channel *)channel)->state->outputEncodingFlags,
TCL_ENCODING_PROFILE_REPLACE);
}
break;
}
@@ -811,8 +819,10 @@ Tcl_GetStdChannel(
tsdPtr->stderrInitialized = -1;
tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR);
if (tsdPtr->stderrChannel != NULL) {
ENCODING_PROFILE_SET(((Channel *)tsdPtr->stderrChannel)->state->inputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
ENCODING_PROFILE_SET(((Channel *)tsdPtr->stderrChannel)->state->outputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
ENCODING_PROFILE_SET(((Channel *)tsdPtr->stderrChannel)->state->inputEncodingFlags,
TCL_ENCODING_PROFILE_REPLACE);
ENCODING_PROFILE_SET(((Channel *)tsdPtr->stderrChannel)->state->outputEncodingFlags,
TCL_ENCODING_PROFILE_REPLACE);
tsdPtr->stderrInitialized = 1;
Tcl_RegisterChannel(NULL, tsdPtr->stderrChannel);
}
@@ -932,11 +942,11 @@ GetChannelTable(
Tcl_HashTable *hTblPtr; /* Hash table of channels. */
Tcl_Channel stdinChan, stdoutChan, stderrChan;
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclIO", NULL);
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
if (hTblPtr == NULL) {
hTblPtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
Tcl_InitHashTable(hTblPtr, TCL_STRING_KEYS);
Tcl_SetAssocData(interp, "tclIO",
Tcl_SetAssocData(interp, ASSOC_KEY,
(Tcl_InterpDeleteProc *) DeleteChannelTable, hTblPtr);
/*
@@ -1372,7 +1382,7 @@ DetachChannel(
statePtr = chanPtr->state;
if (interp != NULL) {
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclIO", NULL);
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
if (hTblPtr == NULL) {
return TCL_ERROR;
}
@@ -1617,10 +1627,12 @@ Tcl_CreateChannel(
Tcl_Panic("channel type %s must define close2Proc", typePtr->typeName);
}
if ((TCL_READABLE & mask) && (NULL == typePtr->inputProc)) {
Tcl_Panic("channel type %s must define inputProc when used for reader channel", typePtr->typeName);
Tcl_Panic("channel type %s must define inputProc when used for reader channel",
typePtr->typeName);
}
if ((TCL_WRITABLE & mask) && (NULL == typePtr->outputProc)) {
Tcl_Panic("channel type %s must define outputProc when used for writer channel", typePtr->typeName);
Tcl_Panic("channel type %s must define outputProc when used for writer channel",
typePtr->typeName);
}
if (NULL == typePtr->watchProc) {
Tcl_Panic("channel type %s must define watchProc", typePtr->typeName);
@@ -2438,9 +2450,9 @@ Tcl_GetChannelHandle(
int
Tcl_RemoveChannelMode(
Tcl_Interp *interp, /* The interp for an error message. Allowed to be NULL. */
Tcl_Channel chan, /* The channel which is modified. */
int mode) /* The access mode to drop from the channel */
Tcl_Interp *interp, /* The interp for an error message. Allowed to be NULL. */
Tcl_Channel chan, /* The channel which is modified. */
int mode) /* The access mode to drop from the channel */
{
const char* emsg;
ChannelState *statePtr = ((Channel *) chan)->state;
@@ -2458,7 +2470,7 @@ Tcl_RemoveChannelMode(
ResetFlag(statePtr, mode);
return TCL_OK;
error:
error:
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"Tcl_RemoveChannelMode error: %s. Channel: \"%s\"",
@@ -9423,7 +9435,8 @@ TclCopyChannel(
* completed.
*/
csPtr = (CopyState *)Tcl_Alloc(offsetof(CopyState, buffer) + 1U + !moveBytes * inStatePtr->bufSize);
csPtr = (CopyState *)
Tcl_Alloc(offsetof(CopyState, buffer) + 1U + !moveBytes * inStatePtr->bufSize);
csPtr->bufSize = !moveBytes * inStatePtr->bufSize;
csPtr->readPtr = inPtr;
csPtr->writePtr = outPtr;
@@ -9802,7 +9815,7 @@ CopyData(
if (moveBytes) {
size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb,
!GotFlag(inStatePtr, CHANNEL_NONBLOCKING));
!GotFlag(inStatePtr, CHANNEL_NONBLOCKING));
} else {
size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb,
!GotFlag(inStatePtr, CHANNEL_NONBLOCKING)
@@ -10165,8 +10178,7 @@ DoRead(
}
if (!bufPtr) {
readErr:
readErr:
UpdateInterest(chanPtr);
TclChannelRelease((Tcl_Channel)chanPtr);
return -1;
@@ -10702,7 +10714,7 @@ Tcl_IsChannelRegistered(
chanPtr = ((Channel *) chan)->state->bottomChanPtr;
statePtr = chanPtr->state;
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclIO", NULL);
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
if (hTblPtr == NULL) {
return 0;
}
+62 -18
View File
@@ -34,6 +34,13 @@ typedef struct {
static Tcl_ThreadDataKey dataKey;
/*
* Key for looking up the table of registered TCP accept callbacks, a hash
* table indexed by AcceptCallback references, used as a set (values are
* meaningless).
*/
#define ASSOC_KEY "tclTCPAcceptCallbacks"
/*
* Static functions for this file:
*/
@@ -135,7 +142,7 @@ Tcl_PutsObjCmd(
string = objv[3];
break;
}
/* Fall through */
TCL_FALLTHROUGH();
default: /* [puts] or
* [puts some bad number of arguments...] */
Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? ?channel? string");
@@ -910,11 +917,12 @@ Tcl_ExecObjCmd(
int argc, background, i, index, keepNewline, result, skip, ignoreStderr;
Tcl_Size length;
static const char *const options[] = {
"-ignorestderr", "-keepnewline", "--", NULL
"-ignorestderr", "-keepnewline", "-encoding", "--", NULL
};
enum execOptionsEnum {
EXEC_IGNORESTDERR, EXEC_KEEPNEWLINE, EXEC_LAST
EXEC_IGNORESTDERR, EXEC_KEEPNEWLINE, EXEC_ENCODING, EXEC_LAST
};
Tcl_Obj *encodingObj = NULL;
/*
* Check for any leading option arguments.
@@ -931,14 +939,34 @@ Tcl_ExecObjCmd(
TCL_EXACT, &index) != TCL_OK) {
return TCL_ERROR;
}
if (index == EXEC_KEEPNEWLINE) {
keepNewline = 1;
} else if (index == EXEC_IGNORESTDERR) {
ignoreStderr = 1;
} else {
if (index == EXEC_LAST) {
skip++;
break;
}
switch (index) {
case EXEC_KEEPNEWLINE:
keepNewline = 1;
break;
case EXEC_IGNORESTDERR:
ignoreStderr = 1;
break;
case EXEC_ENCODING:
if (++skip >= objc) {
Tcl_SetResult(interp, "No value given for option -encoding.",
TCL_STATIC);
return TCL_ERROR;
} else {
Tcl_Encoding encoding;
encodingObj = objv[skip];
/* Verify validity - bug [da5e1bc7bc] */
if (Tcl_GetEncodingFromObj(interp, encodingObj, &encoding)
!= TCL_OK) {
return TCL_ERROR;
}
Tcl_FreeEncoding(encoding);
}
break;
}
}
if (objc <= skip) {
Tcl_WrongNumArgs(interp, 1, objv, "?-option ...? arg ?arg ...?");
@@ -986,11 +1014,6 @@ Tcl_ExecObjCmd(
return TCL_ERROR;
}
/* Bug [0f1ddc0df7] - encoding errors - use replace profile */
if (Tcl_SetChannelOption(NULL, chan, "-profile", "replace") != TCL_OK) {
return TCL_ERROR;
}
if (background) {
/*
* Store the list of PIDs from the pipeline in interp's result and
@@ -1004,6 +1027,18 @@ Tcl_ExecObjCmd(
return TCL_OK;
}
/* Bug [0f1ddc0df7] - encoding errors - use replace profile */
if (Tcl_SetChannelOption(interp, chan, "-profile", "replace") != TCL_OK) {
goto errorWithOpenChannel;
}
/* TIP 716 */
if (encodingObj &&
Tcl_SetChannelOption(interp, chan, "-encoding",
Tcl_GetString(encodingObj)) != TCL_OK) {
goto errorWithOpenChannel;
}
TclNewObj(resultPtr);
if (Tcl_GetChannelHandle(chan, TCL_READABLE, NULL) == TCL_OK) {
if (Tcl_ReadChars(chan, resultPtr, -1, 0) == TCL_IO_FAILURE) {
@@ -1020,7 +1055,7 @@ Tcl_ExecObjCmd(
Tcl_PosixError(interp)));
Tcl_DecrRefCount(resultPtr);
}
return TCL_ERROR;
goto errorWithOpenChannel;
}
}
@@ -1047,6 +1082,11 @@ Tcl_ExecObjCmd(
Tcl_SetObjResult(interp, resultPtr);
return result;
errorWithOpenChannel:
/* Interpreter should already contain error. Pass NULL to not overwrite */
(void)Tcl_CloseEx(NULL, chan, 0);
return TCL_ERROR;
}
/*
@@ -1291,12 +1331,12 @@ RegisterTcpServerInterpCleanup(
Tcl_HashEntry *hPtr; /* Entry for this record. */
int isNew; /* Is the entry new? */
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL);
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
if (hTblPtr == NULL) {
hTblPtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
Tcl_InitHashTable(hTblPtr, TCL_ONE_WORD_KEYS);
Tcl_SetAssocData(interp, "tclTCPAcceptCallbacks",
Tcl_SetAssocData(interp, ASSOC_KEY,
TcpAcceptCallbacksDeleteProc, hTblPtr);
}
@@ -1337,7 +1377,7 @@ UnregisterTcpServerInterpCleanupProc(
Tcl_HashTable *hTblPtr;
Tcl_HashEntry *hPtr;
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL);
hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
if (hTblPtr == NULL) {
return;
}
@@ -1605,7 +1645,7 @@ Tcl_SocketObjCmd(
}
break;
default:
Tcl_Panic("Tcl_SocketObjCmd: bad option index to SocketOptions");
TCL_UNREACHABLE();
}
}
if (server) {
@@ -1810,6 +1850,8 @@ Tcl_FcopyObjCmd(
case FcopyCommand:
cmdPtr = objv[i+1];
break;
default:
TCL_UNREACHABLE();
}
}
@@ -1876,6 +1918,8 @@ ChanPendingObjCmd(
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_OutputBuffered(chan)));
}
break;
default:
TCL_UNREACHABLE();
}
return TCL_OK;
}
+2 -2
View File
@@ -267,8 +267,8 @@ TclChannelTransform(
}
if (TCL_OK != TclListObjLength(interp, cmdObjPtr, &objc)) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("-command value is not a list", -1));
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"-command value is not a list", -1));
return TCL_ERROR;
}
+19 -16
View File
@@ -461,8 +461,9 @@ static const char *msg_seek_beforestart = "{Tried to seek before origin}";
#if TCL_THREADS
static const char *msg_send_originlost = "{Channel thread lost}";
#endif /* TCL_THREADS */
static const char *msg_send_dstlost = "{Owner lost}";
static const char *msg_dstlost = "-code 1 -level 0 -errorcode NONE -errorinfo {} -errorline 1 {Owner lost}";
static const char *msg_send_dstlost = "{Owner lost}";
static const char *msg_dstlost =
"-code 1 -level 0 -errorcode NONE -errorinfo {} -errorline 1 {Owner lost}";
/*
* Main methods to plug into the 'chan' ensemble'. ==================
@@ -722,7 +723,7 @@ TclChanCreateObjCmd(
#if TCL_THREADS
rcmPtr = GetThreadReflectedChannelMap();
hPtr = Tcl_CreateHashEntry(&rcmPtr->map, chanPtr->state->channelName,
&isNew);
NULL);
Tcl_SetHashValue(hPtr, chan);
#endif
@@ -913,8 +914,8 @@ TclChanPostEventObjCmd(
return TCL_ERROR;
}
if (events == 0) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("bad event list: is empty", -1));
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"bad event list: is empty", -1));
return TCL_ERROR;
}
@@ -1350,14 +1351,14 @@ ReflectInput(
memcpy(buf, bytev, bytec);
}
stop:
stop:
Tcl_DecrRefCount(toReadObj);
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
Tcl_Release(rcPtr);
return bytec;
invalid:
invalid:
*errorCodePtr = EINVAL;
error:
error:
bytec = -1;
goto stop;
}
@@ -1478,15 +1479,15 @@ ReflectOutput(
}
*errorCodePtr = EOK;
stop:
stop:
Tcl_DecrRefCount(bufObj);
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
Tcl_Release(rcPtr->interp);
Tcl_Release(rcPtr);
return written;
invalid:
invalid:
*errorCodePtr = EINVAL;
error:
error:
written = -1;
goto stop;
}
@@ -1571,13 +1572,13 @@ ReflectSeekWide(
}
*errorCodePtr = EOK;
stop:
stop:
Tcl_DecrRefCount(offObj);
Tcl_DecrRefCount(baseObj);
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
Tcl_Release(rcPtr);
return newLoc;
invalid:
invalid:
*errorCodePtr = EINVAL;
newLoc = -1;
goto stop;
@@ -1971,16 +1972,16 @@ ReflectGetOption(
goto ok;
}
ok:
ok:
result = TCL_OK;
stop:
stop:
if (optionObj) {
Tcl_DecrRefCount(optionObj);
}
Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
Tcl_Release(rcPtr);
return result;
error:
error:
result = TCL_ERROR;
goto stop;
}
@@ -2108,6 +2109,8 @@ EncodeEventMask(
case EVENT_WRITE:
events |= TCL_WRITABLE;
break;
default:
TCL_UNREACHABLE();
}
listc --;
}
+3 -3
View File
@@ -695,7 +695,7 @@ TclChanPushObjCmd(
Tcl_SetHashValue(hPtr, rtPtr);
#if TCL_THREADS
rtmPtr = GetThreadReflectedTransformMap();
hPtr = Tcl_CreateHashEntry(&rtmPtr->map, TclGetString(rtId), &isNew);
hPtr = Tcl_CreateHashEntry(&rtmPtr->map, TclGetString(rtId), NULL);
Tcl_SetHashValue(hPtr, rtPtr);
#endif /* TCL_THREADS */
@@ -1211,7 +1211,7 @@ ReflectInput(
Tcl_SetByteArrayLength(bufObj, 0);
} /* while toRead > 0 */
stop:
stop:
if (gotBytes == 0) {
rtPtr->eofPending = 0;
}
@@ -1219,7 +1219,7 @@ ReflectInput(
Tcl_Release(rtPtr);
return gotBytes;
error:
error:
gotBytes = -1;
goto stop;
}
+19
View File
@@ -336,6 +336,25 @@ Tcl_OpenTcpServer(
-1, acceptProc, callbackData);
}
#ifdef TCL_SOCK_PRINTF_DEBUGGING
/* printf debugging */
void
printaddrinfo(
struct addrinfo *addrlist,
char *prefix)
{
char host[NI_MAXHOST], port[NI_MAXSERV];
struct addrinfo *ai;
for (ai = addrlist; ai != NULL; ai = ai->ai_next) {
getnameinfo(ai->ai_addr, ai->ai_addrlen,
host, sizeof(host), port, sizeof(port),
NI_NUMERICHOST|NI_NUMERICSERV);
fprintf(stderr,"%s: %s:%s\n", prefix, host, port);
}
}
#endif
/*
* Local Variables:
* mode: c
+15 -15
View File
@@ -255,8 +255,7 @@ Tcl_Stat(
Tcl_WideInt tmp1, tmp2, tmp3 = 0;
# define OUT_OF_RANGE(x) \
(((Tcl_WideInt)(x)) < LONG_MIN || \
((Tcl_WideInt)(x)) > LONG_MAX)
(((Tcl_WideInt)(x)) < LONG_MIN || ((Tcl_WideInt)(x)) > LONG_MAX)
# define OUT_OF_URANGE(x) \
(((Tcl_WideUInt)(x)) > ((Tcl_WideUInt)ULONG_MAX))
@@ -2783,7 +2782,7 @@ Tcl_FSGetCwd(
norm = TclFSNormalizeAbsolutePath(interp, retVal);
if (norm == NULL) {
/*
/*
* 'norm' shouldn't ever be NULL, but we are careful.
*/
@@ -2794,7 +2793,7 @@ Tcl_FSGetCwd(
} else if (norm == tsdPtr->cwdPathPtr) {
goto cdEqual;
} else {
/*
/*
* Determine whether the filesystem's answer is the same as the
* cached local value. Since both 'norm' and 'tsdPtr->cwdPathPtr'
* are normalized pathnames, do something more efficient than
@@ -2900,7 +2899,7 @@ Tcl_FSChdir(
retVal = 0;
} else {
/*
/*
* 'Tcl_SetErrno()' has already been called.
*/
}
@@ -2910,9 +2909,8 @@ Tcl_FSChdir(
}
if (retVal == 0) {
/* Assume that the cwd was actually changed to the normalized value
* just calculated, and cache that information. */
/* Assume that the cwd was actually changed to the normalized value
* just calculated, and cache that information. */
/*
* If the filesystem epoch changed recently, the normalized pathname or
@@ -2929,6 +2927,7 @@ Tcl_FSChdir(
Tcl_SetErrno(ENOENT);
return -1;
}
if (normDirName != pathPtr) { Tcl_IncrRefCount(normDirName); }
if (fsPtr == &tclNativeFilesystem) {
void *cd;
@@ -2980,6 +2979,7 @@ Tcl_FSChdir(
*/
Tcl_FSMountsChanged(NULL);
}
if (normDirName != pathPtr) { Tcl_DecrRefCount(normDirName); }
} else {
/*
* The current directory is now changed or an error occurred and an
@@ -3094,7 +3094,7 @@ Tcl_FSLoadFile(
#endif
static int
skipUnlink(
SkipUnlink(
Tcl_Obj *shlibFile)
{
/*
@@ -3284,9 +3284,9 @@ Tcl_LoadFile(
* load further.
*/
/*
* Try to delete the file we probably created and then exit.
*/
/*
* Try to delete the file we probably created and then exit.
*/
Tcl_FSDeleteFile(copyToPtr);
Tcl_DecrRefCount(copyToPtr);
@@ -3307,14 +3307,14 @@ Tcl_LoadFile(
/*
* It might be necessary on some systems to set the appropriate permissions
* on the file. On Unix we could loop over the file attributes and set any
* that are called "-permissions" to 0700, but just do it directly instead:
* that are called "-permissions" to 0o700, but just do it directly instead:
*/
{
Tcl_Size index;
Tcl_Obj *perm;
TclNewLiteralStringObj(perm, "0700");
TclNewLiteralStringObj(perm, "0o700");
Tcl_IncrRefCount(perm);
if (TclFSFileAttrIndex(copyToPtr, "-permissions", &index) == TCL_OK) {
Tcl_FSFileAttrsSet(NULL, index, copyToPtr, perm);
@@ -3345,7 +3345,7 @@ Tcl_LoadFile(
* and it avoids leaving the copy laying around after exit.
*/
if (!skipUnlink(copyToPtr) &&
if (!SkipUnlink(copyToPtr) &&
(Tcl_FSDeleteFile(copyToPtr) == TCL_OK)) {
Tcl_DecrRefCount(copyToPtr);
+85 -116
View File
@@ -45,9 +45,9 @@ typedef enum {
} UConverterCallbackReasonx;
typedef enum UNormalizationCheckResultx {
UNORM_NO,
UNORM_YES,
UNORM_MAYBE
UNORM_NO,
UNORM_YES,
UNORM_MAYBE
} UNormalizationCheckResultx;
typedef struct UEnumeration UEnumeration;
@@ -59,50 +59,31 @@ typedef struct UConverter UConverter;
typedef struct UConverterFromUnicodeArgs UConverterFromUnicodeArgs;
typedef struct UConverterToUnicodeArgs UConverterToUnicodeArgs;
typedef void (*UConverterFromUCallback)(const void *context,
UConverterFromUnicodeArgs *args,
const UCharx *codeUnits,
int32_t length, UChar32x codePoint,
UConverterCallbackReasonx reason,
UErrorCodex *pErrorCode);
UConverterFromUnicodeArgs *args, const UCharx *codeUnits,
int32_t length, UChar32x codePoint, UConverterCallbackReasonx reason,
UErrorCodex *pErrorCode);
typedef void (*UConverterToUCallback)(const void *context,
UConverterToUnicodeArgs *args,
const char *codeUnits,
int32_t length,
UConverterCallbackReasonx reason,
UErrorCodex *pErrorCode);
UConverterToUnicodeArgs *args, const char *codeUnits,
int32_t length, UConverterCallbackReasonx reason,
UErrorCodex *pErrorCode);
/*
* Prototypes for ICU functions sorted by category.
*/
typedef void (*fn_u_cleanup)(void);
typedef const char *(*fn_u_errorName)(UErrorCodex);
typedef UCharx *(*fn_u_strFromUTF32)(UCharx *dest,
int32_t destCapacity,
int32_t *pDestLength,
const UChar32x *src,
int32_t srcLength,
UErrorCodex *pErrorCode);
typedef UCharx *(*fn_u_strFromUTF32WithSub)(UCharx *dest,
int32_t destCapacity,
int32_t *pDestLength,
const UChar32x *src,
int32_t srcLength,
UChar32x subchar,
int32_t *pNumSubstitutions,
UErrorCodex *pErrorCode);
typedef UChar32x *(*fn_u_strToUTF32)(UChar32x *dest,
int32_t destCapacity,
int32_t *pDestLength,
const UCharx *src,
int32_t srcLength,
UErrorCodex *pErrorCode);
typedef UCharx *(*fn_u_strFromUTF32)(UCharx *dest, int32_t destCapacity,
int32_t *pDestLength, const UChar32x *src, int32_t srcLength,
UErrorCodex *pErrorCode);
typedef UCharx *(*fn_u_strFromUTF32WithSub)(UCharx *dest, int32_t destCapacity,
int32_t *pDestLength, const UChar32x *src, int32_t srcLength,
UChar32x subchar, int32_t *pNumSubstitutions, UErrorCodex *pErrorCode);
typedef UChar32x *(*fn_u_strToUTF32)(UChar32x *dest, int32_t destCapacity,
int32_t *pDestLength, const UCharx *src, int32_t srcLength,
UErrorCodex *pErrorCode);
typedef UChar32x *(*fn_u_strToUTF32WithSub)(UChar32x *dest,
int32_t destCapacity,
int32_t *pDestLength,
const UCharx *src,
int32_t srcLength,
UChar32x subchar,
int32_t *pNumSubstitutions,
UErrorCodex *pErrorCode);
int32_t destCapacity, int32_t *pDestLength, const UCharx *src,
int32_t srcLength, UChar32x subchar, int32_t *pNumSubstitutions,
UErrorCodex *pErrorCode);
typedef void (*fn_ucnv_close)(UConverter *);
typedef uint16_t (*fn_ucnv_countAliases)(const char *, UErrorCodex *);
@@ -113,19 +94,15 @@ typedef const char *(*fn_ucnv_getAlias)(const char *, uint16_t, UErrorCodex *);
typedef const char *(*fn_ucnv_getAvailableName)(int32_t);
typedef UConverter *(*fn_ucnv_open)(const char *converterName, UErrorCodex *);
typedef void (*fn_ucnv_setFromUCallBack)(UConverter *,
UConverterFromUCallback newAction,
const void *newContext,
UConverterFromUCallback *oldAction,
const void **oldContext,
UErrorCodex *err);
UConverterFromUCallback newAction, const void *newContext,
UConverterFromUCallback *oldAction, const void **oldContext,
UErrorCodex *err);
typedef void (*fn_ucnv_setToUCallBack)(UConverter *,
UConverterToUCallback newAction,
const void *newContext,
UConverterToUCallback *oldAction,
const void **oldContext,
UErrorCodex *err);
UConverterToUCallback newAction, const void *newContext,
UConverterToUCallback *oldAction, const void **oldContext,
UErrorCodex *err);
typedef int32_t (*fn_ucnv_toUChars)(UConverter *, UCharx *dest,
int32_t destCapacity, const char *src, int32_t srcLen, UErrorCodex *);
int32_t destCapacity, const char *src, int32_t srcLen, UErrorCodex *);
typedef UConverterFromUCallback fn_UCNV_FROM_U_CALLBACK_STOP;
typedef UConverterToUCallback fn_UCNV_TO_U_CALLBACK_STOP;
@@ -161,12 +138,8 @@ typedef UNormalizer2 *(*fn_unorm2_getNFCInstance)(UErrorCodex *);
typedef UNormalizer2 *(*fn_unorm2_getNFDInstance)(UErrorCodex *);
typedef UNormalizer2 *(*fn_unorm2_getNFKCInstance)(UErrorCodex *);
typedef UNormalizer2 *(*fn_unorm2_getNFKDInstance)(UErrorCodex *);
typedef int32_t (*fn_unorm2_normalize)(const UNormalizer2 *,
const UCharx *,
int32_t,
UCharx *,
int32_t,
UErrorCodex *);
typedef int32_t (*fn_unorm2_normalize)(const UNormalizer2 *, const UCharx *,
int32_t, UCharx *, int32_t, UErrorCodex *);
#define FIELD(name) fn_ ## name _ ## name
@@ -354,8 +327,8 @@ DetectEncoding(
return TCL_ERROR;
}
if (len > INT_MAX) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("Max length supported by ICU exceeded.", TCL_INDEX_NONE));
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"Max length supported by ICU exceeded.", TCL_INDEX_NONE));
return TCL_ERROR;
}
UErrorCodex status = U_ZERO_ERRORZ;
@@ -499,14 +472,9 @@ IcuObjToUCharDString(
char *s;
Tcl_Size len;
s = Tcl_GetStringFromObj(objPtr, &len);
result = Tcl_UtfToExternalDStringEx(interp,
encoding,
s,
len,
strict ? TCL_ENCODING_PROFILE_STRICT
: TCL_ENCODING_PROFILE_REPLACE,
dsPtr,
NULL);
result = Tcl_UtfToExternalDStringEx(interp, encoding, s, len,
strict ? TCL_ENCODING_PROFILE_STRICT : TCL_ENCODING_PROFILE_REPLACE,
dsPtr, NULL);
if (result != TCL_OK) {
Tcl_DStringFree(dsPtr); /* Must be done on error */
/* TCL_CONVER_* errors -> TCL_ERROR */
@@ -554,14 +522,9 @@ IcuObjFromUCharDString(
Tcl_Size len = Tcl_DStringLength(dsPtr);
Tcl_DString dsOut;
int result;
result = Tcl_ExternalToUtfDStringEx(interp,
encoding,
s,
len,
strict ? TCL_ENCODING_PROFILE_STRICT
: TCL_ENCODING_PROFILE_REPLACE,
&dsOut,
NULL);
result = Tcl_ExternalToUtfDStringEx(interp, encoding, s, len,
strict ? TCL_ENCODING_PROFILE_STRICT : TCL_ENCODING_PROFILE_REPLACE,
&dsOut, NULL);
if (result == TCL_OK) {
objPtr = Tcl_DStringToObj(&dsOut); /* Clears dsPtr! */
@@ -776,8 +739,8 @@ IcuConverttoDString(
Tcl_Size utf16len = Tcl_DStringLength(dsInPtr) / sizeof(UCharx);
Tcl_Size dstLen, dstCapacity;
if (utf16len > INT_MAX) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("Max length supported by ICU exceeded.", TCL_INDEX_NONE));
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"Max length supported by ICU exceeded.", TCL_INDEX_NONE));
return TCL_ERROR;
}
@@ -785,7 +748,7 @@ IcuConverttoDString(
Tcl_DStringInit(dsOutPtr);
Tcl_DStringSetLength(dsOutPtr, dstCapacity);
dstLen = ucnv_fromUChars(ucnvPtr, Tcl_DStringValue(dsOutPtr), (int)dstCapacity,
utf16, (int)utf16len, &status);
utf16, (int)utf16len, &status);
if (U_FAILURE(status)) {
switch (status) {
case U_STRING_NOT_TERMINATED_WARNING:
@@ -794,11 +757,11 @@ IcuConverttoDString(
Tcl_DStringSetLength(dsOutPtr, (int)dstLen);
status = U_ZERO_ERRORZ; /* Reset before call */
dstLen = ucnv_fromUChars(ucnvPtr, Tcl_DStringValue(dsOutPtr), (int)dstLen,
utf16, (int)utf16len, &status);
utf16, (int)utf16len, &status);
if (U_SUCCESS(status)) {
break;
}
/* FALLTHRU */
TCL_FALLTHROUGH();
default:
Tcl_DStringFree(dsOutPtr);
ucnv_close(ucnvPtr);
@@ -840,8 +803,8 @@ IcuBytesToUCharDString(
}
if (nbytes > INT_MAX) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("Max length supported by ICU exceeded.", TCL_INDEX_NONE));
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"Max length supported by ICU exceeded.", TCL_INDEX_NONE));
return TCL_ERROR;
}
@@ -864,7 +827,7 @@ IcuBytesToUCharDString(
Tcl_DStringInit(dsOutPtr);
Tcl_DStringSetLength(dsOutPtr, dstCapacity);
dstLen = ucnv_toUChars(ucnvPtr, (UCharx *)Tcl_DStringValue(dsOutPtr), dstCapacity,
(const char *)bytes, (int)nbytes, &status);
(const char *)bytes, (int)nbytes, &status);
if (U_FAILURE(status)) {
switch (status) {
case U_STRING_NOT_TERMINATED_WARNING:
@@ -874,11 +837,11 @@ IcuBytesToUCharDString(
Tcl_DStringSetLength(dsOutPtr, dstCapacity);
status = U_ZERO_ERRORZ; /* Reset before call */
dstLen = ucnv_toUChars(ucnvPtr, (UCharx *)Tcl_DStringValue(dsOutPtr), dstCapacity,
(const char *)bytes, (int)nbytes, &status);
(const char *)bytes, (int)nbytes, &status);
if (U_SUCCESS(status)) {
break;
}
/* FALLTHRU */
TCL_FALLTHROUGH();
default:
Tcl_DStringFree(dsOutPtr);
ucnv_close(ucnvPtr);
@@ -949,8 +912,8 @@ IcuNormalizeUCharDString(
utf16 = (UCharx *) Tcl_DStringValue(dsInPtr);
utf16len = Tcl_DStringLength(dsInPtr) / sizeof(UCharx);
if (utf16len > INT_MAX) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("Max length supported by ICU exceeded.", TCL_INDEX_NONE));
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"Max length supported by ICU exceeded.", TCL_INDEX_NONE));
return TCL_ERROR;
}
Tcl_DStringInit(dsOutPtr);
@@ -974,7 +937,7 @@ IcuNormalizeUCharDString(
if (U_SUCCESS(status)) {
break;
}
/* FALLTHRU */
TCL_FALLTHROUGH();
default:
Tcl_DStringFree(dsOutPtr);
return IcuError(interp, "String normalization failed", status);
@@ -1014,9 +977,9 @@ static int IcuParseConvertOptions(
}
++i;
if (i == objc) {
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("Missing value for option %s.",
Tcl_GetString(objv[i - 1])));
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"Missing value for option %s.",
Tcl_GetString(objv[i - 1])));
return TCL_ERROR;
}
const char *s = Tcl_GetString(objv[i]);
@@ -1025,18 +988,20 @@ static int IcuParseConvertOptions(
if (!strcmp(s, "replace")) {
strict = 0;
} else if (strcmp(s, "strict")) {
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("Invalid value \"%s\" supplied for option"
" \"-profile\". Must be \"strict\" or \"replace\".",
s));
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"Invalid value \"%s\" supplied for option"
" \"-profile\". Must be \"strict\" or \"replace\".",
s));
return TCL_ERROR;
}
break;
case OPT_FAILINDEX:
/* TBD */
Tcl_SetObjResult(interp,
Tcl_NewStringObj("Option -failindex not implemented.", TCL_INDEX_NONE));
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"Option -failindex not implemented.", TCL_INDEX_NONE));
return TCL_ERROR;
default:
TCL_UNREACHABLE();
}
}
*strictPtr = strict;
@@ -1182,9 +1147,9 @@ IcuNormalizeObjCmd(
}
++i;
if (i == (objc-1)) {
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("Missing value for option %s.",
Tcl_GetString(objv[i - 1])));
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"Missing value for option %s.",
Tcl_GetString(objv[i - 1])));
return TCL_ERROR;
}
const char *s = Tcl_GetString(objv[i]);
@@ -1193,18 +1158,21 @@ IcuNormalizeObjCmd(
if (!strcmp(s, "replace")) {
strict = 0;
} else if (strcmp(s, "strict")) {
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("Invalid value \"%s\" supplied for option \"-profile\". Must be "
"\"strict\" or \"replace\".",
s));
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"Invalid value \"%s\" supplied for option \"-profile\". "
"Must be \"strict\" or \"replace\".",
s));
return TCL_ERROR;
}
break;
case OPT_MODE:
if (Tcl_GetIndexFromObj(interp, objv[i], normalizationForms, "normalization mode", 0, &mode) != TCL_OK) {
if (Tcl_GetIndexFromObj(interp, objv[i], normalizationForms,
"normalization mode", 0, &mode) != TCL_OK) {
return TCL_ERROR;
}
break;
default:
TCL_UNREACHABLE();
}
}
@@ -1359,7 +1327,8 @@ TclIcuInit(
/* Going back down to ICU version 60 */
while ((icu_fns.libs[0] == NULL) && (icuversion[1] >= '6')) {
if (--icuversion[2] < '0') {
icuversion[1]--; icuversion[2] = '9';
icuversion[1]--;
icuversion[2] = '9';
}
#if defined(__CYGWIN__)
i = 2;
@@ -1438,10 +1407,10 @@ TclIcuInit(
/* Symbol may have version (Linux), or not (Windows, FreeBSD) */
#define ICUUC_SYM(name) \
do { \
icu_fns._##name = \
(fn_##name)IcuFindSymbol(icu_fns.libs[0], #name, icuversion); \
#define ICUUC_SYM(name) \
do { \
icu_fns._##name = (fn_##name) \
IcuFindSymbol(icu_fns.libs[0], #name, icuversion); \
} while (0)
if (icu_fns.libs[0] != NULL) {
@@ -1485,10 +1454,10 @@ TclIcuInit(
#undef ICUUC_SYM
}
#define ICUIN_SYM(name) \
do { \
icu_fns._##name = \
(fn_##name)IcuFindSymbol(icu_fns.libs[1], #name, icuversion); \
#define ICUIN_SYM(name) \
do { \
icu_fns._##name = (fn_##name) \
IcuFindSymbol(icu_fns.libs[1], #name, icuversion); \
} while (0)
if (icu_fns.libs[1] != NULL) {
@@ -1514,9 +1483,9 @@ TclIcuInit(
/* Ref count number of commands */
icu_fns.nopen += 3;
Tcl_CreateObjCommand(interp, "::tcl::unsupported::icu::convertto",
IcuConverttoObjCmd, 0, TclIcuCleanup);
IcuConverttoObjCmd, 0, TclIcuCleanup);
Tcl_CreateObjCommand(interp, "::tcl::unsupported::icu::convertfrom",
IcuConvertfromObjCmd, 0, TclIcuCleanup);
IcuConvertfromObjCmd, 0, TclIcuCleanup);
Tcl_CreateObjCommand(interp, "::tcl::unsupported::icu::detect",
IcuDetectObjCmd, 0, TclIcuCleanup);
}
+9 -4
View File
@@ -68,7 +68,9 @@ typedef struct {
#define NEXT_ENTRY(table, offset) \
(&(STRING_AT(table, offset)))
#define EXPAND_OF(indexRep) \
(((indexRep)->index != TCL_INDEX_NONE) ? STRING_AT((indexRep)->tablePtr, (indexRep)->offset*(indexRep)->index) : "")
(((indexRep)->index != TCL_INDEX_NONE) ? \
STRING_AT((indexRep)->tablePtr, (indexRep)->offset*(indexRep)->index) : \
"")
/*
*----------------------------------------------------------------------
@@ -363,7 +365,8 @@ Tcl_GetIndexFromObjStruct(
}
/* #define again, needed below */
#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \
((Tcl_GetIndexFromObjStruct)((interp), (objPtr), (tablePtr), (offset), (msg), (flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr)))
((Tcl_GetIndexFromObjStruct)((interp), (objPtr), (tablePtr), (offset), \
(msg), (flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr)))
/*
*----------------------------------------------------------------------
@@ -386,10 +389,12 @@ static void
UpdateStringOfIndex(
Tcl_Obj *objPtr)
{
IndexRep *indexRep = (IndexRep *)TclFetchInternalRep(objPtr, &tclIndexType)->twoPtrValue.ptr1;
IndexRep *indexRep = (IndexRep *)
TclFetchInternalRep(objPtr, &tclIndexType)->twoPtrValue.ptr1;
const char *indexStr = EXPAND_OF(indexRep);
size_t len = strlen(indexStr);
Tcl_InitStringRep(objPtr, indexStr, strlen(indexStr));
TclOOM(Tcl_InitStringRep(objPtr, indexStr, len), len+1);
}
/*
+6 -3
View File
@@ -555,7 +555,7 @@ declare 239 {
}
declare 240 {
int TclNRRunCallbacks(Tcl_Interp *interp, int result,
struct NRE_callback *rootPtr)
struct NRE_callback *rootPtr)
}
declare 241 {
int TclNREvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags,
@@ -563,7 +563,7 @@ declare 241 {
}
declare 242 {
int TclNREvalObjv(Tcl_Interp *interp, Tcl_Size objc,
Tcl_Obj *const objv[], int flags, Command *cmdPtr)
Tcl_Obj *const objv[], int flags, Command *cmdPtr)
}
# Tcl_Obj leak detection support.
@@ -593,7 +593,7 @@ declare 248 {
declare 249 {
char *TclDoubleDigits(double dv, int ndigits, int flags,
int *decpt, int *signum, char **endPtr)
int *decpt, int *signum, char **endPtr)
}
# TIP #285: Script cancellation support.
declare 250 {
@@ -635,6 +635,9 @@ declare 257 {
void TclStaticLibrary(Tcl_Interp *interp, const char *prefix,
Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc)
}
declare 258 {
int TclMSB(unsigned long long n)
}
declare 261 {
void TclUnusedStubEntry(void)
+135 -38
View File
@@ -141,6 +141,32 @@
# define Tcl_ConditionFinalize(condPtr)
#endif
// A way to mark a code path as unreachable.
#ifndef TCL_UNREACHABLE
#if defined(__STDC__) && __STDC__ >= 202311L
#include <stddef.h>
#define TCL_UNREACHABLE() unreachable()
#elif defined(__GNUC__)
#define TCL_UNREACHABLE() __builtin_unreachable()
#elif defined(_MSC_VER)
#include <stdbool.h>
#define TCL_UNREACHABLE() __assume(false)
#else
#define TCL_UNREACHABLE() ((void) 0)
#endif
#endif // TCL_UNREACHABLE
#ifndef TCL_FALLTHROUGH
#if defined(__STDC__) && __STDC__ >= 202311L
#define TCL_FALLTHROUGH() [[fallthrough]]
#elif defined(__GNUC__)
#define TCL_FALLTHROUGH() __attribute__((fallthrough))
#else
// Nothing documented as an alternative to the standard [[fallthrough]].
#define TCL_FALLTHROUGH() ((void) 0)
#endif
#endif // TCL_FALLTHROUGH
/*
* The following procedures allow namespaces to be customized to support
* special name resolution rules for commands/variables.
@@ -718,6 +744,8 @@ typedef struct VarInHash {
#define VAR_ARRAY 0x1
#define VAR_LINK 0x2
#define VAR_CONSTANT 0x10000
#define VAR_TYPE \
(VAR_ARRAY | VAR_LINK | VAR_CONSTANT)
/* Type of storage (0 is compiled local) */
#define VAR_IN_HASHTABLE 0x4
@@ -745,6 +773,8 @@ typedef struct VarInHash {
#define VAR_IS_ARGS 0x400
#define VAR_RESOLVED 0x8000
#define TCL_HASH_FIND ((int *)-1)
/*
* Macros to ensure that various flag bits are set properly for variables.
* The ANSI C "prototypes" for these macros are:
@@ -887,7 +917,7 @@ typedef struct VarInHash {
#define TclIsVarTricky(varPtr,trickyFlags) \
( ((varPtr)->flags & (VAR_ARRAY|VAR_LINK|trickyFlags)) \
|| (TclIsVarInHash(varPtr) \
|| (TclIsVarInHash(varPtr) \
&& (TclVarParentArray(varPtr) != NULL) \
&& (TclVarParentArray(varPtr)->flags & (trickyFlags))))
@@ -1631,6 +1661,10 @@ typedef struct ExecEnv {
#define COR_IS_SUSPENDED(corPtr) \
((corPtr)->stackLevel == NULL)
// The different types of yielded coroutine we have.
#define CORO_ACTIVATE_YIELD NULL // 0 or 1 argument expected
#define CORO_ACTIVATE_YIELDM INT2PTR(1) // Arbitrary arguments expected
/*
* The definitions for the LiteralTable and LiteralEntry structures. Each
* interpreter contains a LiteralTable. It is used to reduce the storage
@@ -1830,35 +1864,39 @@ typedef struct Command {
/*
* Flag bits for commands.
*
* CMD_DYING - If 1 the command is in the process of
* being deleted (its deleteProc is currently
* executing). Other attempts to delete the
* command should be ignored.
* CMD_TRACE_ACTIVE - If 1 the trace processing is currently
* underway for a rename/delete change. See the
* two flags below for which is currently being
* processed.
* CMD_HAS_EXEC_TRACES - If 1 means that this command has at least one
* execution trace (as opposed to simple
* delete/rename traces) in its tracePtr list.
* CMD_COMPILES_EXPANDED - If 1 this command has a compiler that
* can handle expansion (provided it is not the
* first word).
* TCL_TRACE_RENAME - A rename trace is in progress. Further
* recursive renames will not be traced.
* TCL_TRACE_DELETE - A delete trace is in progress. Further
* recursive deletes will not be traced.
* (these last two flags are defined in tcl.h)
*/
#define CMD_DYING 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
#define CMD_DEAD 0x40
enum CommandFlags {
CMD_DYING = 0x01, /* The command is in the process of being
* deleted (its deleteProc is currently
* executing). Other attempts to delete the
* command should be ignored.*/
CMD_TRACE_ACTIVE = 0x02, /* The trace processing is currently underway
* for a rename/delete change. See the flags
* CMD_TRACE_RENAMING, CMD_TRACE_DELETING for
* which is currently being processed. */
CMD_HAS_EXEC_TRACES = 0x04, /* This command has at least one execution
* trace (as opposed to simple delete/rename
* traces) in its tracePtr list. */
CMD_COMPILES_EXPANDED = 0x08,
/* This command has a compiler that can handle
* expansion (provided it is not the first
* word). */
CMD_REDEF_IN_PROGRESS = 0x10,
/* Command is currently being redefined. It
* should not be deleted, though its ClientData
* may be purged. */
CMD_VIA_RESOLVER = 0x20, /* Command was located by resolver. Its literal
* should be marked unshared by the compiler. */
CMD_DEAD = 0x40, /* Command is at an advanced stage of being
* deleted, and is no longer in any hash tables
* but stale references may exist elsewhere. */
CMD_TRACE_RENAMING = TCL_TRACE_RENAME,
/* A rename trace is in progress. Further
* recursive renames will not be traced. */
CMD_TRACE_DELETING = TCL_TRACE_DELETE
/* A delete trace is in progress. Further
* recursive deletes will not be traced. */
};
/*
*----------------------------------------------------------------
@@ -2545,10 +2583,11 @@ typedef struct ListStore {
Tcl_Obj *slots[TCLFLEXARRAY];
/* Variable size array. Grown as needed */
} ListStore;
#define LISTSTORE_CANONICAL 0x1 /* All Tcl_Obj's referencing this
enum ListStoreFlags {
LISTSTORE_CANONICAL = 1 /* All Tcl_Obj's referencing this
* store have their string representation
* derived from the list representation */
};
/* Max number of elements that can be contained in a list */
#define LIST_MAX \
@@ -3152,6 +3191,7 @@ MODULE_SCOPE Tcl_ObjCmdProc TclNRSubstObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRSwitchObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRTryObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRUplevelObjCmd;
MODULE_SCOPE Tcl_NRPostProc TclUplevelCallback;
MODULE_SCOPE Tcl_ObjCmdProc TclNRWhileObjCmd;
MODULE_SCOPE Tcl_NRPostProc TclNRForIterCallback;
@@ -3163,6 +3203,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 TclNRPostInvoke;
MODULE_SCOPE Tcl_NRPostProc TclNRReleaseValues;
MODULE_SCOPE void TclSetTailcall(Tcl_Interp *interp,
@@ -3222,6 +3263,17 @@ struct Tcl_LoadHandle_ {
#define TCL_DD_CONVERSION_TYPE_MASK 0x3
/* Mask to isolate the conversion type */
/*
* Clock operations, communicated from command definitions to the bytecode
* compiler.
*/
enum ClockOps {
CLOCK_READ_CLICKS = 0, /* Read the click counter. */
CLOCK_READ_MICROS = 1, /* Time in microseconds. */
CLOCK_READ_MILLIS = 2, /* Time in milliseconds. */
CLOCK_READ_SECS = 3 /* Time in seconds. */
};
/*
*----------------------------------------------------------------
* Procedures shared among Tcl modules but not used by the outside world:
@@ -3232,6 +3284,10 @@ MODULE_SCOPE void TclAdvanceContinuations(int *line, Tcl_Size **next,
Tcl_Size loc);
MODULE_SCOPE void TclAdvanceLines(int *line, const char *start,
const char *end);
MODULE_SCOPE int TclAliasCreate(Tcl_Interp *interp,
Tcl_Interp *childInterp, Tcl_Interp *parentInterp,
Tcl_Obj *namePtr, Tcl_Obj *targetPtr, Tcl_Size objc,
Tcl_Obj *const objv[]);
MODULE_SCOPE void TclAppendBytesToByteArray(Tcl_Obj *objPtr,
const unsigned char *bytes, Tcl_Size len);
MODULE_SCOPE void TclAppendUtfToUtf(Tcl_Obj *objPtr,
@@ -3278,6 +3334,13 @@ MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr,
Tcl_Obj *originObjPtr);
MODULE_SCOPE Tcl_Size TclConvertElement(const char *src, Tcl_Size length,
char *dst, int flags);
MODULE_SCOPE int TclCopyNamespaceProcedures(Tcl_Interp *interp,
Namespace *srcNsPtr, Namespace *tgtNsPtr);
MODULE_SCOPE int TclCopyNamespaceVariables(Tcl_Interp *interp,
Namespace *originNs, Namespace *targetNs);
MODULE_SCOPE int TclCreateConstantInNS(Tcl_Interp *interp,
Namespace *nsPtr, Tcl_Obj *nameObj,
Tcl_Obj *valueObj);
MODULE_SCOPE Tcl_Command TclCreateObjCommandInNs(Tcl_Interp *interp,
const char *cmdName, Tcl_Namespace *nsPtr,
Tcl_ObjCmdProc *proc, void *clientData,
@@ -3647,6 +3710,8 @@ MODULE_SCOPE void TclErrorStackResetIf(Tcl_Interp *interp,
MODULE_SCOPE int TclZipfs_Init(Tcl_Interp *interp);
MODULE_SCOPE int TclIsZipfsPath(const char *path);
MODULE_SCOPE void TclZipfsFinalize(void);
MODULE_SCOPE Tcl_Obj * TclGetObjNameOfShlib(void);
MODULE_SCOPE void TclSetObjNameOfShlib(Tcl_Obj *namePtr, Tcl_Encoding);
/*
* Many parsing tasks need a common definition of whitespace.
@@ -3656,7 +3721,7 @@ MODULE_SCOPE void TclZipfsFinalize(void);
MODULE_SCOPE int TclIsSpaceProc(int byte);
#define TclIsSpaceProcM(byte) \
(((byte) > 0x20) ? 0 : TclIsSpaceProc(byte))
(((unsigned)(byte) > 0x20) ? 0 : TclIsSpaceProc(byte))
/*
*----------------------------------------------------------------
@@ -3764,6 +3829,7 @@ MODULE_SCOPE Tcl_ObjCmdProc Tcl_SplitObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SocketObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SourceObjCmd;
MODULE_SCOPE Tcl_Command TclInitStringCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Command TclInitUnicodeCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SubstObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SwitchObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc Tcl_TellObjCmd;
@@ -3808,6 +3874,8 @@ MODULE_SCOPE CompileProc TclCompileDictIncrCmd;
MODULE_SCOPE CompileProc TclCompileDictLappendCmd;
MODULE_SCOPE CompileProc TclCompileDictMapCmd;
MODULE_SCOPE CompileProc TclCompileDictMergeCmd;
MODULE_SCOPE CompileProc TclCompileDictRemoveCmd;
MODULE_SCOPE CompileProc TclCompileDictReplaceCmd;
MODULE_SCOPE CompileProc TclCompileDictSetCmd;
MODULE_SCOPE CompileProc TclCompileDictUnsetCmd;
MODULE_SCOPE CompileProc TclCompileDictUpdateCmd;
@@ -3825,18 +3893,22 @@ MODULE_SCOPE CompileProc TclCompileInfoCoroutineCmd;
MODULE_SCOPE CompileProc TclCompileInfoExistsCmd;
MODULE_SCOPE CompileProc TclCompileInfoLevelCmd;
MODULE_SCOPE CompileProc TclCompileInfoObjectClassCmd;
MODULE_SCOPE CompileProc TclCompileInfoObjectCreationIdCmd;
MODULE_SCOPE CompileProc TclCompileInfoObjectIsACmd;
MODULE_SCOPE CompileProc TclCompileInfoObjectNamespaceCmd;
MODULE_SCOPE CompileProc TclCompileIncrCmd;
MODULE_SCOPE CompileProc TclCompileLappendCmd;
MODULE_SCOPE CompileProc TclCompileLassignCmd;
MODULE_SCOPE CompileProc TclCompileLeditCmd;
MODULE_SCOPE CompileProc TclCompileLindexCmd;
MODULE_SCOPE CompileProc TclCompileLinsertCmd;
MODULE_SCOPE CompileProc TclCompileListCmd;
MODULE_SCOPE CompileProc TclCompileLlengthCmd;
MODULE_SCOPE CompileProc TclCompileLmapCmd;
MODULE_SCOPE CompileProc TclCompileLpopCmd;
MODULE_SCOPE CompileProc TclCompileLrangeCmd;
MODULE_SCOPE CompileProc TclCompileLreplaceCmd;
MODULE_SCOPE CompileProc TclCompileLseqCmd;
MODULE_SCOPE CompileProc TclCompileLsetCmd;
MODULE_SCOPE CompileProc TclCompileNamespaceCodeCmd;
MODULE_SCOPE CompileProc TclCompileNamespaceCurrentCmd;
@@ -3878,6 +3950,7 @@ MODULE_SCOPE CompileProc TclCompileTailcallCmd;
MODULE_SCOPE CompileProc TclCompileThrowCmd;
MODULE_SCOPE CompileProc TclCompileTryCmd;
MODULE_SCOPE CompileProc TclCompileUnsetCmd;
MODULE_SCOPE CompileProc TclCompileUplevelCmd;
MODULE_SCOPE CompileProc TclCompileUpvarCmd;
MODULE_SCOPE CompileProc TclCompileVariableCmd;
MODULE_SCOPE CompileProc TclCompileWhileCmd;
@@ -3963,9 +4036,10 @@ MODULE_SCOPE Tcl_Obj * TclStringReplace(Tcl_Interp *interp, Tcl_Obj *objPtr,
MODULE_SCOPE Tcl_Obj * TclStringReverse(Tcl_Obj *objPtr, int flags);
/* Flag values for the [string] ensemble functions. */
#define TCL_STRING_MATCH_NOCASE TCL_MATCH_NOCASE /* (1<<0) in tcl.h */
#define TCL_STRING_IN_PLACE (1<<1)
enum StringOpFlags {
TCL_STRING_MATCH_NOCASE = TCL_MATCH_NOCASE, /* (1<<0) in tcl.h */
TCL_STRING_IN_PLACE = (1<<1) /* Do in-place surgery on Tcl_Obj */
};
/*
* Functions defined in generic/tclVar.c and currently exported only for use
@@ -4093,7 +4167,8 @@ MODULE_SCOPE Tcl_Size TclIndexDecode(int encoded, Tcl_Size endValue);
*/
MODULE_SCOPE int TclCommandWordLimitError(Tcl_Interp *interp,
Tcl_Size count);
MODULE_SCOPE int TclListLimitExceededError(Tcl_Interp *interp);
MODULE_SCOPE int TclCannotAllocateError(Tcl_Interp *interp, Tcl_Obj *objPtr);
/* Constants used in index value encoding routines. */
#define TCL_INDEX_END ((Tcl_Size)-2)
@@ -4368,7 +4443,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
*
* MODULE_SCOPE void TclInitEmptyStringRep(Tcl_Obj *objPtr);
* MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
* MODULE_SCOPE void TclAttemptInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
* MODULE_SCOPE const char *TclAttemptInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
*
*----------------------------------------------------------------
*/
@@ -4393,7 +4468,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
(objPtr)->bytes = (char *)Tcl_AttemptAlloc((len) + 1U), \
(objPtr)->length = ((objPtr)->bytes) ? \
(memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (len)), \
(objPtr)->bytes[len] = '\0', (len)) : (-1) \
(objPtr)->bytes[len] = '\0', (Tcl_Size)(len)) : (-1) \
)), (objPtr)->bytes)
/*
@@ -4416,6 +4491,14 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
? (*(lenPtr) = (objPtr)->length, (objPtr)->bytes) \
: (Tcl_GetStringFromObj)((objPtr), (lenPtr)))
#define TclAttemptGetString(objPtr) \
((objPtr)->bytes? (objPtr)->bytes : Tcl_AttemptGetString(objPtr))
#define TclAttemptGetStringFromObj(objPtr, lenPtr) \
((objPtr)->bytes \
? (*(lenPtr) = (objPtr)->length, (objPtr)->bytes) \
: (Tcl_AttemptGetStringFromObj)((objPtr), (lenPtr)))
/*
*----------------------------------------------------------------
* Macro used by the Tcl core to clean out an object's internal
@@ -4787,6 +4870,16 @@ MODULE_SCOPE Tcl_LibraryInitProc Tcl_ABSListTest_Init;
TCL_DTRACE_OBJ_CREATE(objPtr); \
} while (0)
#define TclAttemptNewStringObj(objPtr, s, len) \
do { \
TclIncrObjsAllocated(); \
TclAllocObjStorage(objPtr); \
(objPtr)->refCount = 0; \
TclAttemptInitStringRep((objPtr), (s), (len)); \
(objPtr)->typePtr = NULL; \
TCL_DTRACE_OBJ_CREATE(objPtr); \
} while (0)
#else /* TCL_MEM_DEBUG */
#define TclNewIntObj(objPtr, w) \
(objPtr) = Tcl_NewWideIntObj(w)
@@ -4814,6 +4907,10 @@ MODULE_SCOPE Tcl_LibraryInitProc Tcl_ABSListTest_Init;
#define TclNewStringObj(objPtr, s, len) \
(objPtr) = Tcl_NewStringObj((s), (len))
#define TclAttemptNewStringObj(objPtr, s, len) \
(objPtr) = Tcl_AttemptNewStringObj((s), (len))
#endif /* TCL_MEM_DEBUG */
/*
+5 -3
View File
@@ -569,7 +569,8 @@ EXTERN void TclStaticLibrary(Tcl_Interp *interp,
const char *prefix,
Tcl_LibraryInitProc *initProc,
Tcl_LibraryInitProc *safeInitProc);
/* Slot 258 is reserved */
/* 258 */
EXTERN int TclMSB(unsigned long long n);
/* Slot 259 is reserved */
/* Slot 260 is reserved */
/* 261 */
@@ -837,7 +838,7 @@ typedef struct TclIntStubs {
int (*tclPtrObjMakeUpvar) (Tcl_Interp *interp, Tcl_Var otherPtr, Tcl_Obj *myNamePtr, int myFlags); /* 255 */
int (*tclPtrUnsetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 256 */
void (*tclStaticLibrary) (Tcl_Interp *interp, const char *prefix, Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc); /* 257 */
void (*reserved258)(void);
int (*tclMSB) (unsigned long long n); /* 258 */
void (*reserved259)(void);
void (*reserved260)(void);
void (*tclUnusedStubEntry) (void); /* 261 */
@@ -1252,7 +1253,8 @@ extern const TclIntStubs *tclIntStubsPtr;
(tclIntStubsPtr->tclPtrUnsetVar) /* 256 */
#define TclStaticLibrary \
(tclIntStubsPtr->tclStaticLibrary) /* 257 */
/* Slot 258 is reserved */
#define TclMSB \
(tclIntStubsPtr->tclMSB) /* 258 */
/* Slot 259 is reserved */
/* Slot 260 is reserved */
#define TclUnusedStubEntry \
+1 -1
View File
@@ -232,7 +232,7 @@ MODULE_SCOPE int TclMacOSXMatchType(Tcl_Interp *interp,
#endif
#if defined(_WIN32)
# if !defined(TCL_NO_DEPRECATED)
# ifndef TCL_NO_DEPRECATED
# define TclWinConvertError Tcl_WinConvertError
# define TclWinConvertWSAError Tcl_WinConvertError
# define TclWinNToHS ntohs
+27 -19
View File
@@ -221,10 +221,6 @@ enum LimitHandlerFlags {
* Prototypes for local static functions:
*/
static int AliasCreate(Tcl_Interp *interp,
Tcl_Interp *childInterp, Tcl_Interp *parentInterp,
Tcl_Obj *namePtr, Tcl_Obj *targetPtr, Tcl_Size objc,
Tcl_Obj *const objv[]);
static int AliasDelete(Tcl_Interp *interp,
Tcl_Interp *childInterp, Tcl_Obj *namePtr);
static int AliasDescribe(Tcl_Interp *interp,
@@ -701,7 +697,7 @@ NRInterpCmd(
return TCL_ERROR;
}
return AliasCreate(interp, childInterp, parentInterp, objv[3],
return TclAliasCreate(interp, childInterp, parentInterp, objv[3],
objv[5], objc - 6, objv + 6);
}
@@ -756,6 +752,8 @@ NRInterpCmd(
case OPT_LAST:
i++;
goto endOfForLoop;
default:
TCL_UNREACHABLE();
}
}
@@ -1022,8 +1020,7 @@ NRInterpCmd(
case LIMIT_TYPE_TIME:
return ChildTimeLimitCmd(interp, childInterp, 4, objc, objv);
default:
Tcl_Panic("unreachable");
return TCL_ERROR;
TCL_UNREACHABLE();
}
}
case OPT_MARKTRUSTED:
@@ -1147,8 +1144,7 @@ NRInterpCmd(
return TCL_OK;
}
default:
Tcl_Panic("unreachable");
return TCL_ERROR;
TCL_UNREACHABLE();
}
}
@@ -1232,7 +1228,7 @@ Tcl_CreateAlias(
targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
Tcl_IncrRefCount(targetObjPtr);
result = AliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
result = TclAliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
targetObjPtr, argc, objv);
for (i = 0; i < argc; i++) {
@@ -1279,7 +1275,7 @@ Tcl_CreateAliasObj(
targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
Tcl_IncrRefCount(targetObjPtr);
result = AliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
result = TclAliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
targetObjPtr, objc, objv);
Tcl_DecrRefCount(childObjPtr);
@@ -1452,7 +1448,7 @@ TclPreventAliasLoop(
/*
*----------------------------------------------------------------------
*
* AliasCreate --
* TclAliasCreate --
*
* Helper function to do the work to actually create an alias.
*
@@ -1466,8 +1462,8 @@ TclPreventAliasLoop(
*----------------------------------------------------------------------
*/
static int
AliasCreate(
int
TclAliasCreate(
Tcl_Interp *interp, /* Interp for error reporting. */
Tcl_Interp *childInterp, /* Interp where alias cmd will live or from
* which alias will be deleted. */
@@ -2468,7 +2464,7 @@ ChildCreate(
TclNewLiteralStringObj(clockObj, "clock");
Tcl_IncrRefCount(clockObj);
status = AliasCreate(interp, childInterp, parentInterp, clockObj,
status = TclAliasCreate(interp, childInterp, parentInterp, clockObj,
clockObj, 0, NULL);
Tcl_DecrRefCount(clockObj);
if (status != TCL_OK) {
@@ -2558,7 +2554,7 @@ NRChildCmd(
return AliasDelete(interp, childInterp, objv[2]);
}
} else {
return AliasCreate(interp, childInterp, interp, objv[2],
return TclAliasCreate(interp, childInterp, interp, objv[2],
objv[3], objc - 4, objv + 4);
}
}
@@ -2677,9 +2673,10 @@ NRChildCmd(
return ChildCommandLimitCmd(interp, childInterp, 3, objc,objv);
case LIMIT_TYPE_TIME:
return ChildTimeLimitCmd(interp, childInterp, 3, objc, objv);
default:
TCL_UNREACHABLE();
}
}
break;
case OPT_MARKTRUSTED:
if (objc != 2) {
Tcl_WrongNumArgs(interp, 2, objv, NULL);
@@ -2692,6 +2689,8 @@ NRChildCmd(
return TCL_ERROR;
}
return ChildRecursionLimit(interp, childInterp, objc - 2, objv + 2);
default:
TCL_UNREACHABLE();
}
return TCL_ERROR;
@@ -4529,6 +4528,8 @@ ChildCommandLimitCmd(
Tcl_NewWideIntObj(Tcl_LimitGetCommands(childInterp)));
}
break;
default:
TCL_UNREACHABLE();
}
return TCL_OK;
} else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
@@ -4537,7 +4538,8 @@ ChildCommandLimitCmd(
} else {
Tcl_Size i, scriptLen = 0, limitLen = 0;
Tcl_Obj *scriptObj = NULL, *granObj = NULL, *limitObj = NULL;
int gran = 0, limit = 0;
int gran = 0;
Tcl_Size limit = 0;
for (i=consumedObjc ; i<objc ; i+=2) {
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
@@ -4568,7 +4570,7 @@ ChildCommandLimitCmd(
if (limitLen == 0) {
break;
}
if (TclGetIntFromObj(interp, objv[i+1], &limit) != TCL_OK) {
if (Tcl_GetSizeIntFromObj(interp, objv[i+1], &limit) != TCL_OK) {
return TCL_ERROR;
}
if (limit < 0) {
@@ -4579,6 +4581,8 @@ ChildCommandLimitCmd(
return TCL_ERROR;
}
break;
default:
TCL_UNREACHABLE();
}
}
if (scriptObj != NULL) {
@@ -4729,6 +4733,8 @@ ChildTimeLimitCmd(
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(limitMoment.sec));
}
break;
default:
TCL_UNREACHABLE();
}
return TCL_OK;
} else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
@@ -4802,6 +4808,8 @@ ChildTimeLimitCmd(
}
limitMoment.sec = (long long) tmp;
break;
default:
TCL_UNREACHABLE();
}
}
if (milliObj != NULL || secObj != NULL) {
+1 -1
View File
@@ -1316,7 +1316,7 @@ ObjValue(
Tcl_Obj *uwObj;
TclNewUIntObj(uwObj, linkPtr->lastValue.uw);
return uwObj;
}
}
case TCL_LINK_STRING:
p = LinkedVar(char *);
+101 -69
View File
@@ -39,32 +39,31 @@
#ifdef ENABLE_LIST_ASSERTS
#define LIST_ASSERT(cond_) assert(cond_)
#define LIST_ASSERT(cond_) \
assert(cond_)
/*
* LIST_INDEX_ASSERT is to catch errors with negative indices and counts
* being passed AFTER validation. On Tcl9 length types are unsigned hence
* the checks against LIST_MAX. On Tcl8 length types are signed hence the
* also checks against 0.
*/
#define LIST_INDEX_ASSERT(idxarg_) \
do { \
Tcl_Size idx_ = (idxarg_); /* To guard against ++ etc. */ \
LIST_ASSERT(idx_ >= 0 && idx_ < LIST_MAX); \
#define LIST_INDEX_ASSERT(idxarg_) \
do { \
Tcl_Size idx_ = (idxarg_); /* To guard against ++ etc. */ \
LIST_ASSERT(idx_ >= 0 && idx_ < LIST_MAX); \
} while (0)
/* Ditto for counts except upper limit is different */
#define LIST_COUNT_ASSERT(countarg_) \
do { \
Tcl_Size count_ = (countarg_); /* To guard against ++ etc. */ \
LIST_ASSERT(count_ >= 0 && count_ <= LIST_MAX); \
#define LIST_COUNT_ASSERT(countarg_) \
do { \
Tcl_Size count_ = (countarg_); /* To guard against ++ etc. */ \
LIST_ASSERT(count_ >= 0 && count_ <= LIST_MAX); \
} while (0)
#else
#define LIST_ASSERT(cond_) ((void) 0)
#define LIST_INDEX_ASSERT(idx_) ((void) 0)
#define LIST_COUNT_ASSERT(count_) ((void) 0)
#endif
#else // !ENABLE_LIST_ASSERTS
#define LIST_ASSERT(cond_) ((void) 0)
#define LIST_INDEX_ASSERT(idx_) ((void) 0)
#define LIST_COUNT_ASSERT(count_) ((void) 0)
#endif // ENABLE_LIST_ASSERTS
/* Checks for when caller should have already converted to internal list type */
#define LIST_ASSERT_TYPE(listObj_) \
@@ -105,13 +104,15 @@
* - Finally if LISTREP_SPACE_ONLY_BACK is present, ALL extra space is at
* the back.
*/
#define LISTREP_PANIC_ON_FAIL 0x00000001
#define LISTREP_SPACE_FAVOR_FRONT 0x00000002
#define LISTREP_SPACE_FAVOR_BACK 0x00000004
#define LISTREP_SPACE_ONLY_BACK 0x00000008
enum ListRepresentationFlags {
LISTREP_PANIC_ON_FAIL = 1,
LISTREP_SPACE_FAVOR_FRONT = 2,
LISTREP_SPACE_FAVOR_BACK = 4,
LISTREP_SPACE_ONLY_BACK = 8
};
#define LISTREP_SPACE_FAVOR_NONE \
(LISTREP_SPACE_FAVOR_FRONT | LISTREP_SPACE_FAVOR_BACK)
#define LISTREP_SPACE_FLAGS \
#define LISTREP_SPACE_FLAGS \
(LISTREP_SPACE_FAVOR_FRONT | LISTREP_SPACE_FAVOR_BACK \
| LISTREP_SPACE_ONLY_BACK)
@@ -119,7 +120,6 @@
* Prototypes for non-inline static functions defined later in this file:
*/
static int MemoryAllocationError(Tcl_Interp *, size_t size);
static int ListLimitExceededError(Tcl_Interp *);
static ListStore *ListStoreNew(Tcl_Size objc, Tcl_Obj *const objv[], int flags);
static int ListRepInit(Tcl_Size objc, Tcl_Obj *const objv[], int flags, ListRep *);
static int ListRepInitAttempt(Tcl_Interp *,
@@ -199,26 +199,26 @@ const Tcl_ObjType tclListType = {
* passed ListRep) and frees it first. Additionally invalidates the string
* representation. Generally used when modifying a Tcl_Obj value.
*/
#define ListObjStompRep(objPtr_, repPtr_) \
do { \
(objPtr_)->internalRep.twoPtrValue.ptr1 = (repPtr_)->storePtr; \
(objPtr_)->internalRep.twoPtrValue.ptr2 = (repPtr_)->spanPtr; \
(objPtr_)->typePtr = &tclListType; \
#define ListObjStompRep(objPtr_, repPtr_) \
do { \
(objPtr_)->internalRep.twoPtrValue.ptr1 = (repPtr_)->storePtr; \
(objPtr_)->internalRep.twoPtrValue.ptr2 = (repPtr_)->spanPtr; \
(objPtr_)->typePtr = &tclListType; \
} while (0)
#define ListObjOverwriteRep(objPtr_, repPtr_) \
do { \
ListRepIncrRefs(repPtr_); \
ListObjStompRep(objPtr_, repPtr_); \
do { \
ListRepIncrRefs(repPtr_); \
ListObjStompRep(objPtr_, repPtr_); \
} while (0)
#define ListObjReplaceRepAndInvalidate(objPtr_, repPtr_) \
do { \
/* Note order important, don't use ListObjOverwriteRep! */ \
ListRepIncrRefs(repPtr_); \
TclFreeInternalRep(objPtr_); \
TclInvalidateStringRep(objPtr_); \
ListObjStompRep(objPtr_, repPtr_); \
#define ListObjReplaceRepAndInvalidate(objPtr_, repPtr_) \
do { \
/* Note order important, don't use ListObjOverwriteRep! */ \
ListRepIncrRefs(repPtr_); \
TclFreeInternalRep(objPtr_); \
TclInvalidateStringRep(objPtr_); \
ListObjStompRep(objPtr_, repPtr_); \
} while (0)
/*
@@ -481,7 +481,7 @@ MemoryAllocationError(
/*
*------------------------------------------------------------------------
*
* ListLimitExceeded --
* TclListLimitExceededError --
*
* Generates an error for exceeding maximum list size.
*
@@ -493,13 +493,19 @@ MemoryAllocationError(
*
*------------------------------------------------------------------------
*/
static int
ListLimitExceededError(
int
TclListLimitExceededError(
Tcl_Interp *interp)
{
/*
* As an aside, note there is no parameter passed for the bad length
* because the cverflow is computationally detected and does not fit
* in Tcl_Size.
*/
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"max length of a Tcl list exceeded", -1));
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("max length (%" TCL_SIZE_MODIFIER
"d) of a Tcl list exceeded", (Tcl_Size)LIST_MAX));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
}
return TCL_ERROR;
@@ -640,12 +646,12 @@ ListRepValidate(
(void)storePtr; /* To stop gcc from whining about unused vars */
#define INVARIANT(cond_) \
do { \
if (!(cond_)) { \
condition = #cond_; \
goto failure; \
} \
#define INVARIANT(cond_) \
do { \
if (!(cond_)) { \
condition = #cond_; \
goto failure; \
} \
} while (0)
/* Separate each condition so line number gives exact reason for failure */
@@ -671,14 +677,11 @@ ListRepValidate(
INVARIANT(ListRepStart(repPtr) <= (storePtr->firstUsed + storePtr->numUsed - ListRepLength(repPtr)));
#undef INVARIANT
return;
failure:
failure:
Tcl_Panic("List internal failure in %s line %d. Condition: %s",
file,
lineNum,
condition);
file, lineNum, condition);
}
/*
@@ -705,7 +708,7 @@ TclListObjValidate(
ListRep listRep;
if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {
Tcl_Panic("Object passed to TclListObjValidate cannot be converted to "
"a list object.");
"a list object.");
}
ListRepValidate(&listRep, __FILE__, __LINE__);
}
@@ -942,7 +945,7 @@ ListRepInitAttempt(
if (result != TCL_OK && interp != NULL) {
if (objc > LIST_MAX) {
ListLimitExceededError(interp);
TclListLimitExceededError(interp);
} else {
MemoryAllocationError(interp, LIST_SIZE(objc));
}
@@ -1197,6 +1200,7 @@ Tcl_DbNewListObj(
*
*------------------------------------------------------------------------
*/
#if 0
Tcl_Obj *
TclNewListObj2(
Tcl_Size objc1, /* Count of objects referenced by objv1. */
@@ -1230,6 +1234,7 @@ TclNewListObj2(
storePtr->numUsed = objc;
return listObj;
}
#endif
/*
*----------------------------------------------------------------------
@@ -1457,7 +1462,7 @@ ListRepRange(
if (rangeStart == 0 && rangeEnd == (numSrcElems-1)) {
/* Option 0 - entire list. This may be used to canonicalize */
/* T:listrep-1.10.1,2.8.1 */
*rangeRepPtr = *srcRepPtr; /* Not ref counts not incremented */
*rangeRepPtr = *srcRepPtr; /* Note ref counts not incremented */
} else if (rangeStart == 0 && (!preserveSrcRep)
&& (!ListRepIsShared(srcRepPtr) && srcRepPtr->spanPtr == NULL)) {
/* Option 1 - Special case unshared, exclude end elements, no span */
@@ -1754,8 +1759,8 @@ Tcl_ListObjAppendList(
*
*------------------------------------------------------------------------
*/
int
TclListObjAppendElements (
int
TclListObjAppendElements(
Tcl_Interp *interp, /* Used to report errors if not NULL. */
Tcl_Obj *toObj, /* List object to append */
Tcl_Size elemCount, /* Number of elements in elemObjs[] */
@@ -1792,7 +1797,7 @@ Tcl_ListObjAppendList(
ListRepElements(&listRep, toLen, toObjv);
if (elemCount > LIST_MAX || toLen > (LIST_MAX - elemCount)) {
return ListLimitExceededError(interp);
return TclListLimitExceededError(interp);
}
finalLen = toLen + elemCount;
@@ -2133,12 +2138,12 @@ Tcl_ListObjReplace(
if (numToDelete < 0) {
numToDelete = 0;
} else if (first > LIST_MAX - numToDelete /* Handle integer overflow */
|| origListLen < first + numToDelete) {
|| origListLen < first + numToDelete) {
numToDelete = origListLen - first;
}
if (numToInsert > LIST_MAX - (origListLen - numToDelete)) {
return ListLimitExceededError(interp);
return TclListLimitExceededError(interp);
}
if ((first+numToDelete) >= origListLen) {
@@ -2664,14 +2669,14 @@ TclLindexFlat(
Tcl_Size i;
/* Handle AbstractList as special case */
if (TclObjTypeHasProc(listObj,indexProc)) {
if (indexCount == 1 && TclObjTypeHasProc(listObj,indexProc)) {
Tcl_Size listLen = TclObjTypeLength(listObj);
Tcl_Size index;
Tcl_Obj *elemObj = listObj; /* for lindex without indices return list */
for (i=0 ; i<indexCount && listObj ; i++) {
if (TclGetIntForIndexM(interp, indexArray[i], /*endValue*/ listLen-1,
&index) == TCL_OK) {
// TODO: ???
&index) != TCL_OK) {
return NULL;
}
if (i==0) {
if (TclObjTypeIndex(interp, listObj, index, &elemObj) != TCL_OK) {
@@ -2684,6 +2689,13 @@ TclLindexFlat(
elemObj = e2Obj;
}
}
if (elemObj == NULL) {
/*
* TclObjTypeIndex returns TCL_OK with NULL in elemObj if
* index was out of bounds.
*/
TclNewObj(elemObj);
}
Tcl_IncrRefCount(elemObj);
return elemObj;
}
@@ -2720,6 +2732,7 @@ TclLindexFlat(
Tcl_IncrRefCount(listObj);
} else {
Tcl_Obj *itemObj;
/* TODO - this will cause shimmering of inner abstract lists! */
/*
* Must set the internal rep again because it may have been
* changed by TclGetIntForIndexM. See test lindex-8.4.
@@ -3531,14 +3544,29 @@ UpdateStringOfList(
flagPtr = localFlags;
} else {
/* We know numElems <= LIST_MAX, so this is safe. */
flagPtr = (char *)Tcl_Alloc(numElems);
flagPtr = (char *)Tcl_AttemptAlloc(numElems);
if (!flagPtr) {
listObj->length = numElems - 1;
allocError:
/* Allocation error. Just give up. */
if (listObj->bytes) {
Tcl_Free(listObj->bytes);
listObj->bytes = NULL;
}
return;
}
}
for (i = 0; i < numElems; i++) {
flagPtr[i] = (i ? TCL_DONT_QUOTE_HASH : 0);
elem = TclGetStringFromObj(elemPtrs[i], &length);
elem = TclAttemptGetStringFromObj(elemPtrs[i], &length);
if (!elem) {
listObj->length = elemPtrs[i]->length;
goto allocError;
}
bytesNeeded += TclScanElement(elem, length, flagPtr+i);
if (bytesNeeded > SIZE_MAX - numElems) {
Tcl_Panic("max size for a Tcl value (%" TCL_Z_MODIFIER "u bytes) exceeded", SIZE_MAX);
listObj->length = bytesNeeded;
goto allocError;
}
}
bytesNeeded += numElems - 1;
@@ -3553,7 +3581,11 @@ UpdateStringOfList(
if (i) {
flagPtr[i] |= TCL_DONT_QUOTE_HASH;
}
elem = TclGetStringFromObj(elemPtrs[i], &length);
elem = TclAttemptGetStringFromObj(elemPtrs[i], &length);
if (!elem) {
listObj->length = elemPtrs[i]->length;
goto allocError;
}
dst += TclConvertElement(elem, length, dst, flagPtr[i]);
*dst++ = ' ';
}
@@ -3619,7 +3651,7 @@ TclListTestObj(
ListObjReplaceRepAndInvalidate(listObj, &listRep);
return listObj;
}
/*
* Local Variables:
* mode: c
File diff suppressed because it is too large Load Diff
+51 -8
View File
@@ -250,8 +250,9 @@ TclCreateLiteral(
if ((flags & LITERAL_ON_HEAP)) {
objPtr->bytes = (char *) bytes;
objPtr->length = length;
} else {
TclInitStringRep(objPtr, bytes, length);
} else if (!TclAttemptInitStringRep(objPtr, bytes, length)) {
Tcl_DecrRefCount(objPtr);
return NULL;
}
/* Should the new literal be shared globally? */
@@ -506,7 +507,7 @@ static LiteralEntry *
LookupLiteralEntry(
Tcl_Interp *interp, /* Interpreter for which objPtr was created to
* hold a literal. */
Tcl_Obj *objPtr) /* Points to a Tcl object holding a literal
Tcl_Obj *objPtr) /* Points to a Tcl object holding a literal
* that was previously created by a call to
* TclRegisterLiteral. */
{
@@ -552,7 +553,7 @@ void
TclHideLiteral(
Tcl_Interp *interp, /* Interpreter for which objPtr was created to
* hold a literal. */
CompileEnv *envPtr,/* Points to CompileEnv whose literal array
CompileEnv *envPtr, /* Points to CompileEnv whose literal array
* contains the entry being hidden. */
int index) /* The index of the entry in the literal
* array. */
@@ -616,7 +617,7 @@ TclHideLiteral(
int
TclAddLiteralObj(
CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
CompileEnv *envPtr, /* Points to CompileEnv in whose literal array
* the object is to be inserted. */
Tcl_Obj *objPtr, /* The object to insert into the array. */
LiteralEntry **litPtrPtr) /* The location where the pointer to the new
@@ -649,6 +650,48 @@ TclAddLiteralObj(
return (int)objIndex;
}
/*
*----------------------------------------------------------------------
*
* TclRegisterLiteralObj --
*
* Find, or if necessary create, an object in a CompileEnv literal array
* that has a string representation matching the argument object.
*
* Results:
* The index in the CompileEnv's literal array that references a shared
* literal matching the string. The object is created if necessary.
*
* Side effects:
* To maximize sharing, we look up the string in the interpreter's global
* literal table. If not found, we create a new shared literal in the
* global table. We then add a reference to the shared literal in the
* CompileEnv's literal array.
*
* The reference count of the argument object is bounced, so that the
* normal case where the object is zero ref count (as it is really acting
* as a local worker buffer) doesn't need explicit refcount handling by
* the caller.
*
*----------------------------------------------------------------------
*/
int
TclRegisterLiteralObj(
CompileEnv *envPtr, /* Points to CompileEnv in whose literal array
* the object is to be inserted. */
Tcl_Obj *objPtr, /* The object to insert into the array. */
int flags) /* If LITERAL_CMD_NAME then the literal should
* not be shared across namespaces.
* LITERAL_ON_HEAP is unsupported/ignored. */
{
Tcl_Size length;
const char *bytes = Tcl_GetStringFromObj(objPtr, &length);
int num = TclRegisterLiteral(envPtr, bytes, length,
flags & ~LITERAL_ON_HEAP);
Tcl_BounceRefCount(objPtr);
return num;
}
/*
*----------------------------------------------------------------------
*
@@ -669,7 +712,7 @@ TclAddLiteralObj(
static size_t
AddLocalLiteralEntry(
CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
CompileEnv *envPtr, /* Points to CompileEnv in whose literal array
* the object is to be inserted. */
Tcl_Obj *objPtr, /* The literal to add to the CompileEnv. */
size_t localHash) /* Hash value for the literal's string. */
@@ -748,7 +791,7 @@ AddLocalLiteralEntry(
static void
ExpandLocalLiteralArray(
CompileEnv *envPtr)/* Points to the CompileEnv whose object array
CompileEnv *envPtr) /* Points to the CompileEnv whose object array
* must be enlarged. */
{
/*
@@ -830,7 +873,7 @@ void
TclReleaseLiteral(
Tcl_Interp *interp, /* Interpreter for which objPtr was created to
* hold a literal. */
Tcl_Obj *objPtr) /* Points to a literal object that was
Tcl_Obj *objPtr) /* Points to a literal object that was
* previously created by a call to
* TclRegisterLiteral. */
{
+20 -11
View File
@@ -85,6 +85,12 @@ typedef struct InterpLibrary {
* for end of list. */
} InterpLibrary;
/*
* Associated data key used to look up the linked list of libraries registered
* in the interpreter.
*/
#define ASSOC_KEY "tclLoad"
/*
* Prototypes for functions that are private to this file:
*/
@@ -157,13 +163,14 @@ Tcl_LoadObjCmd(
&index) != TCL_OK) {
return TCL_ERROR;
}
++objv; --objc;
++objv;
--objc;
if (LOAD_GLOBAL == index) {
flags |= TCL_LOAD_GLOBAL;
} else if (LOAD_LAZY == index) {
flags |= TCL_LOAD_LAZY;
} else {
break;
break;
}
}
if ((objc < 2) || (objc > 4)) {
@@ -278,7 +285,7 @@ Tcl_LoadObjCmd(
*/
if (libraryPtr != NULL) {
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, ASSOC_KEY, NULL);
for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
if (ipPtr->libraryPtr == libraryPtr) {
code = TCL_OK;
@@ -514,11 +521,11 @@ Tcl_LoadObjCmd(
* static libraries at the head of the linked list!
*/
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, ASSOC_KEY, NULL);
ipPtr = (InterpLibrary *)Tcl_Alloc(sizeof(InterpLibrary));
ipPtr->libraryPtr = libraryPtr;
ipPtr->nextPtr = ipFirstPtr;
Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipPtr);
Tcl_SetAssocData(target, ASSOC_KEY, LoadCleanupProc, ipPtr);
done:
Tcl_DStringFree(&pfx);
@@ -599,6 +606,8 @@ Tcl_UnloadObjCmd(
case UNLOAD_LAST: /* -- */
i++;
goto endOfForLoop;
default:
TCL_UNREACHABLE();
}
}
endOfForLoop:
@@ -719,7 +728,7 @@ Tcl_UnloadObjCmd(
code = TCL_ERROR;
if (libraryPtr != NULL) {
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, ASSOC_KEY, NULL);
for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
if (ipPtr->libraryPtr == libraryPtr) {
code = TCL_OK;
@@ -861,7 +870,7 @@ UnloadLibrary(
*/
if (!interpExiting) {
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, ASSOC_KEY, NULL);
if (ipFirstPtr) {
ipPtr = ipFirstPtr;
if (ipPtr->libraryPtr == libraryPtr) {
@@ -878,7 +887,7 @@ UnloadLibrary(
}
}
Tcl_Free(ipPtr);
Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr);
Tcl_SetAssocData(target, ASSOC_KEY, LoadCleanupProc, ipFirstPtr);
}
}
@@ -1055,7 +1064,7 @@ Tcl_StaticLibrary(
* it's already loaded.
*/
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(interp, "tclLoad", NULL);
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
if (ipPtr->libraryPtr == libraryPtr) {
return;
@@ -1070,7 +1079,7 @@ Tcl_StaticLibrary(
ipPtr = (InterpLibrary *)Tcl_Alloc(sizeof(InterpLibrary));
ipPtr->libraryPtr = libraryPtr;
ipPtr->nextPtr = ipFirstPtr;
Tcl_SetAssocData(interp, "tclLoad", LoadCleanupProc, ipPtr);
Tcl_SetAssocData(interp, ASSOC_KEY, LoadCleanupProc, ipPtr);
}
}
@@ -1130,7 +1139,7 @@ TclGetLoadedLibraries(
if (target == NULL) {
return TCL_ERROR;
}
ipPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
ipPtr = (InterpLibrary *)Tcl_GetAssocData(target, ASSOC_KEY, NULL);
/*
* Return information about all of the available libraries.
+37 -11
View File
@@ -533,13 +533,26 @@ Tcl_MainEx(
} else if (is.tty) {
resultPtr = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(resultPtr);
(void)Tcl_GetStringFromObj(resultPtr, &length);
chan = Tcl_GetStdChannel(TCL_STDOUT);
if ((length > 0) && chan) {
if (Tcl_WriteObj(chan, resultPtr) < 0) {
Tcl_WriteChars(chan, ENCODING_ERROR, -1);
(void)Tcl_AttemptGetStringFromObj(resultPtr, &length);
if (!resultPtr->bytes) {
chan = Tcl_GetStdChannel(TCL_STDERR);
if (chan) {
char buf[24];
snprintf(buf, sizeof(buf), "%" TCL_SIZE_MODIFIER "d", resultPtr->length + 1);
Tcl_WriteChars(chan, "cannot allocate ", -1);
Tcl_WriteChars(chan, buf, -1);
Tcl_WriteChars(chan, " bytes for type \'", -1);
Tcl_WriteChars(chan, resultPtr->typePtr->name , -1);
Tcl_WriteChars(chan, "\'\n", -1);
}
} else {
chan = Tcl_GetStdChannel(TCL_STDOUT);
if ((length > 0) && chan) {
if (Tcl_WriteObj(chan, resultPtr) < 0) {
Tcl_WriteChars(chan, ENCODING_ERROR, -1);
}
Tcl_WriteChars(chan, "\n", 1);
}
Tcl_WriteChars(chan, "\n", 1);
}
Tcl_DecrRefCount(resultPtr);
}
@@ -813,12 +826,25 @@ StdinProc(
chan = Tcl_GetStdChannel(TCL_STDOUT);
Tcl_IncrRefCount(resultPtr);
(void)Tcl_GetStringFromObj(resultPtr, &length);
if ((length > 0) && (chan != NULL)) {
if (Tcl_WriteObj(chan, resultPtr) < 0) {
Tcl_WriteChars(chan, ENCODING_ERROR, -1);
(void)Tcl_AttemptGetStringFromObj(resultPtr, &length);
if (!resultPtr->bytes) {
chan = Tcl_GetStdChannel(TCL_STDERR);
if (chan) {
char buf[24];
snprintf(buf, sizeof(buf), "%" TCL_SIZE_MODIFIER "d", resultPtr->length + 1);
Tcl_WriteChars(chan, "cannot allocate ", -1);
Tcl_WriteChars(chan, buf, -1);
Tcl_WriteChars(chan, " bytes for type \'", -1);
Tcl_WriteChars(chan, resultPtr->typePtr->name , -1);
Tcl_WriteChars(chan, "\'\n", -1);
}
} else {
if ((length > 0) && (chan != NULL)) {
if (Tcl_WriteObj(chan, resultPtr) < 0) {
Tcl_WriteChars(chan, ENCODING_ERROR, -1);
}
Tcl_WriteChars(chan, "\n", 1);
}
Tcl_WriteChars(chan, "\n", 1);
}
Tcl_DecrRefCount(resultPtr);
}
+7 -8
View File
@@ -201,16 +201,15 @@ CreateChildEntry(
Namespace *nsPtr, /* Parent namespace. */
const char *name) /* Simple name to look for. */
{
int newEntry;
#ifndef BREAK_NAMESPACE_COMPAT
return Tcl_CreateHashEntry(&nsPtr->childTable, name, &newEntry);
return Tcl_CreateHashEntry(&nsPtr->childTable, name, NULL);
#else
if (nsPtr->childTablePtr == NULL) {
nsPtr->childTablePtr = (Tcl_HashTable *)
Tcl_Alloc(sizeof(Tcl_HashTable));
Tcl_InitHashTable(nsPtr->childTablePtr, TCL_STRING_KEYS);
}
return Tcl_CreateHashEntry(nsPtr->childTablePtr, name, &newEntry);
return Tcl_CreateHashEntry(nsPtr->childTablePtr, name, NULL);
#endif
}
@@ -3265,7 +3264,7 @@ NamespaceCodeCmd(
* Take care to only check for scoping in precisely the style that
* [::namespace code] generates it. Anything more forgiving can have
* the effect of failing in namespaces that contain their own custom
" "namespace" command. [Bug 3202171].
* "namespace" command. [Bug 3202171].
*/
arg = TclGetStringFromObj(objv[1], &length);
@@ -4745,7 +4744,7 @@ NamespaceWhichCmd(
static const char *const opts[] = {
"-command", "-variable", NULL
};
int lookupType = 0;
enum { OPT_COMMAND, OPT_VARIABLE } lookupType = OPT_COMMAND;
Tcl_Obj *resultPtr;
if (objc < 2 || objc > 3) {
@@ -4770,7 +4769,7 @@ NamespaceWhichCmd(
TclNewObj(resultPtr);
switch (lookupType) {
case 0: { /* -command */
case OPT_COMMAND: {
Tcl_Command cmd = Tcl_GetCommandFromObj(interp, objv[objc-1]);
if (cmd != NULL) {
@@ -4778,7 +4777,7 @@ NamespaceWhichCmd(
}
break;
}
case 1: { /* -variable */
case OPT_VARIABLE: {
Tcl_Var var = Tcl_FindNamespaceVar(interp,
TclGetString(objv[objc-1]), NULL, /*flags*/ 0);
@@ -4909,7 +4908,7 @@ SetNsNameFromAny(
name = TclGetString(objPtr);
TclGetNamespaceForQualName(interp, name, NULL, TCL_FIND_ONLY_NS,
&nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
&nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
if ((nsPtr == NULL) || (nsPtr->flags & NS_DYING)) {
return TCL_ERROR;
+1 -1
View File
@@ -390,7 +390,7 @@ Tcl_DeleteEventSource(
void
Tcl_QueueEvent(
Tcl_Event *evPtr, /* Event to add to queue. The storage space
* must have been allocated the caller with
* must have been allocated by the caller with
* malloc (Tcl_Alloc), and it becomes the
* property of the event queue. It will be
* freed after the event has been handled. */
+350 -115
View File
@@ -16,37 +16,67 @@
#include "tclInt.h"
#include "tclOOInt.h"
/*
* Commands in oo and oo::Helpers.
*/
static const struct StdCommands {
const char *name;
Tcl_ObjCmdProc *objProc;
Tcl_ObjCmdProc *nreProc;
CompileProc *compileProc;
int flags;
} ooCmds[] = {
{"define", TclOODefineObjCmd, NULL, NULL, 0},
{"objdefine", TclOOObjDefObjCmd, NULL, NULL, 0},
{"copy", TclOOCopyObjectCmd, NULL, NULL, 0},
{"DelegateName", TclOODelegateNameObjCmd, NULL, NULL, 0},
{NULL, NULL, NULL, NULL, 0}
}, helpCmds[] = {
{"callback", TclOOCallbackObjCmd, NULL, NULL, 0},
{"mymethod", TclOOCallbackObjCmd, NULL, NULL, 0},
{"classvariable", TclOOClassVariableObjCmd, NULL, NULL, 0},
{"link", TclOOLinkObjCmd, NULL, NULL, 0},
{"next", NULL, TclOONextObjCmd, TclCompileObjectNextCmd, CMD_COMPILES_EXPANDED},
{"nextto", NULL, TclOONextToObjCmd, TclCompileObjectNextToCmd, CMD_COMPILES_EXPANDED},
{"self", TclOOSelfObjCmd, NULL, TclCompileObjectSelfCmd, 0},
{NULL, NULL, NULL, NULL, 0}
};
/*
* Commands in oo::define and oo::objdefine.
*/
static const struct {
static const struct DefineCommands {
const char *name;
Tcl_ObjCmdProc *objProc;
int flag;
} defineCmds[] = {
{"constructor", TclOODefineConstructorObjCmd, 0},
{"classmethod", TclOODefineClassMethodObjCmd, 0},
{"constructor", TclOODefineConstructorObjCmd, 0},
{"definitionnamespace", TclOODefineDefnNsObjCmd, 0},
{"deletemethod", TclOODefineDeleteMethodObjCmd, 0},
{"destructor", TclOODefineDestructorObjCmd, 0},
{"export", TclOODefineExportObjCmd, 0},
{"forward", TclOODefineForwardObjCmd, 0},
{"method", TclOODefineMethodObjCmd, 0},
{"private", TclOODefinePrivateObjCmd, 0},
{"renamemethod", TclOODefineRenameMethodObjCmd, 0},
{"self", TclOODefineSelfObjCmd, 0},
{"unexport", TclOODefineUnexportObjCmd, 0},
{"deletemethod", TclOODefineDeleteMethodObjCmd, 0},
{"destructor", TclOODefineDestructorObjCmd, 0},
{"export", TclOODefineExportObjCmd, 0},
{"forward", TclOODefineForwardObjCmd, 0},
{"initialise", TclOODefineInitialiseObjCmd, 0},
{"initialize", TclOODefineInitialiseObjCmd, 0},
{"method", TclOODefineMethodObjCmd, 0},
{"private", TclOODefinePrivateObjCmd, 0},
{"renamemethod", TclOODefineRenameMethodObjCmd, 0},
{"self", TclOODefineSelfObjCmd, 0},
{"unexport", TclOODefineUnexportObjCmd, 0},
{NULL, NULL, 0}
}, objdefCmds[] = {
{"class", TclOODefineClassObjCmd, 1},
{"deletemethod", TclOODefineDeleteMethodObjCmd, 1},
{"export", TclOODefineExportObjCmd, 1},
{"forward", TclOODefineForwardObjCmd, 1},
{"method", TclOODefineMethodObjCmd, 1},
{"private", TclOODefinePrivateObjCmd, 1},
{"renamemethod", TclOODefineRenameMethodObjCmd, 1},
{"self", TclOODefineObjSelfObjCmd, 0},
{"unexport", TclOODefineUnexportObjCmd, 1},
{"class", TclOODefineClassObjCmd, 1},
{"deletemethod", TclOODefineDeleteMethodObjCmd, 1},
{"export", TclOODefineExportObjCmd, 1},
{"forward", TclOODefineForwardObjCmd, 1},
{"method", TclOODefineMethodObjCmd, 1},
{"private", TclOODefinePrivateObjCmd, 1},
{"renamemethod", TclOODefineRenameMethodObjCmd, 1},
{"self", TclOODefineObjSelfObjCmd, 0},
{"unexport", TclOODefineUnexportObjCmd, 1},
{NULL, NULL, 0}
};
@@ -67,7 +97,7 @@ static int CloneClassMethod(Tcl_Interp *interp, Class *clsPtr,
Method **newMPtrPtr);
static int CloneObjectMethod(Tcl_Interp *interp, Object *oPtr,
Method *mPtr, Tcl_Obj *namePtr);
static void DeletedHelpersNamespace(void *clientData);
static Tcl_NamespaceDeleteProc DeletedHelpersNamespace;
static Tcl_NRPostProc FinalizeAlloc;
static Tcl_NRPostProc FinalizeNext;
static Tcl_NRPostProc FinalizeObjectCall;
@@ -76,23 +106,20 @@ static void InitClassSystemRoots(Tcl_Interp *interp,
Foundation *fPtr);
static int InitFoundation(Tcl_Interp *interp);
static Tcl_InterpDeleteProc KillFoundation;
static void MyDeleted(void *clientData);
static void ObjectNamespaceDeleted(void *clientData);
static void MakeAdditionalClasses(Foundation *fPtr,
Tcl_Namespace *defineNs,
Tcl_Namespace *objDefineNs);
static Tcl_CmdDeleteProc MyDeleted;
static Tcl_NamespaceDeleteProc ObjectNamespaceDeleted;
static Tcl_CommandTraceProc ObjectRenamedTrace;
static inline void RemoveClass(Class **list, size_t num, size_t idx);
static inline void RemoveObject(Object **list, size_t num, size_t idx);
static inline void SquelchCachedName(Object *oPtr);
static int PublicNRObjectCmd(void *clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const *objv);
static int PrivateNRObjectCmd(void *clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const *objv);
static int MyClassNRObjCmd(void *clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const *objv);
static void MyClassDeleted(void *clientData);
static Tcl_ObjCmdProc PublicNRObjectCmd;
static Tcl_ObjCmdProc PrivateNRObjectCmd;
static Tcl_ObjCmdProc MyClassNRObjCmd;
static Tcl_CmdDeleteProc MyClassDeleted;
/*
* Methods in the oo::object and oo::class classes. First, we define a helper
@@ -107,6 +134,7 @@ static void MyClassDeleted(void *clientData);
{TCL_OO_METHOD_VERSION_CURRENT,"core method: "#name,proc,NULL,NULL}}
static const DeclaredClassMethod objMethods[] = {
DCM("<cloned>", 0, TclOO_Object_Cloned),
DCM("destroy", 1, TclOO_Object_Destroy),
DCM("eval", 0, TclOO_Object_Eval),
DCM("unknown", 0, TclOO_Object_Unknown),
@@ -114,6 +142,7 @@ static const DeclaredClassMethod objMethods[] = {
DCM("varname", 0, TclOO_Object_VarName),
{NULL, 0, {0, NULL, NULL, NULL, NULL}}
}, clsMethods[] = {
DCM("<cloned>", 0, TclOO_Class_Cloned),
DCM("create", 1, TclOO_Class_Create),
DCM("new", 1, TclOO_Class_New),
DCM("createWithNamespace", 0, TclOO_Class_CreateNs),
@@ -121,6 +150,13 @@ static const DeclaredClassMethod objMethods[] = {
}, cfgMethods[] = {
DCM("configure", 1, TclOO_Configurable_Configure),
{NULL, 0, {0, NULL, NULL, NULL, NULL}}
}, singletonMethods[] = {
DCM("new", 1, TclOO_Singleton_New),
{NULL, 0, {0, NULL, NULL, NULL, NULL}}
}, singletonInstanceMethods[] = {
DCM("<cloned>", 0, TclOO_SingletonInstance_Cloned),
DCM("destroy", 1, TclOO_SingletonInstance_Destroy),
{NULL, 0, {0, NULL, NULL, NULL, NULL}}
};
/*
@@ -134,25 +170,25 @@ static const Tcl_MethodType classConstructor = {
};
/*
* Scripted parts of TclOO. First, the main script (cannot be outside this
* file).
* And the oo::configurable constructor...
*/
static const Tcl_MethodType configurableConstructor = {
TCL_OO_METHOD_VERSION_CURRENT,
"oo::configurable constructor",
TclOO_Configurable_Constructor, NULL, NULL
};
/*
* The scripted part of TclOO: (legacy) package registration. There's no C API
* at all for doing this, not even internally to Tcl.
*/
static const char initScript[] =
#ifndef TCL_NO_DEPRECATED
"package ifneeded TclOO " TCLOO_PATCHLEVEL " {# Already present, OK?};"
#endif
"package ifneeded tcl::oo " TCLOO_PATCHLEVEL " {# Already present, OK?};"
"namespace eval ::oo { variable version " TCLOO_VERSION " };"
"namespace eval ::oo { variable patchlevel " TCLOO_PATCHLEVEL " };";
/* "tcl_findLibrary tcloo $oo::version $oo::version" */
/* " tcloo.tcl OO_LIBRARY oo::library;"; */
/*
* The scripted part of the definitions of TclOO.
*/
#include "tclOOScript.h"
"package ifneeded tcl::oo " TCLOO_PATCHLEVEL " {# Already present, OK?};";
/*
* The actual definition of the variable holding the TclOO stub table.
@@ -181,6 +217,7 @@ MODULE_SCOPE const TclOOStubs tclOOStubs;
#define IsRootClass(ocPtr) ((ocPtr)->flags & ROOT_CLASS)
#define IsRoot(ocPtr) ((ocPtr)->flags & (ROOT_OBJECT|ROOT_CLASS))
/* Wrapper for removing an item from a "flexible" item list. */
#define RemoveItem(type, lst, i) \
do { \
Remove ## type ((lst).list, (lst).num, i); \
@@ -304,7 +341,8 @@ CreateCmdInNS(
const char *name,
Tcl_ObjCmdProc *cmdProc,
Tcl_ObjCmdProc *nreProc,
CompileProc *compileProc)
CompileProc *compileProc,
int flags)
{
Command *cmdPtr;
@@ -315,6 +353,33 @@ CreateCmdInNS(
namespacePtr, cmdProc, NULL, NULL);
cmdPtr->nreProc = nreProc;
cmdPtr->compileProc = compileProc;
cmdPtr->flags |= flags;
}
/*
* ----------------------------------------------------------------------
*
* CreateConstantInNSStr --
*
* Wrapper around TclCreateConstantInNS to make using it with string
* constants easier.
*
* ----------------------------------------------------------------------
*/
static inline void
CreateConstantInNSStr(
Tcl_Interp *interp,
Tcl_Namespace *namespacePtr,// The namespace to contain the constant.
const char *nameStr, // The unqualified name of the constant.
const char *valueStr) // The value to put in the constant.
{
Tcl_Obj *nameObj = Tcl_NewStringObj(nameStr, TCL_AUTO_LENGTH);
Tcl_IncrRefCount(nameObj);
Tcl_Obj *valueObj = Tcl_NewStringObj(valueStr, TCL_AUTO_LENGTH);
Tcl_IncrRefCount(valueObj);
TclCreateConstantInNS(interp, (Namespace *) namespacePtr, nameObj, valueObj);
Tcl_DecrRefCount(nameObj);
Tcl_DecrRefCount(valueObj);
}
/*
@@ -366,14 +431,20 @@ InitFoundation(
TclNewLiteralStringObj(fPtr->clonedName, "<cloned>");
TclNewLiteralStringObj(fPtr->defineName, "::oo::define");
TclNewLiteralStringObj(fPtr->myName, "my");
TclNewLiteralStringObj(fPtr->mcdName, "::oo::MixinClassDelegates");
TclNewLiteralStringObj(fPtr->slotGetName, "Get");
TclNewLiteralStringObj(fPtr->slotSetName, "Set");
TclNewLiteralStringObj(fPtr->slotResolveName, "Resolve");
TclNewLiteralStringObj(fPtr->slotDefOpName, "--default-operation");
Tcl_IncrRefCount(fPtr->unknownMethodNameObj);
Tcl_IncrRefCount(fPtr->constructorName);
Tcl_IncrRefCount(fPtr->destructorName);
Tcl_IncrRefCount(fPtr->clonedName);
Tcl_IncrRefCount(fPtr->defineName);
Tcl_IncrRefCount(fPtr->myName);
Tcl_IncrRefCount(fPtr->mcdName);
Tcl_IncrRefCount(fPtr->slotGetName);
Tcl_IncrRefCount(fPtr->slotSetName);
Tcl_IncrRefCount(fPtr->slotResolveName);
Tcl_IncrRefCount(fPtr->slotDefOpName);
TclCreateObjCommandInNs(interp, "UnknownDefinition", fPtr->ooNs,
TclOOUnknownDefinition, NULL, NULL);
@@ -418,7 +489,7 @@ InitFoundation(
TclNewLiteralStringObj(namePtr, "new");
TclNewInstanceMethod(interp, (Tcl_Object) fPtr->classCls->thisPtr,
namePtr /* keeps ref */, 0 /* private */, NULL, NULL);
namePtr /*keeps ref*/, 0 /*private*/, NULL, NULL);
Tcl_BounceRefCount(namePtr);
fPtr->classCls->constructorPtr = (Method *) TclNewMethod(
(Tcl_Class) fPtr->classCls, NULL, 0, &classConstructor, NULL);
@@ -428,16 +499,16 @@ InitFoundation(
* ensemble.
*/
CreateCmdInNS(interp, fPtr->helpersNs, "next",
NULL, TclOONextObjCmd, TclCompileObjectNextCmd);
CreateCmdInNS(interp, fPtr->helpersNs, "nextto",
NULL, TclOONextToObjCmd, TclCompileObjectNextToCmd);
CreateCmdInNS(interp, fPtr->helpersNs, "self",
TclOOSelfObjCmd, NULL, TclCompileObjectSelfCmd);
CreateCmdInNS(interp, fPtr->ooNs, "define", TclOODefineObjCmd, NULL, NULL);
CreateCmdInNS(interp, fPtr->ooNs, "objdefine", TclOOObjDefObjCmd, NULL, NULL);
CreateCmdInNS(interp, fPtr->ooNs, "copy", TclOOCopyObjectCmd, NULL, NULL);
for (i = 0 ; helpCmds[i].name ; i++) {
CreateCmdInNS(interp, fPtr->helpersNs, helpCmds[i].name,
helpCmds[i].objProc, helpCmds[i].nreProc,
helpCmds[i].compileProc, helpCmds[i].flags);
}
for (i = 0 ; ooCmds[i].name ; i++) {
CreateCmdInNS(interp, fPtr->ooNs, ooCmds[i].name,
ooCmds[i].objProc, ooCmds[i].nreProc,
ooCmds[i].compileProc, ooCmds[i].flags);
}
TclOOInitInfo(interp);
@@ -449,33 +520,13 @@ InitFoundation(
return TCL_ERROR;
}
/*
* Make the configurable class and install its standard defined method.
*/
MakeAdditionalClasses(fPtr, define, objdef);
Tcl_Object cfgCls = Tcl_NewObjectInstance(interp,
(Tcl_Class) fPtr->classCls, "::oo::configuresupport::configurable",
NULL, TCL_INDEX_NONE, NULL, 0);
TclOODefineBasicMethods(((Object *) cfgCls)->classPtr, cfgMethods);
/*
* Don't have handles to these namespaces, so use Tcl_CreateObjCommand.
*/
Tcl_CreateObjCommand(interp,
"::oo::configuresupport::configurableobject::property",
TclOODefinePropertyCmd, (void *) 1, NULL);
Tcl_CreateObjCommand(interp,
"::oo::configuresupport::configurableclass::property",
TclOODefinePropertyCmd, (void *) 0, NULL);
/*
* Evaluate the remaining definitions, which are a compiled-in Tcl script.
*/
return Tcl_EvalEx(interp, tclOOSetupScript, TCL_INDEX_NONE, 0);
CreateConstantInNSStr(interp, fPtr->ooNs, "version", TCLOO_VERSION);
CreateConstantInNSStr(interp, fPtr->ooNs, "patchlevel", TCLOO_PATCHLEVEL);
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
@@ -567,6 +618,154 @@ InitClassSystemRoots(
*/
}
/*
* ----------------------------------------------------------------------
*
* MarkAsMetaclass --
*
* Make a simple class into a metaclass by making it into a subclass of
* oo::class. Assumes that the previous class it had can be ignored.
*
* ----------------------------------------------------------------------
*/
static inline void
MarkAsMetaclass(
Foundation *fPtr,
Class *classPtr)
{
Class **supers = (Class **) Tcl_Alloc(sizeof(Class *));
supers[0] = fPtr->classCls;
AddRef(supers[0]->thisPtr);
TclOOSetSuperclasses(classPtr, 1, supers);
}
/*
* ----------------------------------------------------------------------
*
* MakeAdditionalClasses --
*
* Make the extra classes in TclOO that aren't core to how it functions.
*
* ----------------------------------------------------------------------
*/
static void
MakeAdditionalClasses(
Foundation *fPtr,
Tcl_Namespace *defineNs,
Tcl_Namespace *objDefineNs)
{
Tcl_Interp *interp = fPtr->interp;
/*
* Make the singleton class, the SingletonInstance class, and install their
* standard defined methods.
*/
// A metaclass that is used to make classes that only permit one instance
// of them to exist. See singleton(n).
Object *singletonObj = (Object *) Tcl_NewObjectInstance(interp,
(Tcl_Class) fPtr->classCls, "::oo::singleton",
NULL, TCL_INDEX_NONE, NULL, 0);
Class *singletonCls = singletonObj->classPtr;
TclOODefineBasicMethods(singletonCls, singletonMethods);
// Set the superclass to oo::class
MarkAsMetaclass(fPtr, singletonCls);
// Unexport methods
TclOOUnexportMethods(singletonCls, "create", "createWithNamespace", NULL);
// A mixin used to make an object so it won't be destroyed or cloned (or
// at least not easily).
Object *singletonInst = (Object *) Tcl_NewObjectInstance(interp,
(Tcl_Class) fPtr->classCls, "::oo::SingletonInstance",
NULL, TCL_INDEX_NONE, NULL, 0);
TclOODefineBasicMethods(singletonInst->classPtr, singletonInstanceMethods);
/*
* Make the abstract class.
*/
// A metaclass that is used to make classes that can't be directly
// instantiated. See abstract(n).
Object *abstractCls = (Object *) Tcl_NewObjectInstance(interp,
(Tcl_Class) fPtr->classCls, "::oo::abstract",
NULL, TCL_INDEX_NONE, NULL, 0);
// Set the superclass to oo::class
MarkAsMetaclass(fPtr, abstractCls->classPtr);
// Unexport methods
TclOOUnexportMethods(abstractCls->classPtr,
"create", "createWithNamespace", "new", NULL);
/*
* Make the configurable class and install its standard defined method.
*/
// The class that contains the implementation of the actual
// 'configure' method (mixed into actually configurable classes).
// The 'configure' method is in tclOOBasic.c.
Object *cfgSupObj = (Object *) Tcl_NewObjectInstance(interp,
(Tcl_Class) fPtr->classCls, "::oo::configuresupport::configurable",
NULL, TCL_INDEX_NONE, NULL, 0);
Class *cfgSupCls = cfgSupObj->classPtr;
TclOODefineBasicMethods(cfgSupCls, cfgMethods);
// Namespaces used as implementation vectors for oo::define and
// oo::objdefine when the class/instance is configurable.
// Note that these also contain commands implemented in C,
// especially the [property] definition command.
Tcl_Namespace *cfgObjNs = Tcl_CreateNamespace(interp,
"::oo::configuresupport::configurableobject", NULL, NULL);
TclCreateObjCommandInNs(interp, "property", cfgObjNs,
TclOODefinePropertyCmd, INT2PTR(1) /*useInstance*/, NULL);
TclCreateObjCommandInNs(interp, "properties", cfgObjNs,
TclOODefinePropertyCmd, INT2PTR(1) /*useInstance*/, NULL);
Tcl_Export(interp, cfgObjNs, "property", /*reset*/1);
TclSetNsPath((Namespace *) cfgObjNs, 1, &objDefineNs);
Tcl_Namespace *cfgClsNs = Tcl_CreateNamespace(interp,
"::oo::configuresupport::configurableclass", NULL, NULL);
TclCreateObjCommandInNs(interp, "property", cfgClsNs,
TclOODefinePropertyCmd, INT2PTR(0) /*useInstance*/, NULL);
TclCreateObjCommandInNs(interp, "properties", cfgClsNs,
TclOODefinePropertyCmd, INT2PTR(0) /*useInstance*/, NULL);
Tcl_Export(interp, cfgClsNs, "property", /*reset*/1);
TclSetNsPath((Namespace *) cfgClsNs, 1, &defineNs);
// A metaclass that is used to make classes that can be configured in
// their creation phase (and later too). All the metaclass itself does is
// arrange for the class created to have a 'configure' method and for
// oo::define and oo::objdefine (on the class and its instances) to have
// a property definition for setting things up for 'configure'.
Object *configurableObj = (Object *) Tcl_NewObjectInstance(interp,
(Tcl_Class) fPtr->classCls, "::oo::configurable",
NULL, TCL_INDEX_NONE, NULL, 0);
Class *configurableCls = configurableObj->classPtr;
MarkAsMetaclass(fPtr, configurableCls);
Tcl_ClassSetConstructor(interp, (Tcl_Class) configurableCls, TclNewMethod(
(Tcl_Class) configurableCls, NULL, 0, &configurableConstructor, NULL));
Tcl_Obj *nsName = Tcl_NewStringObj("::oo::configuresupport::configurableclass",
TCL_AUTO_LENGTH);
Tcl_IncrRefCount(nsName);
if (cfgSupCls->clsDefinitionNs != NULL) {
Tcl_DecrRefCount(cfgSupCls->clsDefinitionNs);
}
cfgSupCls->clsDefinitionNs = nsName;
Tcl_IncrRefCount(nsName);
if (configurableCls->clsDefinitionNs != NULL) {
Tcl_DecrRefCount(configurableCls->clsDefinitionNs);
}
configurableCls->clsDefinitionNs = nsName;
nsName = Tcl_NewStringObj("::oo::configuresupport::configurableobject",
TCL_AUTO_LENGTH);
Tcl_IncrRefCount(nsName);
if (cfgSupCls->objDefinitionNs != NULL) {
Tcl_DecrRefCount(cfgSupCls->objDefinitionNs);
}
cfgSupCls->objDefinitionNs = nsName;
}
/*
* ----------------------------------------------------------------------
*
@@ -612,7 +811,10 @@ KillFoundation(
TclDecrRefCount(fPtr->clonedName);
TclDecrRefCount(fPtr->defineName);
TclDecrRefCount(fPtr->myName);
TclDecrRefCount(fPtr->mcdName);
TclDecrRefCount(fPtr->slotGetName);
TclDecrRefCount(fPtr->slotSetName);
TclDecrRefCount(fPtr->slotResolveName);
TclDecrRefCount(fPtr->slotDefOpName);
TclOODecrRefCount(fPtr->objectCls->thisPtr);
TclOODecrRefCount(fPtr->classCls->thisPtr);
@@ -796,6 +998,7 @@ AllocObject(
oPtr->myclassCommand = TclNRCreateCommandInNs(interp, "myclass",
oPtr->namespacePtr, TclOOMyClassObjCmd, MyClassNRObjCmd, oPtr,
MyClassDeleted);
oPtr->linkedCmdsList = NULL;
return oPtr;
}
@@ -840,6 +1043,17 @@ MyDeleted(
{
Object *oPtr = (Object *) clientData;
if (oPtr->linkedCmdsList) {
Tcl_Size linkc, i;
Tcl_Obj **linkv;
TclListObjGetElements(NULL, oPtr->linkedCmdsList, &linkc, &linkv);
for (i=0 ; i<linkc ; i++) {
Tcl_Obj *link = linkv[i];
(void) Tcl_DeleteCommand(oPtr->fPtr->interp, TclGetString(link));
}
Tcl_DecrRefCount(oPtr->linkedCmdsList);
oPtr->linkedCmdsList = NULL;
}
oPtr->myCommand = NULL;
}
@@ -1240,7 +1454,7 @@ ObjectNamespaceDeleted(
* freed memory.
*/
if (((Command *) oPtr->command)->flags && CMD_DYING) {
if (((Command *) oPtr->command)->flags & CMD_DYING) {
/*
* Something has already started the command deletion process. We can
* go ahead and clean up the namespace,
@@ -1387,7 +1601,6 @@ TclOODecrRefCount(
Object *oPtr)
{
if (oPtr->refCount-- <= 1) {
if (oPtr->classPtr != NULL) {
Tcl_Free(oPtr->classPtr);
}
@@ -1865,6 +2078,16 @@ TclNRNewObjectInstance(
return TclOOInvokeContext(contextPtr, interp, objc, objv);
}
/*
* ----------------------------------------------------------------------
*
* TclNewObjectInstanceCommon --
*
* Common code for handling object allocation. Does the basic object
* structure and class structure allocation.
*
* ----------------------------------------------------------------------
*/
Object *
TclNewObjectInstanceCommon(
Tcl_Interp *interp,
@@ -1930,6 +2153,17 @@ TclNewObjectInstanceCommon(
return oPtr;
}
/*
* ----------------------------------------------------------------------
*
* FinalizeAlloc --
*
* Final stage of NR-aware object allocation, running after the
* constructor has been called to decide whether the construction
* succeeded or failed.
*
* ----------------------------------------------------------------------
*/
static int
FinalizeAlloc(
void *data[],
@@ -2885,7 +3119,6 @@ Tcl_ObjectContextInvokeNext(
CallContext *contextPtr = (CallContext *) context;
size_t savedIndex = contextPtr->index;
size_t savedSkip = contextPtr->skip;
int result;
if (contextPtr->index + 1 >= contextPtr->callPtr->numChain) {
/*
@@ -2895,22 +3128,11 @@ Tcl_ObjectContextInvokeNext(
* unexpectedly.
*/
const char *methodType;
if (Tcl_InterpDeleted(interp)) {
return TCL_OK;
}
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
methodType = "constructor";
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
methodType = "destructor";
} else {
methodType = "method";
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"no next %s implementation", methodType));
"no next %s implementation", TclOOContextTypeName(contextPtr)));
OO_ERROR(interp, NOTHING_NEXT);
return TCL_ERROR;
}
@@ -2932,8 +3154,8 @@ Tcl_ObjectContextInvokeNext(
* Invoke the (advanced) method call context in the caller context.
*/
result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr, objc,
objv);
int result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr,
objc, objv);
/*
* Restore the call chain context index as we've finished the inner invoke
@@ -2964,22 +3186,11 @@ TclNRObjectContextInvokeNext(
* unexpectedly.
*/
const char *methodType;
if (Tcl_InterpDeleted(interp)) {
return TCL_OK;
}
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
methodType = "constructor";
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
methodType = "destructor";
} else {
methodType = "method";
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"no next %s implementation", methodType));
"no next %s implementation", TclOOContextTypeName(contextPtr)));
OO_ERROR(interp, NOTHING_NEXT);
return TCL_ERROR;
}
@@ -3141,6 +3352,30 @@ Tcl_GetObjectName(
return TclOOObjectName(interp, (Object *) object);
}
/*
* ----------------------------------------------------------------------
*
* TclOOObjectMyName --
*
* Utility function that returns the name of the object's [my], or NULL
* if it has been deleted (or otherwise doesn't exist).
*
* ----------------------------------------------------------------------
*/
Tcl_Obj *
TclOOObjectMyName(
Tcl_Interp *interp,
Object *oPtr)
{
if (!oPtr->myCommand) {
return NULL;
}
Tcl_Obj *namePtr;
TclNewObj(namePtr);
Tcl_GetCommandFullName(interp, oPtr->myCommand, namePtr);
return namePtr;
}
/*
* ----------------------------------------------------------------------
*
+2 -1
View File
@@ -20,12 +20,13 @@
*
* tests/oo.test
* tests/ooNext2.test
* tests/ooUtil.test
* unix/tclooConfig.sh
* win/tclooConfig.sh
*/
#define TCLOO_VERSION "1.3"
#define TCLOO_PATCHLEVEL TCLOO_VERSION ".0"
#define TCLOO_PATCHLEVEL TCLOO_VERSION ".1"
#include "tcl.h"
+700 -68
View File
@@ -19,10 +19,12 @@
static inline Tcl_Object *AddConstructionFinalizer(Tcl_Interp *interp);
static Tcl_NRPostProc AfterNRDestructor;
static Tcl_NRPostProc DecrRefsPostClassConstructor;
static Tcl_NRPostProc PostClassConstructor;
static Tcl_NRPostProc FinalizeConstruction;
static Tcl_NRPostProc FinalizeEval;
static Tcl_NRPostProc NextRestoreFrame;
static Tcl_NRPostProc MarkAsSingleton;
static Tcl_NRPostProc UpdateClassDelegatesAfterClone;
/*
* ----------------------------------------------------------------------
@@ -65,6 +67,119 @@ FinalizeConstruction(
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* MixinClassDelegates --
*
* Internal utility for setting up the class delegate.
* Runs after the class has called [oo::define] on its argument.
*
* ----------------------------------------------------------------------
*/
// Look up the delegate for a class.
static inline Class *
GetClassDelegate(
Tcl_Interp *interp,
Class *clsPtr)
{
Tcl_Obj *delegateName = Tcl_ObjPrintf("%s:: oo ::delegate",
clsPtr->thisPtr->namespacePtr->fullName);
Class *delegatePtr = TclOOGetClassFromObj(interp, delegateName);
Tcl_DecrRefCount(delegateName);
return delegatePtr;
}
/*
* Patches in the appropriate class delegates' superclasses.
* Sonewhat messy because the list of superclasses isn't modified frequently.
*/
static inline void
SetDelegateSuperclasses(
Tcl_Interp *interp,
Class *clsPtr,
Class *delegatePtr)
{
// Build new list of superclasses
int i, j = delegatePtr->superclasses.num, k;
Class *superPtr, **supers = (Class **) Tcl_Alloc(sizeof(Class *) *
(delegatePtr->superclasses.num + clsPtr->superclasses.num));
if (delegatePtr->superclasses.num) {
memcpy(supers, delegatePtr->superclasses.list,
sizeof(Class *) * delegatePtr->superclasses.num);
}
FOREACH(superPtr, clsPtr->superclasses) {
Class *superDelegatePtr = GetClassDelegate(interp, superPtr);
if (!superDelegatePtr) {
continue;
}
for (k=0 ; k<=j ; k++) {
if (k == j) {
supers[j++] = superDelegatePtr;
TclOOAddToSubclasses(delegatePtr, superDelegatePtr);
AddRef(superDelegatePtr->thisPtr);
break;
} else if (supers[k] == superDelegatePtr) {
break;
}
}
}
// Install new list of superclasses;
if (delegatePtr->superclasses.num) {
Tcl_Free(delegatePtr->superclasses.list);
}
delegatePtr->superclasses.list = supers;
delegatePtr->superclasses.num = j;
// Definitely don't need to bump any epoch here
}
/*
* Mixes the delegate into its controlling class.
*/
static inline void
InstallDelegateAsMixin(
Tcl_Interp *interp,
Class *clsPtr,
Class *delegatePtr)
{
if (clsPtr->thisPtr->mixins.num == 0) {
TclOOObjectSetMixins(clsPtr->thisPtr, 1, &delegatePtr);
return;
}
Class **mixins = (Class **) TclStackAlloc(interp,
sizeof(Class *) * (clsPtr->thisPtr->mixins.num + 1));
for (int i = 0; i < clsPtr->thisPtr->mixins.num; i++) {
mixins[i] = clsPtr->thisPtr->mixins.list[i];
if (mixins[i] == delegatePtr) {
TclStackFree(interp, (void *) mixins);
return;
}
}
mixins[clsPtr->thisPtr->mixins.num] = delegatePtr;
TclOOObjectSetMixins(clsPtr->thisPtr, clsPtr->thisPtr->mixins.num + 1, mixins);
TclStackFree(interp, mixins);
}
// Patches in the appropriate class delegates.
static void
MixinClassDelegates(
Tcl_Interp *interp,
Object *oPtr,
Tcl_Obj *delegateName)
{
Class *clsPtr = oPtr->classPtr;
if (clsPtr) {
Class *delegatePtr = TclOOGetClassFromObj(interp, delegateName);
if (delegatePtr) {
SetDelegateSuperclasses(interp, clsPtr, delegatePtr);
InstallDelegateAsMixin(interp, clsPtr, delegatePtr);
}
}
}
/*
* ----------------------------------------------------------------------
*
@@ -84,7 +199,6 @@ TclOO_Class_Constructor(
Tcl_Obj *const *objv)
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
Tcl_Obj **invoke, *nameObj;
size_t skip = Tcl_ObjectContextSkippedArgs(context);
if ((size_t) objc > skip + 1) {
@@ -101,25 +215,28 @@ TclOO_Class_Constructor(
* argument to [oo::define]. [Bug 680503]
*/
nameObj = Tcl_ObjPrintf("%s:: oo ::delegate",
Tcl_Obj *delegateName = Tcl_ObjPrintf("%s:: oo ::delegate",
oPtr->namespacePtr->fullName);
Tcl_IncrRefCount(delegateName);
Tcl_NewObjectInstance(interp, (Tcl_Class) oPtr->fPtr->classCls,
TclGetString(nameObj), NULL, TCL_INDEX_NONE, NULL, 0);
Tcl_BounceRefCount(nameObj);
TclGetString(delegateName), NULL, TCL_INDEX_NONE, NULL, 0);
/*
* If there's nothing else to do, we're done.
*/
if ((size_t) objc == skip) {
return TCL_OK;
Tcl_InterpState saved = Tcl_SaveInterpState(interp, TCL_OK);
MixinClassDelegates(interp, oPtr, delegateName);
Tcl_DecrRefCount(delegateName);
return Tcl_RestoreInterpState(interp, saved);
}
/*
* Delegate to [oo::define] to do the work.
*/
invoke = (Tcl_Obj **) TclStackAlloc(interp, 3 * sizeof(Tcl_Obj *));
Tcl_Obj **invoke = (Tcl_Obj **) TclStackAlloc(interp, 3 * sizeof(Tcl_Obj *));
invoke[0] = oPtr->fPtr->defineName;
invoke[1] = TclOOObjectName(interp, oPtr);
invoke[2] = objv[objc - 1];
@@ -132,8 +249,8 @@ TclOO_Class_Constructor(
Tcl_IncrRefCount(invoke[0]);
Tcl_IncrRefCount(invoke[1]);
Tcl_IncrRefCount(invoke[2]);
TclNRAddCallback(interp, DecrRefsPostClassConstructor,
invoke, oPtr, NULL, NULL);
TclNRAddCallback(interp, PostClassConstructor,
invoke, oPtr, delegateName, NULL);
/*
* Tricky point: do not want the extra reported level in the Tcl stack
@@ -143,33 +260,28 @@ TclOO_Class_Constructor(
return TclNREvalObjv(interp, 3, invoke, TCL_EVAL_NOERR, NULL);
}
/*
* Called *after* [oo::define] inside the constructor of a class.
* Cleans up some temporary storage and sets up the delegate.
*/
static int
DecrRefsPostClassConstructor(
PostClassConstructor(
void *data[],
Tcl_Interp *interp,
int result)
{
Tcl_Obj **invoke = (Tcl_Obj **) data[0];
Object *oPtr = (Object *) data[1];
Tcl_InterpState saved;
int code;
Tcl_Obj *delegateName = (Tcl_Obj *) data[2];
TclDecrRefCount(invoke[0]);
TclDecrRefCount(invoke[1]);
TclDecrRefCount(invoke[2]);
invoke[0] = oPtr->fPtr->mcdName;
invoke[1] = TclOOObjectName(interp, oPtr);
Tcl_IncrRefCount(invoke[0]);
Tcl_IncrRefCount(invoke[1]);
saved = Tcl_SaveInterpState(interp, result);
code = Tcl_EvalObjv(interp, 2, invoke, 0);
TclDecrRefCount(invoke[0]);
TclDecrRefCount(invoke[1]);
TclStackFree(interp, invoke);
if (code != TCL_OK) {
Tcl_DiscardInterpState(saved);
return code;
}
Tcl_InterpState saved = Tcl_SaveInterpState(interp, result);
MixinClassDelegates(interp, oPtr, delegateName);
Tcl_DecrRefCount(delegateName);
return Tcl_RestoreInterpState(interp, saved);
}
@@ -355,6 +467,176 @@ TclOO_Class_New(
AddConstructionFinalizer(interp));
}
/*
* ----------------------------------------------------------------------
*
* TclOO_Class_Cloned --
*
* Handler for cloning classes, which fixes up the delegates. This allows
* the clone's class methods to evolve independently of the origin's
* class methods; this is how TclOO works by default.
*
* ----------------------------------------------------------------------
*/
int
TclOO_Class_Cloned(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Interpreter in which to create the object;
* also used for error reporting. */
Tcl_ObjectContext context, /* The object/call context. */
int objc, /* Number of arguments. */
Tcl_Obj *const *objv) /* The actual arguments. */
{
Tcl_Object targetObject = Tcl_ObjectContextObject(context);
Tcl_Size skip = Tcl_ObjectContextSkippedArgs(context);
if (skip >= objc) {
Tcl_WrongNumArgs(interp, skip, objv, "originObject");
return TCL_ERROR;
}
Tcl_Object originObject = Tcl_GetObjectFromObj(interp, objv[skip]);
if (!originObject) {
return TCL_ERROR;
}
// Add references so things won't vanish until after
// UpdateClassDelegatesAfterClone is finished with them.
AddRef((Object *) originObject);
AddRef((Object *) targetObject);
TclNRAddCallback(interp, UpdateClassDelegatesAfterClone,
originObject, targetObject, NULL, NULL);
return TclNRObjectContextInvokeNext(interp, context, objc, objv, skip);
}
// Rebuilds the class inheritance delegation class.
static int
UpdateClassDelegatesAfterClone(
void *data[],
Tcl_Interp *interp,
int result)
{
Object *originPtr = (Object *) data[0];
Object *targetPtr = (Object *) data[1];
if (result == TCL_OK && originPtr->classPtr && targetPtr->classPtr) {
// Get the originating delegate to be cloned.
Tcl_Obj *originName = Tcl_ObjPrintf("%s:: oo ::delegate",
originPtr->namespacePtr->fullName);
Object *originDelegate = (Object *) Tcl_GetObjectFromObj(interp,
originName);
Tcl_BounceRefCount(originName);
// Delegates never have their own delegates, so silently make sure we
// don't try to make a clone of them.
if (!(originDelegate && originDelegate->classPtr)) {
goto noOriginDelegate;
}
// Create the cloned target delegate.
Tcl_Obj *targetName = Tcl_ObjPrintf("%s:: oo ::delegate",
targetPtr->namespacePtr->fullName);
Object *targetDelegate = (Object *) Tcl_CopyObjectInstance(interp,
(Tcl_Object) originDelegate, Tcl_GetString(targetName), NULL);
Tcl_BounceRefCount(targetName);
if (targetDelegate == NULL) {
result = TCL_ERROR;
goto noOriginDelegate;
}
// Point the cloned target class at the cloned target delegate.
// This is like TclOOObjectSetMixins() but more efficient in this
// case as there's definitely no relevant call chains to invalidate
// and we're doing a one-for-one replacement.
Tcl_Size i;
Class *mixin;
FOREACH(mixin, targetPtr->mixins) {
if (mixin == originDelegate->classPtr) {
TclOORemoveFromInstances(targetPtr, originDelegate->classPtr);
TclOODecrRefCount(originDelegate);
targetPtr->mixins.list[i] = targetDelegate->classPtr;
TclOOAddToInstances(targetPtr, targetDelegate->classPtr);
AddRef(targetDelegate);
break;
}
}
}
noOriginDelegate:
TclOODecrRefCount(originPtr);
TclOODecrRefCount(targetPtr);
return result;
};
/*
* ----------------------------------------------------------------------
*
* TclOO_Configurable_Constructor --
*
* Implementation for oo::configurable constructor.
*
* ----------------------------------------------------------------------
*/
int
TclOO_Configurable_Constructor(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_ObjectContext context,
int objc,
Tcl_Obj *const *objv)
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
Tcl_Size skip = Tcl_ObjectContextSkippedArgs(context);
if (objc != skip && objc != skip + 1) {
Tcl_WrongNumArgs(interp, skip, objv, "?definitionScript?");
return TCL_ERROR;
}
Tcl_Obj *cfgSupportName = Tcl_NewStringObj(
"::oo::configuresupport::configurable", TCL_AUTO_LENGTH);
Class *mixin = TclOOGetClassFromObj(interp, cfgSupportName);
Tcl_BounceRefCount(cfgSupportName);
if (!mixin) {
return TCL_ERROR;
}
TclOOClassSetMixins(interp, oPtr->classPtr, 1, &mixin);
return TclNRObjectContextInvokeNext(interp, context, objc, objv, skip);
}
/*
* ----------------------------------------------------------------------
*
* TclOO_Object_Cloned --
*
* Handler for cloning objects that clones basic bits (only!) of the
* object's namespace. Non-procedures, traces, sub-namespaces, etc. need
* more complex (and class-specific) handling.
*
* ----------------------------------------------------------------------
*/
int
TclOO_Object_Cloned(
TCL_UNUSED(void *),
Tcl_Interp *interp, // Interpreter for error reporting.
Tcl_ObjectContext context, // The object/call context.
int objc, // Number of arguments.
Tcl_Obj *const *objv) // The actual arguments.
{
int skip = Tcl_ObjectContextSkippedArgs(context);
if (objc != skip + 1) {
Tcl_WrongNumArgs(interp, skip, objv, "originObject");
return TCL_ERROR;
}
Object *targetObject = (Object *) Tcl_ObjectContextObject(context);
Object *originObject = (Object *) Tcl_GetObjectFromObj(interp, objv[skip]);
if (!originObject) {
return TCL_ERROR;
}
Namespace *originNs = (Namespace *) originObject->namespacePtr;
Namespace *targetNs = (Namespace *) targetObject->namespacePtr;
if (TclCopyNamespaceProcedures(interp, originNs, targetNs) != TCL_OK) {
return TCL_ERROR;
}
return TclCopyNamespaceVariables(interp, originNs, targetNs);
}
/*
* ----------------------------------------------------------------------
*
@@ -401,6 +683,9 @@ TclOO_Object_Destroy(
return TCL_OK;
}
/* Post-NRE-callback for TclOO_Object_Destroy. Deletes the object command if
* it's still there, which triggers destruction of the namespace and attached
* structures. */
static int
AfterNRDestructor(
void *data[],
@@ -488,6 +773,7 @@ TclOO_Object_Eval(
return TclNREvalObjEx(interp, scriptPtr, 0, invoker, skip);
}
/* Post-NRE-callback for TclOO_Object_Eval. Cleans up. */
static int
FinalizeEval(
void *data[],
@@ -901,6 +1187,98 @@ TclOO_Object_VarName(
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOOLinkObjCmd --
*
* Implementation of the [link] command, that makes a command that
* invokes a method on the current object. The name of the command and
* the name of the method match by default. Note that this command is
* only ever to be used inside the body of a procedure-like method,
* and is typically intended for constructors.
*
* ----------------------------------------------------------------------
*/
int
TclOOLinkObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
// Set up common bits.
CallFrame *framePtr = ((Interp *) interp)->varFramePtr;
if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"%s may only be called from inside a method",
TclGetString(objv[0])));
OO_ERROR(interp, CONTEXT_REQUIRED);
return TCL_ERROR;
}
CallContext *context = (CallContext *) framePtr->clientData;
Object *oPtr = context->oPtr;
if (!oPtr->myCommand) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"cannot link to non-existent callback handle"));
OO_ERROR(interp, MY_GONE);
return TCL_ERROR;
}
Tcl_Obj *myCmd = Tcl_NewObj();
Tcl_GetCommandFullName(interp, oPtr->myCommand, myCmd);
if (!oPtr->linkedCmdsList) {
oPtr->linkedCmdsList = Tcl_NewListObj(0, NULL);
Tcl_IncrRefCount(oPtr->linkedCmdsList);
}
// For each argument
for (int i=1; i<objc; i++) {
Tcl_Size linkc;
Tcl_Obj **linkv, *src, *dst;
// Parse as list of (one or) two items: source and destination names
if (TclListObjGetElements(interp, objv[i], &linkc, &linkv) != TCL_OK) {
Tcl_BounceRefCount(myCmd);
return TCL_ERROR;
}
switch (linkc) {
case 1:
// Degenerate case
src = dst = linkv[0];
break;
case 2:
src = linkv[0];
dst = linkv[1];
break;
default:
Tcl_BounceRefCount(myCmd);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad link description; must only have one or two elements"));
OO_ERROR(interp, CMDLINK_FORMAT);
return TCL_ERROR;
}
// Qualify the source if necessary
const char *srcStr = TclGetString(src);
if (srcStr[0] != ':' || srcStr[1] != ':') {
src = Tcl_ObjPrintf("%s::%s",
context->oPtr->namespacePtr->fullName, srcStr);
}
// Make the alias command
if (TclAliasCreate(interp, interp, interp, src, myCmd, 1, &dst) != TCL_OK) {
Tcl_BounceRefCount(myCmd);
Tcl_BounceRefCount(src);
return TCL_ERROR;
}
// Remember the alias for cleanup if necessary
Tcl_ListObjAppendElement(NULL, oPtr->linkedCmdsList, src);
}
Tcl_BounceRefCount(myCmd);
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
@@ -958,11 +1336,6 @@ TclOONextToObjCmd(
{
Interp *iPtr = (Interp *) interp;
CallFrame *framePtr = iPtr->varFramePtr;
Class *classPtr;
CallContext *contextPtr;
Tcl_Size i;
Tcl_Object object;
const char *methodType;
/*
* Start with sanity checks on the calling context to make sure that we
@@ -977,7 +1350,7 @@ TclOONextToObjCmd(
OO_ERROR(interp, CONTEXT_REQUIRED);
return TCL_ERROR;
}
contextPtr = (CallContext *) framePtr->clientData;
CallContext *contextPtr = (CallContext *) framePtr->clientData;
/*
* Sanity check the arguments; we need the first one to refer to a class.
@@ -987,15 +1360,8 @@ TclOONextToObjCmd(
Tcl_WrongNumArgs(interp, 1, objv, "class ?arg...?");
return TCL_ERROR;
}
object = Tcl_GetObjectFromObj(interp, objv[1]);
if (object == NULL) {
return TCL_ERROR;
}
classPtr = ((Object *) object)->classPtr;
Class *classPtr = TclOOGetClassFromObj(interp, objv[1]);
if (classPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" is not a class", TclGetString(objv[1])));
OO_ERROR(interp, CLASS_REQUIRED);
return TCL_ERROR;
}
@@ -1005,6 +1371,7 @@ TclOONextToObjCmd(
* allow jumping backwards!
*/
Tcl_Size i;
for (i=contextPtr->index+1 ; i<contextPtr->callPtr->numChain ; i++) {
MInvoke *miPtr = &contextPtr->callPtr->chain[i];
@@ -1028,14 +1395,7 @@ TclOONextToObjCmd(
* is on the chain but unreachable, or not on the chain at all.
*/
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
methodType = "constructor";
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
methodType = "destructor";
} else {
methodType = "method";
}
const char *methodType = TclOOContextTypeName(contextPtr);
for (i=contextPtr->index ; i != TCL_INDEX_NONE ; i--) {
MInvoke *miPtr = &contextPtr->callPtr->chain[i];
@@ -1054,6 +1414,7 @@ TclOONextToObjCmd(
return TCL_ERROR;
}
/* Post-NRE-callback for [next] and [nextto]. */
static int
NextRestoreFrame(
void *data[],
@@ -1207,13 +1568,7 @@ TclOOSelfObjCmd(
} else if (mPtr->declaringObjectPtr != NULL) {
declarerPtr = mPtr->declaringObjectPtr;
} else {
/*
* This should be unreachable code.
*/
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"method without declarer!", TCL_AUTO_LENGTH));
return TCL_ERROR;
TCL_UNREACHABLE();
}
result[0] = TclOOObjectName(interp, declarerPtr);
@@ -1239,13 +1594,7 @@ TclOOSelfObjCmd(
} else if (mPtr->declaringObjectPtr != NULL) {
declarerPtr = mPtr->declaringObjectPtr;
} else {
/*
* This should be unreachable code.
*/
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"method without declarer!", TCL_AUTO_LENGTH));
return TCL_ERROR;
TCL_UNREACHABLE();
}
result[0] = TclOOObjectName(interp, declarerPtr);
@@ -1284,13 +1633,7 @@ TclOOSelfObjCmd(
} else if (mPtr->declaringObjectPtr != NULL) {
declarerPtr = mPtr->declaringObjectPtr;
} else {
/*
* This should be unreachable code.
*/
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"method without declarer!", TCL_AUTO_LENGTH));
return TCL_ERROR;
TCL_UNREACHABLE();
}
result[0] = TclOOObjectName(interp, declarerPtr);
result[1] = mPtr->namePtr;
@@ -1302,8 +1645,9 @@ TclOOSelfObjCmd(
TclNewIndexObj(result[1], contextPtr->index);
Tcl_SetObjResult(interp, Tcl_NewListObj(2, result));
return TCL_OK;
default:
TCL_UNREACHABLE();
}
return TCL_ERROR;
}
/*
@@ -1389,6 +1733,294 @@ TclOOCopyObjectCmd(
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOOCallbackObjCmd --
*
* Implementation of the [callback] command, which constructs callbacks
* into the current object.
*
* ----------------------------------------------------------------------
*/
int
TclOOCallbackObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
Interp *iPtr = (Interp *) interp;
CallFrame *framePtr = iPtr->varFramePtr;
/*
* Start with sanity checks on the calling context to make sure that we
* are invoked from a suitable method context. If so, we can safely
* retrieve the handle to the object call context.
*/
if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"%s may only be called from inside a method",
TclGetString(objv[0])));
OO_ERROR(interp, CONTEXT_REQUIRED);
return TCL_ERROR;
}
CallContext *contextPtr = (CallContext *) framePtr->clientData;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "method ...");
return TCL_ERROR;
}
// Get the [my] real name.
Tcl_Obj *namePtr = TclOOObjectMyName(interp, contextPtr->oPtr);
if (!namePtr) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"no possible safe callback without my", TCL_AUTO_LENGTH));
OO_ERROR(interp, NO_MY);
return TCL_ERROR;
}
// No check that the method exists; could be dynamically added.
Tcl_Obj *listPtr = Tcl_NewListObj(1, &namePtr);
(void) TclListObjAppendElements(NULL, listPtr, objc-1, objv+1);
Tcl_SetObjResult(interp, listPtr);
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOOClassVariableObjCmd --
*
* Implementation of the [classvariable] command, which links to
* variables in the class of the current object.
*
* ----------------------------------------------------------------------
*/
int
TclOOClassVariableObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
Interp *iPtr = (Interp *) interp;
CallFrame *framePtr = iPtr->varFramePtr;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "name ...");
return TCL_ERROR;
}
/*
* Start with sanity checks on the calling context to make sure that we
* are invoked from a suitable method context. If so, we can safely
* retrieve the handle to the object call context.
*/
if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"%s may only be called from inside a method",
TclGetString(objv[0])));
OO_ERROR(interp, CONTEXT_REQUIRED);
return TCL_ERROR;
}
// Get a reference to the class's namespace
CallContext *contextPtr = (CallContext *) framePtr->clientData;
Class *clsPtr = CurrentlyInvoked(contextPtr).mPtr->declaringClassPtr;
if (clsPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"method not defined by a class", TCL_AUTO_LENGTH));
OO_ERROR(interp, UNMATCHED_CONTEXT);
return TCL_ERROR;
}
Tcl_Namespace *clsNsPtr = clsPtr->thisPtr->namespacePtr;
// Check the list of variable names
for (int i = 1; i < objc; i++) {
const char *varName = TclGetString(objv[i]);
if (Tcl_StringMatch(varName, "*(*)")) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad variable name \"%s\": can't create a %s",
varName, "scalar variable that looks like an array element"));
Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL);
return TCL_ERROR;
}
if (Tcl_StringMatch(varName, "*::*")) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad variable name \"%s\": can't create a %s",
varName, "local variable with a namespace separator in it"));
Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL);
return TCL_ERROR;
}
}
// Lastly, link the caller's local variables to the class's variables
Tcl_Namespace *ourNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
for (int i = 1; i < objc; i++) {
// Locate the other variable.
iPtr->varFramePtr->nsPtr = (Namespace *) clsNsPtr;
Var *arrayPtr, *otherPtr = TclObjLookupVarEx(interp, objv[i], NULL,
(TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG|TCL_AVOID_RESOLVERS),
"access", /*createPart1*/ 1, /*createPart2*/ 0, &arrayPtr);
iPtr->varFramePtr->nsPtr = (Namespace *) ourNsPtr;
if (otherPtr == NULL) {
return TCL_ERROR;
}
// Create the new variable and link it to otherPtr.
if (TclPtrObjMakeUpvarIdx(interp, otherPtr, objv[i], 0,
TCL_INDEX_NONE) != TCL_OK) {
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOODelegateNameObjCmd --
*
* Implementation of the [oo::DelegateName] command, which is a utility
* that gets the name of the class delegate for a class. It's trivial,
* but makes working with them much easier as delegate names are
* intentionally hard to create by accident.
*
* Not part of TclOO public API. No public documentation.
*
* ----------------------------------------------------------------------
*/
int
TclOODelegateNameObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "class");
return TCL_ERROR;
}
Class *clsPtr = TclOOGetClassFromObj(interp, objv[1]);
if (clsPtr == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s:: oo ::delegate",
clsPtr->thisPtr->namespacePtr->fullName));
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOO_Singleton_New, MarkAsSingleton --
*
* Implementation for oo::singleton->new method.
*
* ----------------------------------------------------------------------
*/
int
TclOO_Singleton_New(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Interpreter in which to create the object;
* also used for error reporting. */
Tcl_ObjectContext context, /* The object/call context. */
int objc, /* Number of arguments. */
Tcl_Obj *const *objv) /* The actual arguments. */
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
Class *clsPtr = oPtr->classPtr;
if (clsPtr->instances.num) {
Tcl_SetObjResult(interp, TclOOObjectName(interp, clsPtr->instances.list[0]));
return TCL_OK;
}
TclNRAddCallback(interp, MarkAsSingleton, clsPtr, NULL, NULL, NULL);
return TclNRNewObjectInstance(interp, (Tcl_Class) clsPtr,
NULL, NULL, objc, objv, Tcl_ObjectContextSkippedArgs(context),
AddConstructionFinalizer(interp));
}
/* Once the singleton object is made, this mixes in a class to disable easy
* deleting of the instance. */
static int
MarkAsSingleton(
void *data[],
Tcl_Interp *interp,
int result)
{
Class *clsPtr = (Class *) data[0];
if (result == TCL_OK && clsPtr->instances.num) {
// Prepend oo::SingletonInstance to the list of mixins
Tcl_Obj *singletonInstanceName = Tcl_NewStringObj(
"::oo::SingletonInstance", TCL_AUTO_LENGTH);
Class *singInst = TclOOGetClassFromObj(interp, singletonInstanceName);
Tcl_BounceRefCount(singletonInstanceName);
if (!singInst) {
return TCL_ERROR;
}
Object *oPtr = clsPtr->instances.list[0];
Tcl_Size mixinc = oPtr->mixins.num;
Class **mixins = (Class **)TclStackAlloc(interp,
sizeof(Class *) * (mixinc + 1));
if (mixinc > 0) {
memcpy(mixins + 1, oPtr->mixins.list, mixinc * sizeof(Class *));
}
mixins[0] = singInst;
TclOOObjectSetMixins(oPtr, mixinc + 1, mixins);
TclStackFree(interp, mixins);
}
return result;
}
/*
* ----------------------------------------------------------------------
*
* TclOO_SingletonInstance_Destroy, TclOO_SingletonInstance_Cloned --
*
* Implementation for oo::SingletonInstance->destroy method and its
* cloning callback method.
*
* ----------------------------------------------------------------------
*/
int
TclOO_SingletonInstance_Destroy(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Interpreter for error reporting. */
TCL_UNUSED(Tcl_ObjectContext),
TCL_UNUSED(int),
TCL_UNUSED(Tcl_Obj *const *))
{
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"may not destroy a singleton object"));
OO_ERROR(interp, SINGLETON);
return TCL_ERROR;
}
int
TclOO_SingletonInstance_Cloned(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Interpreter in which to create the object;
* also used for error reporting. */
TCL_UNUSED(Tcl_ObjectContext),
TCL_UNUSED(int),
TCL_UNUSED(Tcl_Obj *const *))
{
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"may not clone a singleton object"));
OO_ERROR(interp, SINGLETON);
return TCL_ERROR;
}
/*
* Local Variables:
* mode: c
+29 -7
View File
@@ -427,6 +427,29 @@ FinalizeMethodRefs(
return result;
}
/*
* ----------------------------------------------------------------------
*
* TclOOContextTypeName --
*
* Get the name of the (high-level) type of method that a context is
* processing. Used for error message generation.
*
* ----------------------------------------------------------------------
*/
const char *
TclOOContextTypeName(
CallContext *contextPtr)
{
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
return "constructor";
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
return "destructor";
} else {
return "method";
}
}
/*
* ----------------------------------------------------------------------
*
@@ -776,9 +799,7 @@ AddPrivateMethodNames(
FOREACH_HASH(namePtr, mPtr, methodsTablePtr) {
if (IS_PRIVATE(mPtr)) {
int isNew;
hPtr = Tcl_CreateHashEntry(namesPtr, namePtr, &isNew);
hPtr = Tcl_CreateHashEntry(namesPtr, namePtr, NULL);
Tcl_SetHashValue(hPtr, INT2PTR(IN_LIST));
}
}
@@ -1554,14 +1575,13 @@ TclOOGetStereotypeCallChain(
}
} else {
if (hPtr == NULL) {
int isNew;
if (clsPtr->classChainCache == NULL) {
clsPtr->classChainCache = (Tcl_HashTable *)
Tcl_Alloc(sizeof(Tcl_HashTable));
Tcl_InitObjHashTable(clsPtr->classChainCache);
}
hPtr = Tcl_CreateHashEntry(clsPtr->classChainCache,
methodNameObj, &isNew);
methodNameObj, NULL);
}
callPtr->refCount++;
Tcl_SetHashValue(hPtr, callPtr);
@@ -1647,6 +1667,7 @@ AddClassFiltersToCallContext(
AddClassFiltersToCallContext(oPtr, superPtr, cbPtr, doneFilters,
flags);
}
TCL_FALLTHROUGH();
case 0:
return;
}
@@ -1734,7 +1755,7 @@ AddPrivatesFromClassChainToCallContext(
return 1;
}
}
/* FALLTHRU */
TCL_FALLTHROUGH();
case 0:
return 0;
}
@@ -1829,7 +1850,7 @@ AddSimpleClassChainToCallContext(
privateDanger |= AddSimpleClassChainToCallContext(superPtr,
methodNameObj, cbPtr, doneFilters, flags, filterDecl);
}
/* FALLTHRU */
TCL_FALLTHROUGH();
case 0:
return privateDanger;
}
@@ -2067,6 +2088,7 @@ AddSimpleClassDefineNamespaces(
FOREACH(superPtr, classPtr->superclasses) {
AddSimpleClassDefineNamespaces(superPtr, definePtr, flags);
}
TCL_FALLTHROUGH();
case 0:
return;
}
+932 -129
View File
File diff suppressed because it is too large Load Diff
+40 -55
View File
@@ -51,7 +51,7 @@ static Tcl_ObjCmdProc InfoClassVariablesCmd;
static const EnsembleImplMap infoObjectCmds[] = {
{"call", InfoObjectCallCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
{"class", InfoObjectClassCmd, TclCompileInfoObjectClassCmd, NULL, NULL, 0},
{"creationid", InfoObjectIdCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"creationid", InfoObjectIdCmd, TclCompileInfoObjectCreationIdCmd, NULL, NULL, 0},
{"definition", InfoObjectDefnCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
{"filters", InfoObjectFiltersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"forward", InfoObjectForwardCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
@@ -88,22 +88,39 @@ static const EnsembleImplMap infoClassCmds[] = {
{"variables", InfoClassVariablesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
{NULL, NULL, NULL, NULL, NULL, 0}
};
/*
* ----------------------------------------------------------------------
*
* LocalVarName --
* DescribeMethodArgs --
*
* Get the name of a local variable (especially a method argument) as a
* Tcl value.
* Generate the descriptor for the arguments to a method (including a
* constructor, usually).
*
* ----------------------------------------------------------------------
*/
static inline Tcl_Obj *
LocalVarName(
CompiledLocal *localPtr)
DescribeMethodArgs(
Proc *procPtr)
{
return Tcl_NewStringObj(localPtr->name, TCL_AUTO_LENGTH);
Tcl_Obj *argObjList;
CompiledLocal *localPtr;
TclNewObj(argObjList);
for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
localPtr=localPtr->nextPtr) {
if (TclIsVarArgument(localPtr)) {
Tcl_Obj *argObj;
TclNewObj(argObj);
Tcl_ListObjAppendElement(NULL, argObj, Tcl_NewStringObj(
localPtr->name, localPtr->nameLength));
if (localPtr->defValuePtr != NULL) {
Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
}
Tcl_ListObjAppendElement(NULL, argObjList, argObj);
}
}
return argObjList;
}
/*
@@ -252,7 +269,6 @@ InfoObjectDefnCmd(
Object *oPtr;
Tcl_HashEntry *hPtr;
Proc *procPtr;
CompiledLocal *localPtr;
Tcl_Obj *resultObjs[2];
if (objc != 3) {
@@ -281,20 +297,7 @@ InfoObjectDefnCmd(
* We now have the method to describe the definition of.
*/
TclNewObj(resultObjs[0]);
for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
localPtr=localPtr->nextPtr) {
if (TclIsVarArgument(localPtr)) {
Tcl_Obj *argObj;
TclNewObj(argObj);
Tcl_ListObjAppendElement(NULL, argObj, LocalVarName(localPtr));
if (localPtr->defValuePtr != NULL) {
Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
}
Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj);
}
}
resultObjs[0] = DescribeMethodArgs(procPtr);
resultObjs[1] = TclOOGetMethodBody((Method *) Tcl_GetHashValue(hPtr));
Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObjs));
return TCL_OK;
@@ -485,6 +488,8 @@ InfoObjectIsACmd(
return TCL_ERROR;
}
break;
default:
TCL_UNREACHABLE();
}
/*
@@ -538,6 +543,8 @@ InfoObjectIsACmd(
result = TclOOIsReachable(o2Ptr->classPtr, oPtr->selfCls);
}
break;
default:
TCL_UNREACHABLE();
}
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
return TCL_OK;
@@ -628,6 +635,8 @@ InfoObjectMethodsCmd(
return TCL_ERROR;
}
break;
default:
TCL_UNREACHABLE();
}
}
}
@@ -995,7 +1004,6 @@ InfoClassConstrCmd(
Tcl_Obj *const objv[])
{
Proc *procPtr;
CompiledLocal *localPtr;
Tcl_Obj *resultObjs[2];
Class *clsPtr;
@@ -1019,20 +1027,7 @@ InfoClassConstrCmd(
return TCL_ERROR;
}
TclNewObj(resultObjs[0]);
for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
localPtr=localPtr->nextPtr) {
if (TclIsVarArgument(localPtr)) {
Tcl_Obj *argObj;
TclNewObj(argObj);
Tcl_ListObjAppendElement(NULL, argObj, LocalVarName(localPtr));
if (localPtr->defValuePtr != NULL) {
Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
}
Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj);
}
}
resultObjs[0] = DescribeMethodArgs(procPtr);
resultObjs[1] = TclOOGetMethodBody(clsPtr->constructorPtr);
Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObjs));
return TCL_OK;
@@ -1057,7 +1052,6 @@ InfoClassDefnCmd(
{
Tcl_HashEntry *hPtr;
Proc *procPtr;
CompiledLocal *localPtr;
Tcl_Obj *resultObjs[2];
Class *clsPtr;
@@ -1087,20 +1081,7 @@ InfoClassDefnCmd(
return TCL_ERROR;
}
TclNewObj(resultObjs[0]);
for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
localPtr=localPtr->nextPtr) {
if (TclIsVarArgument(localPtr)) {
Tcl_Obj *argObj;
TclNewObj(argObj);
Tcl_ListObjAppendElement(NULL, argObj, LocalVarName(localPtr));
if (localPtr->defValuePtr != NULL) {
Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
}
Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj);
}
}
resultObjs[0] = DescribeMethodArgs(procPtr);
resultObjs[1] = TclOOGetMethodBody((Method *) Tcl_GetHashValue(hPtr));
Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObjs));
return TCL_OK;
@@ -1145,9 +1126,9 @@ InfoClassDefnNsCmd(
return TCL_ERROR;
}
if (kind) {
if (kind) { // -instance
nsNamePtr = clsPtr->objDefinitionNs;
} else {
} else { // -class
nsNamePtr = clsPtr->clsDefinitionNs;
}
if (nsNamePtr) {
@@ -1412,6 +1393,8 @@ InfoClassMethodsCmd(
return TCL_ERROR;
}
break;
default:
TCL_UNREACHABLE();
}
}
}
@@ -1427,6 +1410,8 @@ InfoClassMethodsCmd(
case SCOPE_UNEXPORTED:
flag = 0;
break;
default:
TCL_UNREACHABLE();
}
}
+24 -3
View File
@@ -255,6 +255,7 @@ struct Object {
PropertyStorage properties; /* Information relating to the lists of
* properties that this object *claims* to
* support. */
Tcl_Obj *linkedCmdsList; /* List of names of linked commands. */
};
enum ObjectFlags {
@@ -405,8 +406,10 @@ struct Foundation {
* "<cloned>" pseudo-constructor. */
Tcl_Obj *defineName; /* Fully qualified name of oo::define. */
Tcl_Obj *myName; /* The "my" shared object. */
Tcl_Obj *mcdName; /* The shared object for calling the helper to
* mix in class delegates. */
Tcl_Obj *slotGetName; /* The "Get" name used by slots. */
Tcl_Obj *slotSetName; /* The "Set" name used by slots. */
Tcl_Obj *slotResolveName; /* The "Resolve" name used by slots. */
Tcl_Obj *slotDefOpName; /* The "--default-operation" name used by slots. */
};
/*
@@ -498,12 +501,14 @@ struct DeclaredClassMethod {
MODULE_SCOPE int TclOOInit(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOOObjDefObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineClassMethodObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineConstructorObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDefnNsObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDeleteMethodObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDestructorObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineExportObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineForwardObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineInitialiseObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineMethodObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineRenameMethodObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefineUnexportObjCmd;
@@ -513,7 +518,11 @@ MODULE_SCOPE Tcl_ObjCmdProc TclOODefineObjSelfObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefinePrivateObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODefinePropertyCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOOUnknownDefinition;
MODULE_SCOPE Tcl_ObjCmdProc TclOOCallbackObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOOClassVariableObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOOCopyObjectCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOODelegateNameObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOOLinkObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOONextObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOONextToObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclOOSelfObjCmd;
@@ -524,16 +533,22 @@ MODULE_SCOPE Tcl_ObjCmdProc TclOOInfoClassPropCmd;
* Method implementations (in tclOOBasic.c).
*/
MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Cloned;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Constructor;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Create;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_CreateNs;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_New;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Cloned;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Destroy;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Eval;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_LinkVar;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Unknown;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_VarName;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Configurable_Configure;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Configurable_Constructor;
MODULE_SCOPE Tcl_MethodCallProc TclOO_Singleton_New;
MODULE_SCOPE Tcl_MethodCallProc TclOO_SingletonInstance_Cloned;
MODULE_SCOPE Tcl_MethodCallProc TclOO_SingletonInstance_Destroy;
/*
* Private definitions, some of which perhaps ought to be exposed properly or
@@ -567,6 +582,7 @@ MODULE_SCOPE Object * TclNewObjectInstanceCommon(Tcl_Interp *interp,
const char *nsNameStr);
MODULE_SCOPE int TclOODecrRefCount(Object *oPtr);
MODULE_SCOPE int TclOOObjectDestroyed(Object *oPtr);
MODULE_SCOPE const char *TclOOContextTypeName(CallContext *contextPtr);
MODULE_SCOPE int TclOODefineSlots(Foundation *fPtr);
MODULE_SCOPE void TclOODeleteChain(CallChain *callPtr);
MODULE_SCOPE void TclOODeleteChainCache(Tcl_HashTable *tablePtr);
@@ -574,6 +590,7 @@ MODULE_SCOPE void TclOODeleteContext(CallContext *contextPtr);
MODULE_SCOPE void TclOODeleteDescendants(Tcl_Interp *interp,
Object *oPtr);
MODULE_SCOPE void TclOODelMethodRef(Method *method);
MODULE_SCOPE int TclOOExportMethods(Class *clsPtr, ...);
MODULE_SCOPE CallContext *TclOOGetCallContext(Object *oPtr,
Tcl_Obj *methodNameObj, int flags,
Object *contextObjPtr, Class *contextClsPtr,
@@ -608,6 +625,7 @@ MODULE_SCOPE int TclNRObjectContextInvokeNext(Tcl_Interp *interp,
MODULE_SCOPE void TclOODefineBasicMethods(Class *clsPtr,
const DeclaredClassMethod *dcm);
MODULE_SCOPE Tcl_Obj * TclOOObjectName(Tcl_Interp *interp, Object *oPtr);
MODULE_SCOPE Tcl_Obj * TclOOObjectMyName(Tcl_Interp *interp, Object *oPtr);
MODULE_SCOPE void TclOOReleaseClassContents(Tcl_Interp *interp,
Object *oPtr);
MODULE_SCOPE int TclOORemoveFromInstances(Object *oPtr, Class *clsPtr);
@@ -618,11 +636,14 @@ MODULE_SCOPE int TclOORemoveFromSubclasses(Class *subPtr,
Class *superPtr);
MODULE_SCOPE Tcl_Obj * TclOORenderCallChain(Tcl_Interp *interp,
CallChain *callPtr);
MODULE_SCOPE void TclOOSetSuperclasses(Class *clsPtr, Tcl_Size superc,
Class **superclasses);
MODULE_SCOPE void TclOOStashContext(Tcl_Obj *objPtr,
CallContext *contextPtr);
MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
MODULE_SCOPE int TclOOUnexportMethods(Class *clsPtr, ...);
MODULE_SCOPE Tcl_Obj * TclOOGetAllObjectProperties(Object *oPtr,
int writable);
MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
MODULE_SCOPE Tcl_Obj * TclOOGetPropertyList(PropertyList *propList);
MODULE_SCOPE void TclOOReleasePropertyStorage(PropertyStorage *propsPtr);
MODULE_SCOPE void TclOOInstallReadableProperties(PropertyStorage *props,
+22 -14
View File
@@ -99,7 +99,16 @@ static const Tcl_MethodType fwdMethodType = {
((Tcl_HashTable *) (&((Namespace *) (contextNs))->varTable))
#define TclVarHashGetValue(hPtr) \
((Tcl_Var) ((char *)hPtr - offsetof(VarInHash, entry)))
/*
* ----------------------------------------------------------------------
*
* AllocProcedureMethodRecord --
*
* Allocate and initialise the record for procedure-like methods.
*
* ----------------------------------------------------------------------
*/
static inline ProcedureMethod *
AllocProcedureMethodRecord(
int flags)
@@ -555,7 +564,6 @@ InitCmdFrame(
if (context.line && context.nline > 1
&& (context.line[context.nline - 1] >= 0)) {
int isNew;
CmdFrame *cfPtr = (CmdFrame *) Tcl_Alloc(sizeof(CmdFrame));
Tcl_HashEntry *hPtr;
@@ -574,7 +582,7 @@ InitCmdFrame(
cfPtr->len = 0;
hPtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr,
procPtr, &isNew);
procPtr, NULL);
Tcl_SetHashValue(hPtr, cfPtr);
}
@@ -586,7 +594,8 @@ InitCmdFrame(
Tcl_DecrRefCount(context.data.eval.path);
context.data.eval.path = NULL;
}
}}
}
}
/*
* ----------------------------------------------------------------------
@@ -774,14 +783,14 @@ TclOOMakeProcMethod2(
InitCmdFrame(iPtr, procPtr);
return TclNewMethod(
(Tcl_Class) clsPtr, nameObj, flags, (const Tcl_MethodType *)typePtr, clientData);
return TclNewMethod((Tcl_Class) clsPtr, nameObj, flags,
(const Tcl_MethodType *)typePtr, clientData);
}
/*
* ----------------------------------------------------------------------
*
* InvokeProcedureMethod, PushMethodCallFrame --
* InvokeProcedureMethod, FinalizePMCall, PushMethodCallFrame --
*
* How to invoke a procedure-like method.
*
@@ -790,7 +799,7 @@ TclOOMakeProcMethod2(
static int
InvokeProcedureMethod(
void *clientData, /* Pointer to some per-method context. */
void *clientData, /* Pointer to the per-method record. */
Tcl_Interp *interp,
Tcl_ObjectContext context, /* The method calling context. */
int objc, /* Number of arguments. */
@@ -894,9 +903,9 @@ InvokeProcedureMethod(
static int
FinalizePMCall(
void *data[],
Tcl_Interp *interp,
int result)
void *data[], /* Data from InvokeProcedureMethod. */
Tcl_Interp *interp, /* Current interpreter. */
int result) /* Result of the body of the method. */
{
ProcedureMethod *pmPtr = (ProcedureMethod *) data[0];
Tcl_ObjectContext context = (Tcl_ObjectContext) data[1];
@@ -1548,7 +1557,7 @@ TclOONewForwardMethod(
/*
* ----------------------------------------------------------------------
*
* InvokeForwardMethod --
* InvokeForwardMethod, FinalizeForwardCall --
*
* How to invoke a forwarded method. Works by doing some ensemble-like
* command rearranging and then invokes some other Tcl command.
@@ -1580,7 +1589,7 @@ InvokeForwardMethod(
TclListObjGetElements(NULL, fmPtr->prefixObj, &numPrefixes, &prefixObjs);
argObjs = InitEnsembleRewrite(interp, objc, objv, skip,
numPrefixes, prefixObjs, &len);
Tcl_NRAddCallback(interp, FinalizeForwardCall, argObjs, NULL, NULL, NULL);
TclNRAddCallback(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
@@ -1708,7 +1717,6 @@ TclOOGetFwdFromMethod(
*
* ----------------------------------------------------------------------
*/
static Tcl_Obj **
InitEnsembleRewrite(
Tcl_Interp *interp, /* Place to log the rewrite info. */
+14 -8
View File
@@ -211,10 +211,10 @@ GetPropertyName(
* We use a recursive call to look this up.
*/
Tcl_InterpState foo = Tcl_SaveInterpState(interp, result);
Tcl_InterpState state = Tcl_SaveInterpState(interp, result);
Tcl_Obj *otherName = GetPropertyName(interp, oPtr,
flags ^ (GPN_WRITABLE | GPN_FALLING_BACK), namePtr, NULL);
result = Tcl_RestoreInterpState(interp, foo);
result = Tcl_RestoreInterpState(interp, state);
if (otherName != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"property \"%s\" is %s only",
@@ -542,18 +542,18 @@ FindClassProps(
* property set. */
Tcl_HashTable *accumulator) /* Where to gather the names. */
{
int i, dummy;
int i;
Tcl_Obj *propName;
Class *mixin, *sup;
tailRecurse:
if (writable) {
FOREACH(propName, clsPtr->properties.writable) {
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
Tcl_CreateHashEntry(accumulator, (void *) propName, NULL);
}
} else {
FOREACH(propName, clsPtr->properties.readable) {
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
Tcl_CreateHashEntry(accumulator, (void *) propName, NULL);
}
}
if (clsPtr->thisPtr->flags & ROOT_OBJECT) {
@@ -593,17 +593,17 @@ FindObjectProps(
* property set. */
Tcl_HashTable *accumulator) /* Where to gather the names. */
{
int i, dummy;
int i;
Tcl_Obj *propName;
Class *mixin;
if (writable) {
FOREACH(propName, oPtr->properties.writable) {
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
Tcl_CreateHashEntry(accumulator, (void *) propName, NULL);
}
} else {
FOREACH(propName, oPtr->properties.readable) {
Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
Tcl_CreateHashEntry(accumulator, (void *) propName, NULL);
}
}
FOREACH(mixin, oPtr->mixins) {
@@ -1099,6 +1099,8 @@ TclOODefinePropertyCmd(
return TCL_ERROR;
}
break;
default:
TCL_UNREACHABLE();
}
}
@@ -1221,6 +1223,8 @@ TclOOInfoClassPropCmd(
case PROP_WRITABLE:
writable = 1;
break;
default:
TCL_UNREACHABLE();
}
}
@@ -1279,6 +1283,8 @@ TclOOInfoObjectPropCmd(
case PROP_WRITABLE:
writable = 1;
break;
default:
TCL_UNREACHABLE();
}
}
-297
View File
@@ -1,297 +0,0 @@
/*
* tclOOScript.h --
*
* This file contains support scripts for TclOO. They are defined here so
* that the code can be definitely run even in safe interpreters; TclOO's
* core setup is safe.
*
* Copyright (c) 2012-2018 Donal K. Fellows
* Copyright (c) 2013 Andreas Kupries
* Copyright (c) 2017 Gerald Lester
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef TCL_OO_SCRIPT_H
#define TCL_OO_SCRIPT_H
/*
* The scripted part of the definitions of TclOO.
*
* Compiled from tools/tclOOScript.tcl by tools/makeHeader.tcl, which
* contains the commented version of everything; *this* file is automatically
* generated.
*/
static const char *tclOOSetupScript =
/* !BEGIN!: Do not edit below this line. */
"::namespace eval ::oo {\n"
"\t::namespace path {}\n"
"\tnamespace eval Helpers {\n"
"\t\tnamespace path {}\n"
"\t\tproc callback {method args} {\n"
"\t\t\tlist [uplevel 1 {::namespace which my}] $method {*}$args\n"
"\t\t}\n"
"\t\tnamespace export callback\n"
"\t\tnamespace eval tmp {namespace import ::oo::Helpers::callback}\n"
"\t\tnamespace export -clear\n"
"\t\trename tmp::callback mymethod\n"
"\t\tnamespace delete tmp\n"
"\t\tproc classvariable {name args} {\n"
"\t\t\tset ns [info object namespace [uplevel 1 {self class}]]\n"
"\t\t\tforeach v [list $name {*}$args] {\n"
"\t\t\t\tif {[string match *(*) $v]} {\n"
"\t\t\t\t\tset reason \"can\'t create a scalar variable that looks like an array element\"\n"
"\t\t\t\t\treturn -code error -errorcode {TCL UPVAR LOCAL_ELEMENT} \\\n"
"\t\t\t\t\t\t[format {bad variable name \"%s\": %s} $v $reason]\n"
"\t\t\t\t}\n"
"\t\t\t\tif {[string match *::* $v]} {\n"
"\t\t\t\t\tset reason \"can\'t create a local variable with a namespace separator in it\"\n"
"\t\t\t\t\treturn -code error -errorcode {TCL UPVAR INVERTED} \\\n"
"\t\t\t\t\t\t[format {bad variable name \"%s\": %s} $v $reason]\n"
"\t\t\t\t}\n"
"\t\t\t\tlappend vs $v $v\n"
"\t\t\t}\n"
"\t\t\ttailcall namespace upvar $ns {*}$vs\n"
"\t\t}\n"
"\t\tproc link {args} {\n"
"\t\t\tset ns [uplevel 1 {::namespace current}]\n"
"\t\t\tforeach link $args {\n"
"\t\t\t\tif {[llength $link] == 2} {\n"
"\t\t\t\t\tlassign $link src dst\n"
"\t\t\t\t} elseif {[llength $link] == 1} {\n"
"\t\t\t\t\tlassign $link src\n"
"\t\t\t\t\tset dst $src\n"
"\t\t\t\t} else {\n"
"\t\t\t\t\treturn -code error -errorcode {TCL OO CMDLINK_FORMAT} \\\n"
"\t\t\t\t\t\t\"bad link description; must only have one or two elements\"\n"
"\t\t\t\t}\n"
"\t\t\t\tif {![string match ::* $src]} {\n"
"\t\t\t\t\tset src [string cat $ns :: $src]\n"
"\t\t\t\t}\n"
"\t\t\t\tinterp alias {} $src {} ${ns}::my $dst\n"
"\t\t\t\ttrace add command ${ns}::my delete [list \\\n"
"\t\t\t\t\t::oo::UnlinkLinkedCommand $src]\n"
"\t\t\t}\n"
"\t\t\treturn\n"
"\t\t}\n"
"\t}\n"
"\tproc UnlinkLinkedCommand {cmd args} {\n"
"\t\tif {[namespace which $cmd] ne {}} {\n"
"\t\t\trename $cmd {}\n"
"\t\t}\n"
"\t}\n"
"\tproc DelegateName {class} {\n"
"\t\tstring cat [info object namespace $class] {:: oo ::delegate}\n"
"\t}\n"
"\tproc MixinClassDelegates {class} {\n"
"\t\tif {![info object isa class $class]} {\n"
"\t\t\treturn\n"
"\t\t}\n"
"\t\tset delegate [DelegateName $class]\n"
"\t\tif {![info object isa class $delegate]} {\n"
"\t\t\treturn\n"
"\t\t}\n"
"\t\tforeach c [info class superclass $class] {\n"
"\t\t\tset d [DelegateName $c]\n"
"\t\t\tif {![info object isa class $d]} {\n"
"\t\t\t\tcontinue\n"
"\t\t\t}\n"
"\t\t\tdefine $delegate ::oo::define::superclass -appendifnew $d\n"
"\t\t}\n"
"\t\tobjdefine $class ::oo::objdefine::mixin -appendifnew $delegate\n"
"\t}\n"
"\tproc UpdateClassDelegatesAfterClone {originObject targetObject} {\n"
"\t\tset originDelegate [DelegateName $originObject]\n"
"\t\tset targetDelegate [DelegateName $targetObject]\n"
"\t\tif {\n"
"\t\t\t[info object isa class $originDelegate]\n"
"\t\t\t&& ![info object isa class $targetDelegate]\n"
"\t\t} then {\n"
"\t\t\tcopy $originDelegate $targetDelegate\n"
"\t\t\tobjdefine $targetObject ::oo::objdefine::mixin -set \\\n"
"\t\t\t\t{*}[lmap c [info object mixin $targetObject] {\n"
"\t\t\t\t\tif {$c eq $originDelegate} {set targetDelegate} {set c}\n"
"\t\t\t\t}]\n"
"\t\t}\n"
"\t}\n"
"\tproc define::classmethod {name args} {\n"
"\t\t::set argc [::llength [::info level 0]]\n"
"\t\t::if {$argc == 3} {\n"
"\t\t\t::return -code error -errorcode {TCL WRONGARGS} [::format \\\n"
"\t\t\t\t{wrong # args: should be \"%s name \?args body\?\"} \\\n"
"\t\t\t\t[::lindex [::info level 0] 0]]\n"
"\t\t}\n"
"\t\t::set cls [::uplevel 1 self]\n"
"\t\t::if {$argc == 4} {\n"
"\t\t\t::oo::define [::oo::DelegateName $cls] method $name {*}$args\n"
"\t\t}\n"
"\t\t::tailcall forward $name myclass $name\n"
"\t}\n"
"\tproc define::initialise {body} {\n"
"\t\t::set clsns [::info object namespace [::uplevel 1 self]]\n"
"\t\t::tailcall apply [::list {} $body $clsns]\n"
"\t}\n"
"\tnamespace eval define {\n"
"\t\t::namespace export initialise\n"
"\t\t::namespace eval tmp {::namespace import ::oo::define::initialise}\n"
"\t\t::namespace export -clear\n"
"\t\t::rename tmp::initialise initialize\n"
"\t\t::namespace delete tmp\n"
"\t}\n"
"\tdefine Slot {\n"
"\t\tmethod Get -unexport {} {\n"
"\t\t\treturn -code error -errorcode {TCL OO ABSTRACT_SLOT} \"unimplemented\"\n"
"\t\t}\n"
"\t\tmethod Set -unexport list {\n"
"\t\t\treturn -code error -errorcode {TCL OO ABSTRACT_SLOT} \"unimplemented\"\n"
"\t\t}\n"
"\t\tmethod Resolve -unexport list {\n"
"\t\t\treturn $list\n"
"\t\t}\n"
"\t\tmethod -set -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\ttailcall my Set $args\n"
"\t\t}\n"
"\t\tmethod -append -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\ttailcall my Set [list {*}$current {*}$args]\n"
"\t\t}\n"
"\t\tmethod -appendifnew -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\tforeach a $args {\n"
"\t\t\t\tset a [uplevel 1 [list $my Resolve $a]]\n"
"\t\t\t\tif {$a ni $current} {\n"
"\t\t\t\t\tlappend current $a\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t\ttailcall my Set $current\n"
"\t\t}\n"
"\t\tmethod -clear -export {} {tailcall my Set {}}\n"
"\t\tmethod -prepend -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\ttailcall my Set [list {*}$args {*}$current]\n"
"\t\t}\n"
"\t\tmethod -remove -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\ttailcall my Set [lmap val $current {\n"
"\t\t\t\tif {$val in $args} continue else {set val}\n"
"\t\t\t}]\n"
"\t\t}\n"
"\t\tforward --default-operation my -append\n"
"\t\tmethod unknown -unexport {args} {\n"
"\t\t\tset def --default-operation\n"
"\t\t\tif {[llength $args] == 0} {\n"
"\t\t\t\ttailcall my $def\n"
"\t\t\t} elseif {![string match -* [lindex $args 0]]} {\n"
"\t\t\t\ttailcall my $def {*}$args\n"
"\t\t\t}\n"
"\t\t\tnext {*}$args\n"
"\t\t}\n"
"\t\tunexport destroy\n"
"\t}\n"
"\tobjdefine define::superclass forward --default-operation my -set\n"
"\tobjdefine define::mixin forward --default-operation my -set\n"
"\tobjdefine objdefine::mixin forward --default-operation my -set\n"
"\tdefine object method <cloned> -unexport {originObject} {\n"
"\t\tforeach p [info procs [info object namespace $originObject]::*] {\n"
"\t\t\tset args [info args $p]\n"
"\t\t\tset idx -1\n"
"\t\t\tforeach a $args {\n"
"\t\t\t\tif {[info default $p $a d]} {\n"
"\t\t\t\t\tlset args [incr idx] [list $a $d]\n"
"\t\t\t\t} else {\n"
"\t\t\t\t\tlset args [incr idx] [list $a]\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t\tset b [info body $p]\n"
"\t\t\tset p [namespace tail $p]\n"
"\t\t\tproc $p $args $b\n"
"\t\t}\n"
"\t\tforeach v [info vars [info object namespace $originObject]::*] {\n"
"\t\t\tupvar 0 $v vOrigin\n"
"\t\t\tnamespace upvar [namespace current] [namespace tail $v] vNew\n"
"\t\t\tif {[info exists vOrigin]} {\n"
"\t\t\t\tif {[array exists vOrigin]} {\n"
"\t\t\t\t\tarray set vNew [array get vOrigin]\n"
"\t\t\t\t} else {\n"
"\t\t\t\t\tset vNew $vOrigin\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t}\n"
"\t}\n"
"\tdefine class method <cloned> -unexport {originObject} {\n"
"\t\tnext $originObject\n"
"\t\t::oo::UpdateClassDelegatesAfterClone $originObject [self]\n"
"\t}\n"
"\tclass create singleton {\n"
"\t\tsuperclass class\n"
"\t\tvariable object\n"
"\t\tunexport create createWithNamespace\n"
"\t\tmethod new args {\n"
"\t\t\tif {![info exists object] || ![info object isa object $object]} {\n"
"\t\t\t\tset object [next {*}$args]\n"
"\t\t\t\t::oo::objdefine $object {\n"
"\t\t\t\t\tmethod destroy {} {\n"
"\t\t\t\t\t\t::return -code error -errorcode {TCL OO SINGLETON} \\\n"
"\t\t\t\t\t\t\t\"may not destroy a singleton object\"\n"
"\t\t\t\t\t}\n"
"\t\t\t\t\tmethod <cloned> -unexport {originObject} {\n"
"\t\t\t\t\t\t::return -code error -errorcode {TCL OO SINGLETON} \\\n"
"\t\t\t\t\t\t\t\"may not clone a singleton object\"\n"
"\t\t\t\t\t}\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t\treturn $object\n"
"\t\t}\n"
"\t}\n"
"\tclass create abstract {\n"
"\t\tsuperclass class\n"
"\t\tunexport create createWithNamespace new\n"
"\t}\n"
"\tnamespace eval configuresupport {\n"
"\t\t::namespace eval configurableclass {\n"
"\t\t\t::proc properties args {::tailcall property {*}$args}\n"
"\t\t\t::namespace path ::oo::define\n"
"\t\t\t::namespace export property\n"
"\t\t}\n"
"\t\t::namespace eval configurableobject {\n"
"\t\t\t::proc properties args {::tailcall property {*}$args}\n"
"\t\t\t::namespace path ::oo::objdefine\n"
"\t\t\t::namespace export property\n"
"\t\t}\n"
"\t\t::oo::define configurable {\n"
"\t\t\tdefinitionnamespace -instance configurableobject\n"
"\t\t\tdefinitionnamespace -class configurableclass\n"
"\t\t}\n"
"\t}\n"
"\tclass create configurable {\n"
"\t\tsuperclass class\n"
"\t\tconstructor {{definitionScript \"\"}} {\n"
"\t\t\tnext {mixin ::oo::configuresupport::configurable}\n"
"\t\t\tnext $definitionScript\n"
"\t\t}\n"
"\t\tdefinitionnamespace -class configuresupport::configurableclass\n"
"\t}\n"
"}\n"
/* !END!: Do not edit above this line. */
;
#endif /* TCL_OO_SCRIPT_H */
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
+159 -93
View File
@@ -145,13 +145,13 @@ typedef struct PendingObjData {
#define ObjDeletionUnlock(contextPtr) ((contextPtr)->deletionCount--)
#define ObjDeletePending(contextPtr) ((contextPtr)->deletionCount > 0)
#define ObjOnStack(contextPtr) ((contextPtr)->deletionStack != NULL)
#define PushObjToDelete(contextPtr,objPtr) \
#define PushObjToDelete(contextPtr, objPtr) \
/* The string rep is already invalidated so we can use the bytes value \
* for our pointer chain: push onto the head of the stack. */ \
(objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \
* for our pointer chain: push onto the head of the stack. */ \
(objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \
(contextPtr)->deletionStack = (objPtr)
#define PopObjToDelete(contextPtr,objPtrVar) \
(objPtrVar) = (contextPtr)->deletionStack; \
#define PopObjToDelete(contextPtr, objPtrVar) \
(objPtrVar) = (contextPtr)->deletionStack; \
(contextPtr)->deletionStack = (Tcl_Obj *) (objPtrVar)->bytes
/*
@@ -168,8 +168,8 @@ static __thread PendingObjData pendingObjData;
#else
static Tcl_ThreadDataKey pendingObjDataKey;
#define ObjInitDeletionContext(contextPtr) \
PendingObjData *const contextPtr = \
(PendingObjData *)Tcl_GetThreadData(&pendingObjDataKey, sizeof(PendingObjData))
PendingObjData *const contextPtr = (PendingObjData *) \
Tcl_GetThreadData(&pendingObjDataKey, sizeof(PendingObjData))
#endif
/*
@@ -177,15 +177,15 @@ static Tcl_ThreadDataKey pendingObjDataKey;
*/
#define PACK_BIGNUM(bignum, objPtr) \
if ((bignum).used > 0x7FFF) { \
mp_int *temp = (mp_int *)Tcl_Alloc(sizeof(mp_int)); \
*temp = bignum; \
(objPtr)->internalRep.twoPtrValue.ptr1 = temp; \
(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1); \
if ((bignum).used > 0x7FFF) { \
mp_int *temp = (mp_int *)Tcl_Alloc(sizeof(mp_int)); \
*temp = bignum; \
(objPtr)->internalRep.twoPtrValue.ptr1 = temp; \
(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1); \
} else if (((bignum).alloc <= 0x7FFF) || (mp_shrink(&(bignum))) == MP_OKAY) { \
(objPtr)->internalRep.twoPtrValue.ptr1 = (bignum).dp; \
(objPtr)->internalRep.twoPtrValue.ptr1 = (bignum).dp; \
(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(((bignum).sign << 30) \
| ((bignum).alloc << 15) | ((bignum).used)); \
| ((bignum).alloc << 15) | ((bignum).used)); \
}
/*
@@ -548,7 +548,8 @@ TclContinuationsEnter(
ThreadSpecificData *tsdPtr = TclGetContLineTable();
Tcl_HashEntry *hPtr =
Tcl_CreateHashEntry(tsdPtr->lineCLPtr, objPtr, &newEntry);
ContLineLoc *clLocPtr = (ContLineLoc *)Tcl_Alloc(offsetof(ContLineLoc, loc) + (num + 1U) *sizeof(Tcl_Size));
ContLineLoc *clLocPtr = (ContLineLoc *)
Tcl_Alloc(offsetof(ContLineLoc, loc) + (num + 1U) *sizeof(Tcl_Size));
if (!newEntry) {
/*
@@ -810,11 +811,9 @@ Tcl_RegisterObjType(
* be statically allocated (must live
* forever). */
{
int isNew;
Tcl_MutexLock(&tableMutex);
Tcl_SetHashValue(
Tcl_CreateHashEntry(&typeTable, typePtr->name, &isNew), typePtr);
Tcl_CreateHashEntry(&typeTable, typePtr->name, NULL), typePtr);
Tcl_MutexUnlock(&tableMutex);
}
@@ -1556,6 +1555,25 @@ TclObjBeingDeleted(
} \
}
#define AttemptSetDuplicateObj(dupPtr, objPtr) \
{ \
const Tcl_ObjType *typePtr = (objPtr)->typePtr; \
const char *bytes = (objPtr)->bytes; \
if (bytes) { \
(void)TclAttemptInitStringRep((dupPtr), bytes, (objPtr)->length); \
} else { \
(dupPtr)->bytes = NULL; \
} \
if (typePtr) { \
if (typePtr->dupIntRepProc) { \
typePtr->dupIntRepProc((objPtr), (dupPtr)); \
} else { \
(dupPtr)->internalRep = (objPtr)->internalRep; \
(dupPtr)->typePtr = typePtr; \
} \
} \
}
Tcl_Obj *
Tcl_DuplicateObj(
Tcl_Obj *objPtr) /* The object to duplicate. */
@@ -1567,6 +1585,21 @@ Tcl_DuplicateObj(
return dupPtr;
}
Tcl_Obj *
Tcl_AttemptDuplicateObj(
Tcl_Obj *objPtr) /* The object to duplicate. */
{
Tcl_Obj *dupPtr;
TclNewObj(dupPtr);
AttemptSetDuplicateObj(dupPtr, objPtr);
if (!dupPtr->bytes) {
Tcl_DecrRefCount(dupPtr);
dupPtr = NULL;
}
return dupPtr;
}
void
TclSetDuplicateObj(
Tcl_Obj *dupPtr,
@@ -1580,61 +1613,6 @@ TclSetDuplicateObj(
SetDuplicateObj(dupPtr, objPtr);
}
/*
*----------------------------------------------------------------------
*
* Tcl_GetString --
*
* Returns the string representation byte array pointer for an object.
*
* Results:
* Returns a pointer to the string representation of objPtr. The byte
* array referenced by the returned pointer must not be modified by the
* caller. Furthermore, the caller must copy the bytes if they need to
* retain them since the object's string rep can change as a result of
* other operations.
*
* Side effects:
* May call the object's updateStringProc to update the string
* representation from the internal representation.
*
*----------------------------------------------------------------------
*/
#undef Tcl_GetString
char *
Tcl_GetString(
Tcl_Obj *objPtr) /* Object whose string rep byte pointer should
* be returned. */
{
if (objPtr->bytes == NULL) {
/*
* Note we do not check for objPtr->typePtr == NULL. An invariant
* of a properly maintained Tcl_Obj is that at least one of
* objPtr->bytes and objPtr->typePtr must not be NULL. If broken
* extensions fail to maintain that invariant, we can crash here.
*/
if (objPtr->typePtr->updateStringProc == NULL) {
/*
* Those Tcl_ObjTypes which choose not to define an
* updateStringProc must be written in such a way that
* (objPtr->bytes) never becomes NULL.
*/
Tcl_Panic("UpdateStringProc should not be invoked for type %s",
objPtr->typePtr->name);
}
objPtr->typePtr->updateStringProc(objPtr);
if (objPtr->bytes == NULL || objPtr->length == TCL_INDEX_NONE
|| objPtr->bytes[objPtr->length] != '\0') {
Tcl_Panic("UpdateStringProc for type '%s' "
"failed to create a valid string rep",
objPtr->typePtr->name);
}
}
return objPtr->bytes;
}
/*
*----------------------------------------------------------------------
*
@@ -1658,7 +1636,7 @@ Tcl_GetString(
*----------------------------------------------------------------------
*/
#if !defined(TCL_NO_DEPRECATED)
#ifndef TCL_NO_DEPRECATED
#undef TclGetStringFromObj
char *
TclGetStringFromObj(
@@ -1702,7 +1680,7 @@ TclGetStringFromObj(
}
return objPtr->bytes;
}
#endif /* !defined(TCL_NO_DEPRECATED) */
#endif /* !TCL_NO_DEPRECATED */
#undef Tcl_GetStringFromObj
char *
@@ -1731,10 +1709,11 @@ Tcl_GetStringFromObj(
objPtr->typePtr->name);
}
objPtr->typePtr->updateStringProc(objPtr);
if (objPtr->bytes == NULL
|| objPtr->bytes[objPtr->length] != '\0') {
Tcl_Panic("UpdateStringProc for type '%s' "
"failed to create a valid string rep",
if (objPtr->bytes == NULL) {
Tcl_Panic("cannot allocate %" TCL_SIZE_MODIFIER "d bytes for type '%s' ",
objPtr->length + 1, objPtr->typePtr->name);
} else if (objPtr->bytes[objPtr->length] != '\0') {
Tcl_Panic("cannot create a valid string rep for type '%s'",
objPtr->typePtr->name);
}
}
@@ -1743,6 +1722,86 @@ Tcl_GetStringFromObj(
}
return objPtr->bytes;
}
char *
Tcl_DbGetStringFromObj(
Tcl_Obj *objPtr, /* Object whose string rep byte pointer should
* be returned. */
Tcl_Size *lengthPtr, /* If non-NULL, the location where the string
* rep's byte array length should * be stored.
* If NULL, no length is stored. */
const char *file,
int line)
{
if (objPtr->bytes == NULL) {
/*
* Note we do not check for objPtr->typePtr == NULL. An invariant
* of a properly maintained Tcl_Obj is that at least one of
* objPtr->bytes and objPtr->typePtr must not be NULL. If broken
* extensions fail to maintain that invariant, we can crash here.
*/
if (objPtr->typePtr->updateStringProc == NULL) {
/*
* Those Tcl_ObjTypes which choose not to define an
* updateStringProc must be written in such a way that
* (objPtr->bytes) never becomes NULL.
*/
Tcl_Panic("cannot invoke UpdateStringProc for type %s. %s:%d",
objPtr->typePtr->name, file, line);
}
objPtr->typePtr->updateStringProc(objPtr);
if (objPtr->bytes == NULL) {
Tcl_Panic("cannot allocate %" TCL_SIZE_MODIFIER "d bytes for type '%s'. %s:%d",
objPtr->length + 1, objPtr->typePtr->name, file, line);
} else if (objPtr->bytes[objPtr->length] != '\0') {
Tcl_Panic("cannot create a valid string rep for type '%s'. %s:%d",
objPtr->typePtr->name, file, line);
}
}
if (lengthPtr != NULL) {
*lengthPtr = objPtr->length;
}
return objPtr->bytes;
}
char *
Tcl_AttemptGetStringFromObj(
Tcl_Obj *objPtr, /* Object whose string rep byte pointer should
* be returned. */
Tcl_Size *lengthPtr) /* If non-NULL, the location where the string
* rep's byte array length should * be stored.
* If NULL, no length is stored. */
{
if (objPtr->bytes == NULL) {
/*
* Note we do not check for objPtr->typePtr == NULL. An invariant
* of a properly maintained Tcl_Obj is that at least one of
* objPtr->bytes and objPtr->typePtr must not be NULL. If broken
* extensions fail to maintain that invariant, we can crash here.
*/
if (objPtr->typePtr->updateStringProc == NULL) {
/*
* Those Tcl_ObjTypes which choose not to define an
* updateStringProc must be written in such a way that
* (objPtr->bytes) never becomes NULL.
*/
Tcl_Panic("cannot invoke UpdateStringProc for type %s",
objPtr->typePtr->name);
}
objPtr->typePtr->updateStringProc(objPtr);
if (objPtr->bytes != NULL
&& objPtr->bytes[objPtr->length] != '\0') {
Tcl_Panic("cannot create a valid string rep for type '%s'",
objPtr->typePtr->name);
}
}
if (lengthPtr != NULL) {
*lengthPtr = objPtr->bytes ? objPtr->length : -1;
}
return objPtr->bytes;
}
/*
*----------------------------------------------------------------------
@@ -2015,13 +2074,15 @@ Tcl_GetBoolFromObj(
if (interp) {
TclNewObj(objPtr);
TclParseNumber(interp, objPtr, (flags & TCL_NULL_OK)
? "boolean value or \"\"" : "boolean value", NULL, TCL_INDEX_NONE, NULL, 0);
? "boolean value or \"\"" : "boolean value", NULL,
TCL_INDEX_NONE, NULL, 0);
Tcl_DecrRefCount(objPtr);
}
return TCL_ERROR;
}
do {
if (TclHasInternalRep(objPtr, &tclIntType) || TclHasInternalRep(objPtr, &tclBooleanType)) {
if (TclHasInternalRep(objPtr, &tclIntType)
|| TclHasInternalRep(objPtr, &tclBooleanType)) {
result = (objPtr->internalRep.wideValue != 0);
goto boolEnd;
}
@@ -2068,7 +2129,8 @@ Tcl_GetBoolFromObj(
if (length > 0) {
listRep:
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf("expected boolean value%s but got a list",
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected boolean value%s but got a list",
(flags & TCL_NULL_OK) ? " or \"\"" : ""));
}
return TCL_ERROR;
@@ -2091,7 +2153,8 @@ Tcl_GetBooleanFromObj(
Tcl_Obj *objPtr, /* The object from which to get boolean. */
int *intPtr) /* Place to store resulting boolean. */
{
return Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof(int), (char *)(void *)intPtr);
return Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof(int),
(char *)(void *)intPtr);
}
/*
@@ -2470,8 +2533,9 @@ Tcl_GetDoubleFromObj(
if (length > 0) {
listRep:
if (interp) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("expected floating-point number but got a list", TCL_INDEX_NONE));
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"expected floating-point number but got a list",
TCL_INDEX_NONE));
}
return TCL_ERROR;
}
@@ -4186,11 +4250,13 @@ AllocObjEntry(
void *keyPtr) /* Key to store in the hash table entry. */
{
Tcl_Obj *objPtr = (Tcl_Obj *)keyPtr;
Tcl_HashEntry *hPtr = (Tcl_HashEntry *)Tcl_Alloc(sizeof(Tcl_HashEntry));
Tcl_HashEntry *hPtr = (Tcl_HashEntry *)Tcl_AttemptAlloc(sizeof(Tcl_HashEntry));
hPtr->key.objPtr = objPtr;
Tcl_IncrRefCount(objPtr);
hPtr->clientData = NULL;
if (hPtr) {
hPtr->key.objPtr = objPtr;
Tcl_IncrRefCount(objPtr);
hPtr->clientData = NULL;
}
return hPtr;
}
@@ -4226,10 +4292,10 @@ TclCompareObjKeys(
* If the object pointers are the same then they match.
* OPT: this comparison was moved to the caller
if (objPtr1 == objPtr2) {
return 1;
}
*/
if (objPtr1 == objPtr2) {
return 1;
}
*/
/*
* Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
+108 -20
View File
@@ -10,6 +10,7 @@
*/
#include "tclInt.h"
#define ALLOW_DEPRECATED_OPCODES
#include "tclCompile.h"
#include <assert.h>
@@ -79,38 +80,48 @@ LocateTargetAddresses(
currentInstPtr < envPtr->codeNext ;
currentInstPtr += AddrLength(currentInstPtr)) {
switch (*currentInstPtr) {
#ifndef REMOVE_DEPRECATED_OPCODES
case INST_JUMP1:
case INST_JUMP_TRUE1:
case INST_JUMP_FALSE1:
targetInstPtr = currentInstPtr+TclGetInt1AtPtr(currentInstPtr+1);
goto storeTarget;
case INST_JUMP4:
case INST_JUMP_TRUE4:
case INST_JUMP_FALSE4:
#endif
case INST_JUMP:
case INST_JUMP_TRUE:
case INST_JUMP_FALSE:
case INST_START_CMD:
targetInstPtr = currentInstPtr+TclGetInt4AtPtr(currentInstPtr+1);
goto storeTarget;
case INST_BEGIN_CATCH4:
case INST_BEGIN_CATCH:
targetInstPtr = envPtr->codeStart + envPtr->exceptArrayPtr[
TclGetUInt4AtPtr(currentInstPtr+1)].codeOffset;
storeTarget:
DefineTargetAddress(tablePtr, targetInstPtr);
break;
case INST_JUMP_TABLE_NUM:
hPtr = Tcl_FirstHashEntry(
&JUMPTABLENUMINFO(envPtr, currentInstPtr+1)->hashTable,
&hSearch);
goto storeJumpTableTargets;
case INST_JUMP_TABLE:
hPtr = Tcl_FirstHashEntry(
&JUMPTABLEINFO(envPtr, currentInstPtr+1)->hashTable,
&hSearch);
storeJumpTableTargets:
for (; hPtr ; hPtr = Tcl_NextHashEntry(&hSearch)) {
targetInstPtr = currentInstPtr +
PTR2INT(Tcl_GetHashValue(hPtr));
DefineTargetAddress(tablePtr, targetInstPtr);
}
break;
#ifndef REMOVE_DEPRECATED_OPCODES
case INST_RETURN_CODE_BRANCH:
for (i=TCL_ERROR ; i<TCL_CONTINUE+1 ; i++) {
DefineTargetAddress(tablePtr, currentInstPtr + 2*i - 1);
}
break;
#endif
}
}
@@ -240,7 +251,7 @@ ConvertZeroEffectToNOP(
}
}
break;
case INST_PUSH4:
case INST_PUSH:
if (nextInst == INST_POP) {
blank = size + 1;
} else if (nextInst == INST_STR_CONCAT1
@@ -258,6 +269,7 @@ ConvertZeroEffectToNOP(
case INST_LNOT:
switch (nextInst) {
#ifndef REMOVE_DEPRECATED_OPCODES
case INST_JUMP_TRUE1:
blank = size;
currentInstPtr[size] = INST_JUMP_FALSE1;
@@ -266,25 +278,30 @@ ConvertZeroEffectToNOP(
blank = size;
currentInstPtr[size] = INST_JUMP_TRUE1;
break;
case INST_JUMP_TRUE4:
#endif
case INST_JUMP_TRUE:
blank = size;
currentInstPtr[size] = INST_JUMP_FALSE4;
currentInstPtr[size] = INST_JUMP_FALSE;
break;
case INST_JUMP_FALSE4:
case INST_JUMP_FALSE:
blank = size;
currentInstPtr[size] = INST_JUMP_TRUE4;
currentInstPtr[size] = INST_JUMP_TRUE;
break;
}
break;
case INST_TRY_CVT_TO_NUMERIC:
switch (nextInst) {
#ifndef REMOVE_DEPRECATED_OPCODES
case INST_JUMP_TRUE1:
case INST_JUMP_TRUE4:
case INST_JUMP_FALSE1:
case INST_JUMP_FALSE4:
#endif
case INST_JUMP_TRUE:
case INST_JUMP_FALSE:
case INST_INCR_SCALAR1:
case INST_INCR_SCALAR:
case INST_INCR_ARRAY1:
case INST_INCR_ARRAY:
case INST_INCR_ARRAY_STK:
case INST_INCR_SCALAR_STK:
case INST_INCR_STK:
@@ -351,6 +368,7 @@ AdvanceJumps(
int offset, delta, isNew;
switch (*currentInstPtr) {
#ifndef REMOVE_DEPRECATED_OPCODES
case INST_JUMP1:
case INST_JUMP_TRUE1:
case INST_JUMP_FALSE1:
@@ -373,7 +391,7 @@ AdvanceJumps(
case INST_JUMP1:
delta = TclGetInt1AtPtr(currentInstPtr + offset + 1);
continue;
case INST_JUMP4:
case INST_JUMP:
delta = TclGetInt4AtPtr(currentInstPtr + offset + 1);
continue;
}
@@ -382,12 +400,13 @@ AdvanceJumps(
Tcl_DeleteHashTable(&jumps);
TclStoreInt1AtPtr(offset, currentInstPtr + 1);
continue;
#endif
case INST_JUMP4:
case INST_JUMP_TRUE4:
case INST_JUMP_FALSE4:
case INST_JUMP:
case INST_JUMP_TRUE:
case INST_JUMP_FALSE:
Tcl_InitHashTable(&jumps, TCL_ONE_WORD_KEYS);
Tcl_CreateHashEntry(&jumps, INT2PTR(0), &isNew);
Tcl_CreateHashEntry(&jumps, INT2PTR(0), NULL);
for (offset = TclGetInt4AtPtr(currentInstPtr + 1); offset!=0 ;) {
Tcl_CreateHashEntry(&jumps, INT2PTR(offset), &isNew);
if (!isNew) {
@@ -398,10 +417,12 @@ AdvanceJumps(
case INST_NOP:
offset += InstLength(INST_NOP);
continue;
#ifndef REMOVE_DEPRECATED_OPCODES
case INST_JUMP1:
offset += TclGetInt1AtPtr(currentInstPtr + offset + 1);
continue;
case INST_JUMP4:
#endif
case INST_JUMP:
offset += TclGetInt4AtPtr(currentInstPtr + offset + 1);
continue;
}
@@ -414,6 +435,71 @@ AdvanceJumps(
}
}
/*
* ----------------------------------------------------------------------
*
* BetterEqualityTesting --
*
* Convert PUSH("");OP(STR_EQ); into OP(IS_EMPTY); and some NOPs.
*
* ----------------------------------------------------------------------
*/
static void
BetterEqualityTesting(
CompileEnv *envPtr)
{
unsigned char *currentInstPtr, *emptyPushInstPtr = NULL;
Tcl_HashTable targets;
LocateTargetAddresses(envPtr, &targets);
for (currentInstPtr = envPtr->codeStart ;
currentInstPtr < envPtr->codeNext-1 ;
currentInstPtr += AddrLength(currentInstPtr)) {
if (emptyPushInstPtr && IsTargetAddress(&targets, currentInstPtr)) {
emptyPushInstPtr = NULL;
}
switch (*currentInstPtr) {
case INST_PUSH: {
Tcl_Size idx = TclGetUInt4AtPtr(currentInstPtr + 1);
Tcl_Obj *literal = TclFetchLiteral(envPtr, idx);
if (literal->bytes && literal->length == 0) {
emptyPushInstPtr = currentInstPtr;
} else {
emptyPushInstPtr = NULL;
}
break;
}
case INST_EQ:
case INST_STR_EQ:
if (emptyPushInstPtr != NULL) {
while (emptyPushInstPtr < currentInstPtr) {
*emptyPushInstPtr++ = INST_NOP;
}
*currentInstPtr = INST_IS_EMPTY;
}
emptyPushInstPtr = NULL;
break;
case INST_NEQ:
case INST_STR_NEQ:
if (emptyPushInstPtr != NULL) {
while (emptyPushInstPtr < currentInstPtr) {
*emptyPushInstPtr++ = INST_NOP;
}
currentInstPtr[-1] = INST_IS_EMPTY;
currentInstPtr[0] = INST_LNOT;
}
emptyPushInstPtr = NULL;
break;
case INST_NOP:
break;
default:
emptyPushInstPtr = NULL;
}
}
Tcl_DeleteHashTable(&targets);
}
/*
* ----------------------------------------------------------------------
*
@@ -428,9 +514,11 @@ void
TclOptimizeBytecode(
void *envPtr)
{
ConvertZeroEffectToNOP((CompileEnv *)envPtr);
AdvanceJumps((CompileEnv *)envPtr);
TrimUnreachable((CompileEnv *)envPtr);
CompileEnv *realEnvPtr = (CompileEnv *) envPtr;
ConvertZeroEffectToNOP(realEnvPtr);
BetterEqualityTesting(realEnvPtr);
AdvanceJumps(realEnvPtr);
TrimUnreachable(realEnvPtr);
}
/*
+10 -4
View File
@@ -1381,7 +1381,8 @@ Tcl_ParseVarName(
*/
if (*src == '{') {
char ch; int braceCount = 0;
char ch;
int braceCount = 0;
src++;
numBytes--;
tokenPtr->type = TCL_TOKEN_TEXT;
@@ -1391,13 +1392,18 @@ Tcl_ParseVarName(
ch = *src;
while (numBytes && (braceCount>0 || ch != '}')) {
switch (ch) {
case '{': braceCount++; break;
case '}': braceCount--; break;
case '{':
braceCount++;
break;
case '}':
braceCount--;
break;
case '\\':
/* if 2 or more left, consume 2, else consume
* just the \ and let it run into the end */
if (numBytes > 1) {
src++; numBytes--;
src++;
numBytes--;
}
}
numBytes--;
+10 -12
View File
@@ -89,14 +89,15 @@ typedef struct {
* fields.
*/
#define PATHOBJ(pathPtr) ((FsPath *) (TclFetchInternalRep((pathPtr), &fsPathType)->twoPtrValue.ptr1))
#define PATHOBJ(pathPtr) \
((FsPath *) (TclFetchInternalRep((pathPtr), &fsPathType)->twoPtrValue.ptr1))
#define SETPATHOBJ(pathPtr,fsPathPtr) \
do { \
Tcl_ObjInternalRep ir; \
ir.twoPtrValue.ptr1 = (void *) (fsPathPtr); \
ir.twoPtrValue.ptr2 = NULL; \
Tcl_StoreInternalRep((pathPtr), &fsPathType, &ir); \
} while (0)
do { \
Tcl_ObjInternalRep ir; \
ir.twoPtrValue.ptr1 = (void *) (fsPathPtr); \
ir.twoPtrValue.ptr2 = NULL; \
Tcl_StoreInternalRep((pathPtr), &fsPathType, &ir); \
} while (0)
#define PATHFLAGS(pathPtr) (PATHOBJ(pathPtr)->flags)
/*
@@ -679,10 +680,7 @@ TclPathPart(
}
}
default:
/* We should never get here */
Tcl_Panic("Bad portion to TclPathPart");
/* For less clever compilers */
return NULL;
TCL_UNREACHABLE();
}
} else if (fsPathPtr->cwdPtr != NULL) {
/* Relative path */
@@ -2606,7 +2604,7 @@ Tcl_FSTildeExpand(
/* path[split] is / for ~user/... or \0 for ~user */
result = MakeTildeRelativePath(interp, user,
path[split] ? &path[split + 1] : NULL, dsPtr);
path[split] ? &path[split + 1] : NULL, dsPtr);
Tcl_DStringFree(&dsUser);
}
if (result != TCL_OK) {
+19 -20
View File
@@ -50,6 +50,9 @@ typedef struct PkgFiles {
* package. */
} PkgFiles;
/* Associated data key used to look up the PkgFiles for an interpreter. */
#define ASSOC_KEY "tclPkgFiles"
/*
* For each package that is known in any way to an interpreter, there is one
* record of the following type. These records are stored in the
@@ -101,7 +104,8 @@ static int PkgRequireCoreFinal(void *data[], Tcl_Interp *interp, int result);
static int PkgRequireCoreCleanup(void *data[], Tcl_Interp *interp, int result);
static int PkgRequireCoreStep1(void *data[], Tcl_Interp *interp, int result);
static int PkgRequireCoreStep2(void *data[], Tcl_Interp *interp, int result);
static int TclNRPkgRequireProc(void *clientData, Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]);
static int TclNRPkgRequireProc(void *clientData, Tcl_Interp *interp,
int reqc, Tcl_Obj *const reqv[]);
static int SelectPackage(void *data[], Tcl_Interp *interp, int result);
static int SelectPackageFinal(void *data[], Tcl_Interp *interp, int result);
static int TclNRPackageObjCmdCleanup(void *data[], Tcl_Interp *interp, int result);
@@ -258,13 +262,13 @@ TclInitPkgFiles(
* If assocdata "tclPkgFiles" doesn't exist yet, create it.
*/
PkgFiles *pkgFiles = (PkgFiles *)Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
PkgFiles *pkgFiles = (PkgFiles *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
if (!pkgFiles) {
pkgFiles = (PkgFiles *)Tcl_Alloc(sizeof(PkgFiles));
pkgFiles->names = NULL;
Tcl_InitHashTable(&pkgFiles->table, TCL_STRING_KEYS);
Tcl_SetAssocData(interp, "tclPkgFiles", PkgFilesCleanupProc, pkgFiles);
Tcl_SetAssocData(interp, ASSOC_KEY, PkgFilesCleanupProc, pkgFiles);
}
return pkgFiles;
}
@@ -274,8 +278,7 @@ TclPkgFileSeen(
Tcl_Interp *interp,
const char *fileName)
{
PkgFiles *pkgFiles = (PkgFiles *)
Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
PkgFiles *pkgFiles = (PkgFiles *) Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
if (pkgFiles && pkgFiles->names) {
const char *name = pkgFiles->names->name;
@@ -857,7 +860,7 @@ SelectPackageFinal(
* Pop the "ifneeded" package name from "tclPkgFiles" assocdata
*/
PkgFiles *pkgFiles = (PkgFiles *)Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
PkgFiles *pkgFiles = (PkgFiles *)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
PkgName *pkgName = pkgFiles->names;
pkgFiles->names = pkgName->nextPtr;
Tcl_Free(pkgName);
@@ -1098,13 +1101,12 @@ TclNRPackageObjCmd(
}
switch (optionIndex) {
case PKG_FILES: {
PkgFiles *pkgFiles;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "package");
return TCL_ERROR;
}
pkgFiles = (PkgFiles *) Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
PkgFiles *pkgFiles = (PkgFiles *)
Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
if (pkgFiles) {
Tcl_HashEntry *entry = Tcl_FindHashEntry(&pkgFiles->table,
TclGetString(objv[2]));
@@ -1116,12 +1118,11 @@ TclNRPackageObjCmd(
break;
}
case PKG_FORGET: {
const char *keyString;
PkgFiles *pkgFiles = (PkgFiles *)
Tcl_GetAssocData(interp, "tclPkgFiles", NULL);
Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
for (i = 2; i < objc; i++) {
keyString = TclGetString(objv[i]);
const char *keyString = TclGetString(objv[i]);
if (pkgFiles) {
hPtr = Tcl_FindHashEntry(&pkgFiles->table, keyString);
if (hPtr) {
@@ -1157,8 +1158,7 @@ TclNRPackageObjCmd(
}
case PKG_IFNEEDED: {
Tcl_Size length;
int res;
char *argv3i, *avi;
char *argv3i;
if ((objc != 4) && (objc != 5)) {
Tcl_WrongNumArgs(interp, 2, objv, "package version ?script?");
@@ -1183,13 +1183,14 @@ TclNRPackageObjCmd(
for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL;
prevPtr = availPtr, availPtr = availPtr->nextPtr) {
char *avi;
if (CheckVersionAndConvert(interp, availPtr->version, &avi,
NULL) != TCL_OK) {
Tcl_Free(argv3i);
return TCL_ERROR;
}
res = CompareVersions(avi, argv3i, NULL);
int res = CompareVersions(avi, argv3i, NULL);
Tcl_Free(avi);
if (res == 0) {
@@ -1394,9 +1395,7 @@ TclNRPackageObjCmd(
return TCL_OK;
}
break;
case PKG_UNKNOWN: {
Tcl_Size length;
case PKG_UNKNOWN:
if (objc == 2) {
if (iPtr->packageUnknown != NULL) {
Tcl_SetObjResult(interp,
@@ -1406,6 +1405,7 @@ TclNRPackageObjCmd(
if (iPtr->packageUnknown != NULL) {
Tcl_Free(iPtr->packageUnknown);
}
Tcl_Size length;
argv2 = TclGetStringFromObj(objv[2], &length);
if (argv2[0] == 0) {
iPtr->packageUnknown = NULL;
@@ -1417,7 +1417,6 @@ TclNRPackageObjCmd(
return TCL_ERROR;
}
break;
}
case PKG_PREFER: {
static const char *const pkgPreferOptions[] = {
"latest", "stable", NULL
@@ -1528,7 +1527,7 @@ TclNRPackageObjCmd(
break;
}
default:
Tcl_Panic("Tcl_PackageObjCmd: bad option index to pkgOptions");
TCL_UNREACHABLE();
}
return TCL_OK;
}

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