Compare commits

...
Author SHA1 Message Date
apnadkarni 05262be331 Update manpages in anticipation of TIP 656 2023-03-16 16:24:04 +00:00
pooryorick 70cf69246f New script used in the "valgrind_each" target in Makefile.in 2023-03-15 20:13:22 +00:00
jan.nijtmans 7543a1313f Merge 8.6 2023-03-15 16:23:22 +00:00
jan.nijtmans e0e09638fe Remove _LARGEFILE_SOURCE64 usage. See [d690400d07] 2023-03-15 16:21:53 +00:00
dgp 6d3b66ad23 Merge in constraint spelling fix. Keep it in case the knownBug constraint is ever removed. 2023-03-15 13:28:55 +00:00
dgp 6bd8763c2d Misspelled constraint created testing noise. 2023-03-15 12:53:03 +00:00
jan.nijtmans 23a421a9c1 Merge-mark. @nathan, please do forward merges from core-8-6-branch -> core-8-branch -> trunk. Fossil is not so intelligent, figuring out what's happening here. 2023-03-15 09:32:02 +00:00
pooryorick ba737587a8 Further fix for issue [ea69b0258a9833cb], crash when using a channel transformation on TCP client socket. 2023-03-15 09:25:15 +00:00
pooryorick 6ded4b92be Further fix for issue [ea69b0258a9833cb], crash when using a channel transformation on TCP client socket. 2023-03-15 08:42:11 +00:00
pooryorick 6cf4a0dea3 Merge core-8-branch. 2023-03-14 20:37:45 +00:00
pooryorick fdcb9621bb Further fix for issue [ea69b0258a9833cb], crash when using a channel
transformation on TCP client socket.
2023-03-14 20:30:34 +00:00
pooryorick 3aef0c58f9 Further fix for issue [ea69b0258a9833cb], crash when using a channel transformation on TCP client socket. 2023-03-14 20:27:04 +00:00
jan.nijtmans b05b4cf948 Since "unicode" is deprecated, use "utf-16" in testcases. Otherwise -DTCL_NO_DEPRECATED build fails. 2023-03-14 10:30:59 +00:00
jan.nijtmans 18a99f2522 Add "ucs-2" constraint to encoding-bug-183a1adcc0-5 testcase, otherwise it fails with TCL_UTF_MAX>3.
Broken by [47857515422b8519|this] commit
2023-03-14 10:05:24 +00:00
pooryorick 953a44bc6e Fix for issue [ea69b0258a9833cb], crash when using a channel transformation on
TCP client socket.
2023-03-13 19:19:32 +00:00
pooryorick 5094fb7825 Fix for issue [ea69b0258a9833cb], crash when using a channel transformation on
TCP client socket.
2023-03-13 19:07:25 +00:00
apnadkarni d53dfb14c7 Merge 8.6: Bug [183a1adcc0]. Buffer overflow in Tcl_UtfToExternal 2023-03-13 15:34:22 +00:00
apnadkarni 6d74232282 Bug [183a1adcc0]. Buffer overflow in Tcl_UtfToExternal 2023-03-13 13:44:35 +00:00
pooryorick df8a3a6ea4 Fix for issue [ea69b0258a9833cb], crash when using a channel transformation on
TCP client socket.
2023-03-13 13:36:52 +00:00
pooryorick 967e55306e Fix for issue [ea69b0258a9833cb], crash when using a channel transformation on
TCP client socket.
2023-03-13 12:22:06 +00:00
jan.nijtmans 131176ce2f Backport [6fb14ee3e876978c]. Add testcases 2023-03-12 16:37:12 +00:00
jan.nijtmans 77e951f2b8 Fix [db7a085bd9]: encoding convertfrom -strict utf-16 accepts partial surrogates 2023-03-12 12:37:29 +00:00
jan.nijtmans 8bf2e2ace2 Forgot that \x00 is not printable anyway 2023-03-12 11:32:52 +00:00
jan.nijtmans b7f151f126 Make test-output more readable when it contains non-printable characters (stolen from TIP #656 impl, thanks Ashok!)
tcltest -> 2.5.6
2023-03-12 11:24:24 +00:00
jan.nijtmans 8c5fc11b5a Always output 2 hex characters in "unexpected byte sequence" exception message.
make testcases io-38.3/chan-io-38.3 independant from system encoding
2023-03-12 10:49:18 +00:00
jan.nijtmans 1889ded114 Proposed fix for [db7a085bd9]: encoding convertfrom -strict utf-16 accepts partial surrogates. TODO: testcases, and implement for 8.7 too 2023-03-11 22:00:29 +00:00
dgp 21388fa31e merge 8.7 2023-03-10 13:45:01 +00:00
dgp 0951d3f692 merge 8.6 2023-03-10 13:33:19 +00:00
dgp 93bf87ed85 Make test less fragile to changing set of options. 2023-03-10 13:32:47 +00:00
jan.nijtmans 494b4c8127 Fix cmdAH-4.3.13.00D80000.solo.utf-32le.tcl8.a testcase from tip-656-tcl9 branch, when TCL_UTF_MAX=3 2023-03-09 20:55:43 +00:00
jan.nijtmans bd3a6be21b Merge 8.7 2023-03-09 10:22:55 +00:00
jan.nijtmans 962d8aed89 Merge 8.6 2023-03-09 10:21:54 +00:00
jan.nijtmans 5b0be62536 Adapt 2 testcases (io-39.16/io-39.16a), showing that "-encoding" can be shortened to "-en", but not to "-e" (because there is -eofchar too) 2023-03-09 10:08:02 +00:00
jan.nijtmans a1fb554585 Fix tests/tcltest.test testcases (missing "namespace import") 2023-03-09 09:39:59 +00:00
apnadkarni 552d2bb53f Merge 8.7 - winFCmd-1.24 differs in error code on Win 11 2023-03-09 02:52:51 +00:00
apnadkarni 1b7f525ec7 Merge 8.6 - winFCmd-1.24 differs in error code on Win 11 2023-03-09 02:50:32 +00:00
apnadkarni 38555b60a2 winFCmd-1.24 has different error code on Win 11 2023-03-09 02:47:53 +00:00
jan.nijtmans c3da6c8fed Merge core-8-branch 2023-03-08 20:16:32 +00:00
jan.nijtmans 468e5148b3 Merge 8.6 2023-03-08 20:15:43 +00:00
jan.nijtmans 7ed7017d94 Add "notWsl" test constraints. Clean up many testcases 2023-03-08 19:58:08 +00:00
jan.nijtmans 10f4d4565d More -Wconversion warning fixes 2023-03-08 15:01:20 +00:00
jan.nijtmans fa28b1f243 Merge 8.7 2023-03-08 11:12:04 +00:00
jan.nijtmans 3203978c65 Add "teststringobj newunicode". Not used in testcases yet. 2023-03-08 11:02:27 +00:00
jan.nijtmans 9aea48988c Merge 8.7 2023-03-07 20:10:15 +00:00
jan.nijtmans 0e0d74624b Fix [b4af93cd9f]: uninitialized bytes in http11-1.13.0 2023-03-07 20:09:30 +00:00
jan.nijtmans fffb0bdce5 Merge 8.7 2023-03-07 18:23:15 +00:00
jan.nijtmans 82acd6a35a Merge 8.6 2023-03-07 18:14:39 +00:00
jan.nijtmans 5cf1eed910 Fix a few -Wconversion warnings 2023-03-07 17:56:45 +00:00
apnadkarni 8c5476848a Merge 8.7 - testchmod fixes 2023-03-07 12:53:58 +00:00
apnadkarni 4df874dd7f Merge 8.6 - testchmod fixes 2023-03-07 12:28:40 +00:00
apnadkarni 906268caa7 Merge testchmod fix 2023-03-07 10:46:31 +00:00
jan.nijtmans 1ae5fd8198 Merge 8.7 2023-03-07 07:41:26 +00:00
jan.nijtmans 01d6e02666 Merge 8.6 2023-03-07 07:34:21 +00:00
jan.nijtmans e10915b565 Fix [95e287b956]: uninit value use in stringObj-4.2 2023-03-07 07:23:10 +00:00
jan.nijtmans 03618f8c95 merge-mark 2023-03-07 07:06:51 +00:00
jan.nijtmans 071917e1b2 Fix [f3cb2a32d6]: uninitialized value in format-2.18. Also remove repeated call to Tcl_DStringInit() 2023-03-07 07:03:36 +00:00
apnadkarni 1f6cec5ff3 Fix testchmod and associated tests that always failed on Windows 2023-03-07 02:52:26 +00:00
apnadkarni fe7ee54772 Create new branch named "bug-win-testchmod" 2023-03-07 02:27:43 +00:00
jan.nijtmans f5ba8a8478 Proposed fix for [95e287b956]: uninit value use in stringObj-4.2 2023-03-06 21:01:45 +00:00
jan.nijtmans f4450abcf9 Proposed fix for [f3cb2a32d6]: uninitialized value in format-2.18 2023-03-06 19:58:53 +00:00
dgp 5e095a3a4d [b4af93cd9f] Proposed fix from apnadkarni. It works! 2023-03-06 18:17:19 +00:00
jan.nijtmans 3eb68691b8 ckfree() -> Tcl_Free() 2023-03-06 10:30:41 +00:00
jan.nijtmans f0e415c1e1 Merge 8.7 2023-03-06 10:28:47 +00:00
jan.nijtmans cfa443421b Tcl_WinTCharToUtf() is deprecated, so use Tcl_WCharToUtfDString() in stead. 2023-03-06 10:24:15 +00:00
pooryorick 296e4767ea Add new valgrind suppression items. 2023-03-06 07:00:48 +00:00
pooryorick fa795b478a Add new valgrind suppression items. 2023-03-06 06:59:52 +00:00
pooryorick 40e214cd76 Add new valgrind suppression items. 2023-03-06 06:58:13 +00:00
jan.nijtmans 7ec4501d37 Merge 8.7 2023-03-05 21:27:49 +00:00
jan.nijtmans 9e0cc9d630 Merge-mark (but also remove some lost spacing) 2023-03-05 21:16:33 +00:00
jan.nijtmans 9d2cc36a0e Fix [57bfcf43dd]: Remove unreachable code in Tcl_SetWideIntObj() 2023-03-05 21:09:46 +00:00
jan.nijtmans e4e1062338 Another round of -1 -> TCL_INDEX_NONE 2023-03-05 19:57:48 +00:00
apnadkarni 0968aa6de7 Merge 8.7: Bug [9c5a00c69d]. Fix ~user on Windows 2023-03-05 11:42:31 +00:00
pooryorick f736bb9d86 A better fix for Valgrind "still reachable" report in TestcmdtokenCmd(). 2023-03-05 11:39:36 +00:00
apnadkarni 6e7d72c158 Merge 8.6: Bug [9c5a00c69d]. Fix ~user on Windows 2023-03-05 11:09:10 +00:00
apnadkarni 1f7d2aae34 Bug [9c5a00c69d]. Fix ~user on Windows 2023-03-05 09:57:29 +00:00
pooryorick 76edd58c3e A better fix for Valgrind "still reachable" report in TestcmdtokenCmd(). 2023-03-05 07:11:15 +00:00
jan.nijtmans 923ff1e3ca More -1 -> TCL_INDEX_NONE 2023-03-05 00:26:54 +00:00
jan.nijtmans 33d81b98be Make dltest/pkg*.c simple example how to use Tcl_Size with Tcl_GetStringFromObj() 2023-03-04 18:12:49 +00:00
apnadkarni 234394e2df Merge 8.7 - Protect zlib errors with check for null interp 2023-03-04 16:33:36 +00:00
apnadkarni 7b3ef36925 Protect zlib errors with check for null interp 2023-03-04 16:26:00 +00:00
apnadkarni c862e57095 Add test for [9c5a00c69d], tilde expansion of ~user 2023-03-04 15:11:01 +00:00
apnadkarni 0229ba1283 Bug [9c5a00c69d]. Tilde expansion on Windows 2023-03-04 12:13:31 +00:00
jan.nijtmans 4e84e02684 Merge 8.7 2023-03-04 10:20:34 +00:00
jan.nijtmans 80b392ba8e Merge 8.6 2023-03-04 10:19:44 +00:00
jan.nijtmans e13edcba86 Test constraint notInCIenv no longer necessary (due to previous fix) 2023-03-04 10:18:41 +00:00
jan.nijtmans e95b015990 Merge 8.7 2023-03-04 10:13:19 +00:00
jan.nijtmans aebb7627f5 Merge 8.6 2023-03-04 10:09:21 +00:00
jan.nijtmans 6285c13367 Fix [1b8df10110]: Tcl_GetTime returns wrong usec value on Windows 2023-03-04 10:08:18 +00:00
jan.nijtmans 8f18e27691 Adapt type-casts to Tcl 9.0 signature of Tcl_Free/Tcl_Realloc/Tcl_AttemptRealloc 2023-03-03 13:04:11 +00:00
jan.nijtmans 7f3d1257ff ckfree() shouldn't be used in Tcl 9 core code any more 2023-03-03 13:03:02 +00:00
pooryorick e7b37f1737 Fix Valgrind "still reachable" report in TestcmdtokenCmd(). 2023-03-03 12:39:09 +00:00
pooryorick 18385b8363 Fix Valgrind "still reachable" report in TestcmdtokenCmd(). 2023-03-03 12:17:15 +00:00
pooryorick d3aa6839f4 Fix Valgrind "still reachable" report in TestcmdtokenCmd(). 2023-03-03 12:15:11 +00:00
apnadkarni cb3d36ad5a Bug [9a978f8323]: Fix large reads > 2GB 2023-03-03 10:47:51 +00:00
apnadkarni b464703493 Merge 8.7: Disable more file permissions tests for WSL (not supported in WSL/NTFS) 2023-03-02 07:32:04 +00:00
apnadkarni 4d67456953 Disable more file permissions tests for WSL (not supported in WSL/NTFS) 2023-03-02 07:08:48 +00:00
apnadkarni 1d9ebbc740 Merge mark with core-8-branch 2023-03-01 14:57:20 +00:00
apnadkarni 5a3e0c869e Cherrypick [f1dd5f1cc7]: constrain tests not supported on WSL 2023-03-01 14:55:13 +00:00
apnadkarni 64e7f77040 Disable file permission tests under WSL as WSL does not support Unix file attrs without special config 2023-03-01 13:58:52 +00:00
apnadkarni cc5dd09db3 Merge trunk 2023-03-01 13:41:44 +00:00
apnadkarni 30a9b333ba Bug [9a978f8323]: crash reading large files 2023-03-01 13:18:17 +00:00
jan.nijtmans 261c174d97 Fix msvc build (with OPTS=symbols) 2023-03-01 11:06:17 +00:00
apnadkarni a6b4ef3d29 Fix [f8ef6b3670] crash. TclpSysAlloc macro was truncating size request to 32 bits on Windows. 2023-03-01 07:56:03 +00:00
jan.nijtmans 62d9150ef5 Merge 8.7 2023-02-28 13:36:00 +00:00
jan.nijtmans 4227ef37bb Put back testcase io-52.20, and re-fix [4a7397e0b3] 2023-02-28 13:33:04 +00:00
jan.nijtmans 7c9fe49b51 Merge 8.7 2023-02-28 12:45:06 +00:00
jan.nijtmans bb80189110 Missing ')' 2023-02-28 12:43:53 +00:00
jan.nijtmans 1923d22832 Merge 8.7 2023-02-28 12:20:34 +00:00
jan.nijtmans 70e40dd53d Restore previous behavior for non-blocking mode, as for this mode the semantics of [read]/[gets] were not broken. This was the 'some agreement'.
The change in line 8286 is necessary for both blocking and non-blocking mode: Whenver the encoding change we need to reset the CHANNEL_ENCODING_ERROR flag.
2023-02-28 12:16:10 +00:00
pooryorick 7661972907 Reverted [d156af9fb76dd2f4] and removed tests io-52.20 io-75.6 io-75.7, as this
commit, intended to fix issue [b8f575aa2398b0e4], breaks the semantics of
[read] and [gets].  Such a change would require an accepted TIP. See [b8f575aa2398b0e4] for further discussion.

jn: @pouryorick See [b8f575aa2398b0e4] for the reason why this commit is not appropriate: It gets core-8-branch back in the buggy state it was, without even providing a real solution everyone agrees on. You shouldn't revert my patch just because I reverted yours.

pooryorick:  As I explained, the reason for this reversion is that it hard-codes an unapproved change in the semantics of [read] and [gets] into the test suite.  Jan, your statement that it's a "revenge" reversion is false.  I spent a month trying to find some alternative to this reversion before actually performing it.  A commit that codifes in its tests changes in semantcs to [read]/[gets] simply shouldn't be on core-8-branch.
2023-02-28 11:57:03 +00:00
pooryorick bb2f06fc73 Reverted [d156af9fb76dd2f4] and removed tests io-52.20 io-75.6 io-75.7, as this
commit, intended to fix issue [b8f575aa2398b0e4], breaks the semantics of
[read] and [gets].  Such a change would require an accepted TIP. See [b8f575aa2398b0e4] for further discussion.

jn: @pouryorick See [b8f575aa2398b0e4] for the reason why this commit is not appropriate: It gets core-8-branch back in the buggy state it was, without even providing a real solution everyone agrees on. You shouldn't revert my patch just because I reverted yours.

pooryorick:  As I explained, the reason for this reversion is that it hard-codes an unapproved change in the semantics of [read] and [gets] into the test suite.  Jan, your statement that it's a "revenge" reversion is false.  I spent a month trying to find some alternative to this reversion before actually performing it.  A commit that codifes in its tests changes in semantcs to [read]/[gets] simply shouldn't be on core-8-branch.
2023-02-28 11:42:15 +00:00
jan.nijtmans fadb24f26a Merge 8.7. And fix Tcl_UtfToExternal()/Tcl_ExternalToUtf() (at least - sufficient for tclZlib.c), such that it now returns an error when src and dst *both* exceed INT_MAX. To be discussed further. 2023-02-28 11:00:44 +00:00
jan.nijtmans 5d8ae9bf17 Merge 8.6 2023-02-28 10:36:25 +00:00
apnadkarni 8e139e5cd7 Merge bug-fb368527ae. Bug [fb368527ae] Large string truncation 2023-02-28 10:28:28 +00:00
jan.nijtmans da55e192ba Fix [f9eafc3886]: Error handling in zlib comment/filename 2023-02-28 10:18:28 +00:00
pooryorick 57d266423a Make the descriptions in doc/Tcl.n more concise and intuitive. 2023-02-28 10:13:25 +00:00
pooryorick d29598480f Make the descriptions in doc/Tcl.n more concise and intuitive. 2023-02-28 10:06:22 +00:00
pooryorick 7d6cf09e02 Make the descriptions in doc/Tcl.n more concise and intuitive. 2023-02-28 10:04:49 +00:00
pooryorick 8b417f0e1e Fix formatting issue in Tcl.n 2023-02-28 09:59:29 +00:00
pooryorick e743d3e487 Fix formatting issue in Tcl.n 2023-02-28 09:57:22 +00:00
jan.nijtmans a947270ff7 In case of combining TIP #494 (TCL_8_COMPAT) and #628 (building for Tcl 8.7 with 9.0 headers), ignore TCL_8_COMPAT macro. More Tcl_Size usage. 2023-02-28 07:45:27 +00:00
jan.nijtmans a1fe72fa4a Fix testcases 2023-02-27 20:50:33 +00:00
apnadkarni 85bf0db1e8 Fix crash. int->size_t needs +1 in comparisons. 2023-02-27 12:31:49 +00:00
jan.nijtmans c6bb33407a Fix [3d01d51bc4]: Tcl 9: Cannot write large strings to file. Also some size_t -> Tcl_Size changes. 2023-02-27 11:59:54 +00:00
apnadkarni e2d89615d5 Tests for encoding strings > 4GB (under perf constraint) 2023-02-27 04:15:07 +00:00
apnadkarni ed360ca42f Add perf constraint to large io tests to prevent memory faults on systems with limited memory 2023-02-27 03:13:38 +00:00
jan.nijtmans 6b172a2131 fill in bug ticket-nr 2023-02-26 21:37:15 +00:00
jan.nijtmans e7b8b9d2dd Proposed fix for [f9eafc3886]: Error handling in zlib comment/filename. With testcases 2023-02-26 20:12:43 +00:00
jan.nijtmans 152d7203ac Handle Tcl_UtfToExternal error in tclZlib.c 2023-02-26 17:19:07 +00:00
jan.nijtmans baf9b5e9bb Handle statePtr != NULL as well 2023-02-26 16:54:02 +00:00
jan.nijtmans cbda5cb9b2 Make Tcl_UtfToExternal()/Tcl_ExternalToUtf() report the error, if srcLen and dstLen are both > INT_MAX and therefore not all characters can be handled by this function. 2023-02-26 16:41:06 +00:00
jan.nijtmans 6ab1efe806 merge-mark 2023-02-26 16:04:57 +00:00
jan.nijtmans 08a6b105e5 Merge 8.6 2023-02-26 16:04:03 +00:00
jan.nijtmans 8fdf20ec2b More dstring testcases, extracted from [46dda6fc29] 2023-02-26 16:01:29 +00:00
apnadkarni 4e6558b44a Fix [46dda6fc29] - trace crash caused by TclScanElement 2023-02-26 15:42:37 +00:00
jan.nijtmans 5ffda39949 Move the "srcLen -= srcChunkRead;" past the "if ((result != TCL_CONVERT_NOSPACE)..." (where it originally was), since this isn't needed if the loop ends anyway. 2023-02-26 12:56:18 +00:00
jan.nijtmans 79cbdf745a (size_t) -1 -> TCL_INDEX_NONE 2023-02-26 12:27:43 +00:00
apnadkarni deec081e74 Also fix [90ff9b7f73] - writes of exactly 4294967295 bytes 2023-02-26 07:15:06 +00:00
apnadkarni 2fb6b99620 Minor refactor, add tests 2023-02-26 06:26:01 +00:00
apnadkarni 7b0b2ebd37 Fix large writes to file. Need to break into INT_MAX size chunks. 2023-02-25 17:23:42 +00:00
apnadkarni 2a5b403768 Experimental fix for [fb368527ae] - length truncation 2023-02-25 16:29:09 +00:00
apnadkarni aa2b48262b Fix and tests for [46dda6fc29] 2023-02-25 09:26:06 +00:00
apnadkarni a826e66f11 Add tests for Bug [46dda6fc29] 2023-02-25 08:58:31 +00:00
apnadkarni 8390c51fca Fix [1d074b177a]. Failure to read .tclshrc 2023-02-25 07:35:21 +00:00
jan.nijtmans d5e9da898f Merge 8.7 2023-02-24 08:33:24 +00:00
jan.nijtmans 1c3c25097b int -> Tcl_Size in tclEncoding.c (making the diff between Tcl 8.7 and 9.0 smaller) 2023-02-24 08:25:27 +00:00
jan.nijtmans 190f9219d5 Merge 8.7 2023-02-23 11:02:00 +00:00
jan.nijtmans 956059093c Fix [4bea02e811]: encoding convertfrom -strict ascii \x7f generates exception
Many other encodings had the same problem, and also the reverse happened: encodings which should throw an exception with -strict but didn't (within range 0x80-0x9F)
2023-02-23 11:00:48 +00:00
jan.nijtmans ce349b05df merge-mark 2023-02-23 10:45:56 +00:00
jan.nijtmans bf7b1adb89 See [d19fe0a5b] for follow-up to previous commit 2023-02-23 10:44:56 +00:00
jan.nijtmans 9ae7f4dc4f merge-mark 2023-02-22 20:46:01 +00:00
jan.nijtmans 1d76ffb03b minor bug-fix in utf-16/utf-32: 2 testcases failed in Tcl 9 compatibility mode (-DTCL_NO_DEPRECATED) 2023-02-22 20:44:13 +00:00
jan.nijtmans 7c6f71019a Merge 8.7 2023-02-22 20:27:34 +00:00
jan.nijtmans 8f37d5c24e Merge 8.6 2023-02-22 17:56:42 +00:00
jan.nijtmans c3e063b0aa Fix [d19fe0a5b]: Handling incomplete byte sequences for utf-16/utf-32 2023-02-22 17:34:22 +00:00
jan.nijtmans 12345dfed8 re-generate macDingbats.enc, so it can now throw exceptions for the range 0x8E-0x9F 2023-02-22 13:34:04 +00:00
jan.nijtmans 78db448fff Make txt2enc smarter, so we don't have to add DELETE any more in all original tables, better keep them as-is. 2023-02-22 13:31:41 +00:00
jan.nijtmans 58f1209a70 Merge 8.7. Adapt more testcases not to depend on the system encoding any more 2023-02-22 13:03:31 +00:00
jan.nijtmans e106525498 Merge 8.7 2023-02-22 07:48:10 +00:00
jan.nijtmans f0284298ad Fix [5607d6482c]: strict ucs-2 never implemented (TIP #346/#656) 2023-02-22 07:28:27 +00:00
jan.nijtmans 03a9d6928d Merge 8.6 2023-02-22 07:24:42 +00:00
jan.nijtmans 5219c94af5 Fix [534172ff5b]: Crash in DeleteReflectedChannelMap (introduced via tcllib 1.21) 2023-02-22 07:21:15 +00:00
jan.nijtmans a970bffd00 Add 0x7F: DELETE to more mac* encodings (so re-generating doesn't remove it again) 2023-02-21 23:22:45 +00:00
jan.nijtmans f95599f4d4 More encoding fixes, e.g. range 0x80-0x9F for dingbats and symbol. Remove "-m" option from txt2enc.c tool, since the same is already handled in the table encoding code in Tcl itself. This was wat prevent Tcl to handle throwing exceptions correctly 2023-02-21 23:16:14 +00:00
jan.nijtmans c606ae1574 Proposed fix for [d19fe0a5b]: Handling incomplete byte sequences for utf-16/utf-32 2023-02-21 17:50:36 +00:00
jan.nijtmans 42956f6f09 Some test-cases start failing in 9.0-compatibility-mode (-DTCL_NO_DEPRECATED), if the system encoding is one with gaps. So, better use iso8859-1 for those testcases 2023-02-21 16:58:13 +00:00
jan.nijtmans 417f868693 Proposed fix for [534172ff5b]: Crash in DeleteReflectedChannelMap (introduced via tcllib 1.21) 2023-02-21 16:09:18 +00:00
jan.nijtmans 3315012c95 re-generated 8 more encodings 2023-02-20 21:43:29 +00:00
jan.nijtmans 8660fd1af2 Two more files, re-generated 2023-02-20 20:52:06 +00:00
jan.nijtmans 280034d2ab Proposed fix for [4bea02e811]: encoding convertfrom -strict ascii \x7f generates exception 2023-02-20 20:41:00 +00:00
jan.nijtmans 23d9ca0ec4 Proposed fix for [5607d6482c]: strict ucs-2 never implemented (TIP #346/#656) 2023-02-19 11:41:44 +00:00
jan.nijtmans 0892c6f37c Merge 8.7 2023-02-17 19:15:28 +00:00
jan.nijtmans c731ca1ffd Fix for [885c86a9a0]: convertfrom utf8 breaks for 4 byte utf encodings 2023-02-17 19:14:42 +00:00
jan.nijtmans 45796af99d complete fix 2023-02-16 21:50:53 +00:00
jan.nijtmans 6bcdbfbf84 Merge 8.7 2023-02-16 21:41:49 +00:00
jan.nijtmans 6d674a96a1 Final part of [10c2c17c32]: UTF-LE32 encoder mapping of surrogates. Problem was in testcase, not in actual code 2023-02-16 21:29:07 +00:00
jan.nijtmans a3f58db271 Merge 8.7 2023-02-16 21:14:24 +00:00
jan.nijtmans 2c3252bc5c Fix [5e6ae6e05e]: Implement -strict correctly for cesu-8 2023-02-16 21:03:48 +00:00
jan.nijtmans d790e81db2 Fix [33ab6d08eb]: Inconsistent behavior with encoding convertfrom -failindex 2023-02-16 20:57:47 +00:00
jan.nijtmans 0563a78902 Fix [5e6ae6e05e]: Implement -strict correctly for cesu-8 2023-02-16 16:59:10 +00:00
jan.nijtmans 5053891183 Try to fix [885c86a9a0]. Doesn't work completely yet. 2023-02-16 07:59:09 +00:00
jan.nijtmans f06c5e7af1 Fix for [33ab6d08eb]: Inconsistent behavior with encoding convertfrom -failindex 2023-02-15 20:26:10 +00:00
jan.nijtmans 7fb1760f42 Merge 8.7. Test-case only 2023-02-15 07:30:03 +00:00
jan.nijtmans 4c2d834fca Ticket [10c2c17c32] follow-up. One output char too much with -failindex. 2023-02-15 07:21:55 +00:00
jan.nijtmans fb260e8382 Merge 8.7 2023-02-14 22:06:32 +00:00
jan.nijtmans 5040a69c28 Fix for [bd1a60eb9c]: convertfrom utf-8 strict mode allows surrogates in input sequence 2023-02-14 21:42:01 +00:00
jan.nijtmans 38df355850 Complete fix for [bd1a60eb9c]. Also fix a bug in the tableencoding. With testcases. 2023-02-14 20:50:26 +00:00
jan.nijtmans 2974b57279 Make a start fixing [bd1a60eb9c]. WIP 2023-02-14 07:29:36 +00:00
jan.nijtmans 0c306c8f81 Merge 8.7. Mark (new) testcase encoding-16.15 as "knownBug": still needs a fix. 2023-02-13 10:12:45 +00:00
jan.nijtmans 05f4bc701f Fix for [10c2c17c32]: UTF-LE32 encoder mapping of surrogates. With testcases (both for utf-32 and utf-16, which had the same bug) 2023-02-13 08:39:29 +00:00
jan.nijtmans bfaa709c2e Merge 8.7 2023-02-12 01:00:58 +00:00
jan.nijtmans 3954b7c2a3 Proposed fix (and testcases) for [4a7397e0b3]: Tcl 9: fcopy with -strictencoding 1 UTF-8 channels 2023-02-12 00:49:22 +00:00
jan.nijtmans bab9170bdc Proposed fix (and testcases) for [4a7397e0b3]: Tcl 9: fcopy with -strictencoding 1 UTF-8 channels 2023-02-10 20:22:07 +00:00
jan.nijtmans fd83fb931e Add 4 more testcases, showing that the same bug is present in utf-16 as well. Also fix the bug (really, now!) 2023-02-09 19:52:00 +00:00
jan.nijtmans b185a55c3b Add 4 testcases, showing that the bug fix introduces another (minor) problem. To be fixed soon 2023-02-09 07:55:29 +00:00
jan.nijtmans f5f5ff4257 Proposed fix for [10c2c17c32]: UTF-LE32 encoder mapping of surrogates. TODO: testcase 2023-02-06 22:43:30 +00:00
jan.nijtmans c529405c65 Merge 8.7 2023-02-02 07:17:06 +00:00
jan.nijtmans de0a637d7c Fix documentation on "encoding" command 2023-02-02 07:12:34 +00:00
jan.nijtmans 536651d954 Merge 8.7 2023-02-01 23:02:16 +00:00
jan.nijtmans b9c893dbc9 Renumber testscase, sync with Tcl 9.0 2023-02-01 21:01:51 +00:00
jan.nijtmans 6b6d121149 merge-mark 2023-02-01 08:13:06 +00:00
jan.nijtmans 3eaad4bbc9 (cherry-pick) Make Tcl_UniCharToUtf more readable and add test to exercise surrogate handling. (test-case was still missing, which cannot be used in Tcl 8.6) 2023-02-01 08:10:12 +00:00
jan.nijtmans 44dd5d86bc merge-mark 2023-02-01 07:33:13 +00:00
jan.nijtmans 537c8e77ba (cherry-pick) Make Tcl_UniCharToUtf more readable and add test to exercise surrogate handling. 2023-02-01 07:32:14 +00:00
jan.nijtmans 5866ef6d2a (Cherry-pick) Make Tcl_UniCharToUtf more readable. 2023-02-01 07:29:48 +00:00
pooryorick 0184ebda4f Make Tcl_UniCharToUtf more readable and add test to exercise surrogate
handling.
2023-01-31 23:04:56 +00:00
pooryorick 078a694834 Fix error introduced in [3e5e37f83b058f3d] for Tcl_UniCharToUtf, and add test. 2023-01-31 22:15:02 +00:00
jan.nijtmans e5272c9be6 Remove incorrect comment. See: [https://www.magicsplat.com/tcl9/tcl9unicode.html#surrogates-as-literals]. Thanks, Ashok, for noticing this! 2023-01-31 17:34:05 +00:00
jan.nijtmans 596e33bb9e Remove incorrect comment. See: [https://www.magicsplat.com/tcl9/tcl9unicode.html#surrogates-as-literals]. Thanks, Ashok, for noticing this! 2023-01-31 17:30:59 +00:00
jan.nijtmans 081c085c0f merge-mark 2023-01-31 08:14:00 +00:00
jan.nijtmans 64e3a23bfd SetFlag -> GotFlag (since SetFlag always returns 1, this is nonsence in an if() statement). Also add test-case, showing that it was actually wrong, in behavior too. 2023-01-31 07:49:16 +00:00
dgp 58446472bb merge 8.7 2023-01-30 15:57:39 +00:00
dgp d3dae9eba4 silence compiler warning 2023-01-30 15:37:41 +00:00
pooryorick 8c0f76a7de A few more readability changes to Tcl_UniCharToUtf()
jn: Please, don't do that here. Tcl_UniCharToUtf() is shared between 8.6, 8.7 and 9.0. So if you want to make it easier to read, it should be done on all 3 branches. I know you only care about "trunk", but it makes maintenance on 8.6/8.7/9.0 harder than it already is. I don't want to spend time on reviewing such kind of changes, and no-one else is doing it. Thanks for understanding (I hope)!
2023-01-30 11:59:41 +00:00
pooryorick 4d235ca93a Make Tcl_UniCharToUtf() a little easier to read. 2023-01-30 11:22:28 +00:00
jan.nijtmans 5b86b255d4 Another situation where TCL_COMBINE handling gives a strange result (utf-32 encoder) 2023-01-28 20:50:36 +00:00
jan.nijtmans 468b1a4346 Fix "format %c 0x10000041", should give the same answer as in Tcl 8.6 (Handling of TCL_COMBINE flag should not be visible at script level) 2023-01-28 18:50:32 +00:00
pooryorick 7f87f0f8ea Add some comments and tidy code. 2023-01-27 19:15:09 +00:00
jan.nijtmans 5d13f6b527 Merge 8.7 2023-01-27 15:10:36 +00:00
jan.nijtmans 0318ff75d9 Fix off-by-one error in tclCmdAH.c, with testcases showing that it works now. 2023-01-27 14:48:37 +00:00
jan.nijtmans 06de3a9ba1 new testcase encoding-18.1. Testcase cleanup 2023-01-27 14:23:08 +00:00
jan.nijtmans d838764849 Update fcopy documentation regarding -size argument 2023-01-27 08:20:57 +00:00
jan.nijtmans 8ea5f2cfce Update fcopy documentation regarding -size argument 2023-01-27 08:17:34 +00:00
pooryorick 23e46e5885 Merge 8.7 2023-01-27 00:46:36 +00:00
pooryorick d271c9f407 Fix for [ee08ed090b0a5408], sporadic segmentation fault in
coroutine.test/coroutine-7.4.
2023-01-26 23:55:30 +00:00
jan.nijtmans 97041036d3 Merge 8.7 2023-01-24 20:05:00 +00:00
82 changed files with 2289 additions and 1085 deletions
+61 -24
View File
@@ -8,7 +8,7 @@
.so man.macros
.BS
.SH NAME
Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternal, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath, Tcl_GetDefaultEncodingDir, Tcl_SetDefaultEncodingDir \- procedures for creating and using encodings
Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_UtfToExternalDStringEx, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternalDStringEx, Tcl_UtfToExternal, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath, Tcl_GetDefaultEncodingDir, Tcl_SetDefaultEncodingDir \- procedures for creating and using encodings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -26,13 +26,13 @@ char *
\fBTcl_ExternalToUtfDString\fR(\fIencoding, src, srcLen, dstPtr\fR)
.sp
int
\fBTcl_ExternalToUtfDStringEx\fR(\fIencoding, src, srcLen, flags, dstPtr\fR)
\fBTcl_ExternalToUtfDStringEx\fR(\fIinterp, encoding, src, srcLen, flags, dstPtr, errorIdxPtr\fR)
.sp
char *
\fBTcl_UtfToExternalDString\fR(\fIencoding, src, srcLen, dstPtr\fR)
.sp
int
\fBTcl_UtfToExternalDStringEx\fR(\fIencoding, src, srcLen, flags, dstPtr\fR)
\fBTcl_UtfToExternalDStringEx\fR(\fIinterp, encoding, src, srcLen, flags, dstPtr, errorIdxPtr\fR)
.sp
int
\fBTcl_ExternalToUtf\fR(\fIinterp, encoding, src, srcLen, flags, statePtr,
@@ -105,7 +105,7 @@ encoding-specific length of the string is used.
Pointer to an uninitialized or free \fBTcl_DString\fR in which the converted
result will be stored.
.AP int flags in
Various flag bits OR-ed together.
This is a bit mask passed in to control the operation of the encoding functions.
\fBTCL_ENCODING_START\fR signifies that the
source buffer is the first block in a (potentially multi-block) input
stream, telling the conversion routine to reset to an initial state and
@@ -113,16 +113,15 @@ perform any initialization that needs to occur before the first byte is
converted. \fBTCL_ENCODING_END\fR signifies that the source buffer is the last
block in a (potentially multi-block) input stream, telling the conversion
routine to perform any finalization that needs to occur after the last
byte is converted and then to reset to an initial state.
\fBTCL_ENCODING_STOPONERROR\fR signifies that the conversion routine should
return immediately upon reading a source character that does not exist in
the target encoding; otherwise a default fallback character will
automatically be substituted. The flag \fBTCL_ENCODING_STRICT\fR makes the
encoder/decoder more strict in what it considers to be an invalid byte
sequence. The flag \fBTCL_ENCODING_NOCOMPLAIN\fR has
no effect, it is reserved for Tcl 9.0. The flag \fBTCL_ENCODING_MODIFIED\fR makes
\fBTcl_UtfToExternalDStringEx\fR and \fBTcl_UtfToExternal\fR produce the
byte sequence \exC0\ex80 in stead of \ex00, for the utf-8/cesu-8 encoders.
byte is converted and then to reset to an initial state. The
\fBTCL_PROFILE_*\fR bits defined in the \fBPROFILES\fR section below
control the encoding profile to be used for dealing with invalid data or
other errors in the encoding transform.
\fBTCL_ENCODING_STOPONERROR\fR is present for backward compatibility with
Tcl 8.6 and forces the encoding profile to \fBstrict\fR.
Some flags bits may not be usable with some functions as noted in the
function descriptions below.
.AP Tcl_EncodingState *statePtr in/out
Used when converting a (generally long or indefinite length) byte stream
in a piece-by-piece fashion. The conversion routine stores its current
@@ -148,6 +147,9 @@ buffer as a result of the conversion. May be NULL.
.AP int *dstCharsPtr out
Filled with the number of characters that correspond to the number of bytes
stored in the output buffer. May be NULL.
.AP Tcl_Size *errorIdxPtr out
Filled with the index of the byte or character that caused the encoding transform
to fail. May be NULL.
.AP Tcl_DString *bufPtr out
Storage for the prescribed system encoding name.
.AP "const Tcl_EncodingType" *typePtr in
@@ -221,11 +223,30 @@ call \fBTcl_DStringFree\fR to free any information stored in \fIdstPtr\fR.
When converting, if any of the characters in the source buffer cannot be
represented in the target encoding, a default fallback character will be
used. The return value is a pointer to the value stored in the DString.
.PP
\fBTcl_ExternalToUtfDStringEx\fR is the same as \fBTcl_ExternalToUtfDString\fR,
but it has an additional flags parameter. The return value is the index of
the first byte in the input string causing a conversion error.
Or TCL_INDEX_NONE if all is OK.
\fBTcl_ExternalToUtfDStringEx\fR is a more flexible version of older
\fBTcl_ExternalToUtfDString\fR function. It takes three additional parameters,
\fBinterp\fR, \fBflags\fR and \fBerrorIdxPtr\fR. The \fBflags\fR parameter may
be used to specify the profile to be used for the transform. The
\fBTCL_ENCODING_START\fR and \fBTCL_ENCODING_END\fR bits in \fBflags\fR are
ignored as the function assumes the entire source string to be decoded is passed
into the function. On success, the function returns \fBTCL_ERROR\fR with the
converted string stored in \fB*dstPtr\fR. For errors other than conversion
errors, such as invalid flags, the function returns \fBTCL_OK\fR with an error
message in \fBinterp\fR if it is not NULL.
For conversion errors, \fBTcl_ExternalToUtfDStringEx\fR returns one
of the \fBTCL_CONVERT_*\fR errors listed below for \fBTcl_ExternalToUtf\fR.
When one of these conversion errors is returned, an error message is
stored in \fBinterp\fR only if \fBerrorIdxPtr\fR is NULL. Otherwise, no error message
is stored as the function expects the caller is interested whatever is
decoded to that point and not treating this as an immediate error condition.
The index of the error location is stored in \fB*errorIdxPtr\fR.
The caller must call \fBTcl_DStringFree\fR to free up the \fB*dstPtr\fR resources
irrespective of the return value from the function.
.PP
\fBTcl_ExternalToUtf\fR converts a source buffer \fIsrc\fR from the specified
\fIencoding\fR into UTF-8. Up to \fIsrcLen\fR bytes are converted from the
@@ -248,12 +269,12 @@ the unconverted bytes that remained in \fIsrc\fR plus some further bytes
from the source stream to properly convert the formerly split-up multibyte
sequence.
.IP \fBTCL_CONVERT_SYNTAX\fR 29
The source buffer contained an invalid character sequence. This may occur
The source buffer contained an invalid byte or character sequence. This may occur
if the input stream has been damaged or if the input encoding method was
misidentified.
.IP \fBTCL_CONVERT_UNKNOWN\fR 29
The source buffer contained a character that could not be represented in
the target encoding and \fBTCL_ENCODING_STOPONERROR\fR was specified.
the target encoding.
.RE
.LP
\fBTcl_UtfToExternalDString\fR converts a source buffer \fIsrc\fR from UTF-8
@@ -265,10 +286,14 @@ characters in the source buffer cannot be represented in the target
encoding, a default fallback character will be used. The return value is
a pointer to the value stored in the DString.
.PP
\fBTcl_UtfToExternalDStringEx\fR is the same as \fBTcl_UtfToExternalDString\fR,
but it has an additional flags parameter. The return value is the index of
the first byte of an utf-8 byte-sequence in the input string causing a
conversion error. Or TCL_INDEX_NONE if all is OK.
\fBTcl_UtfToExternalDStringEx\fR is an enhanced version of
\fBTcl_UtfToExternalDString\fR that transforms UTF-8 encoded source data to a specified
\fIencoding\fR. Except for the direction of the transform, the parameters and
return values are identical to those of \fBTcl_ExternalToUtfDStringEx\fR. See
that function above for details about the same.
Irrespective of the return code from the function, the caller must free
resources associated with \fB*dstPtr\fR when the function returns.
.PP
\fBTcl_UtfToExternal\fR converts a source buffer \fIsrc\fR from UTF-8 into
the specified \fIencoding\fR. Up to \fIsrcLen\fR bytes are converted from
@@ -592,6 +617,18 @@ to the object, it will be deleted.
.PP
\fBTcl_GetEncodingSearchPath\fR returns an object with a reference count of at
least 1.
.SH "PROFILES"
Encoding profiles define the manner in which errors in the encoding transforms
are handled by the encoding functions. An application can specify the profile
to be used by OR-ing the \fBflags\fR parameter passed to the function
with at most one of \fBTCL_ENCODING_PROFILE_TCL8\fR,
\fBTCL_ENCODING_PROFILE_STRICT\fR or \fBTCL_ENCODING_PROFILE_REPLACE\fR.
These correspond to the \fBtcl8\fR, \fBstrict\fR and \fBreplace\fR profiles
respectively. If none are specified, a version-dependent default profile is used.
For Tcl 8.7, the default profile is \fBtcl8\fR.
For details about profiles, see the \fBPROFILES\fR section in
the documentation of the \fBencoding\fR command.
.SH "SEE ALSO"
encoding(n)
.SH KEYWORDS
+126 -202
View File
@@ -1,6 +1,7 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2023 Nathan Coulter
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -16,176 +17,152 @@ Summary of Tcl language syntax.
.SH DESCRIPTION
.PP
The following rules define the syntax and semantics of the Tcl language:
.IP "[1] \fBCommands.\fR"
A Tcl script is a string containing one or more commands.
Semi-colons and newlines are command separators unless quoted as
described below.
Close brackets are command terminators during command substitution
(see below) unless quoted.
.IP "[2] \fBEvaluation.\fR"
A command is evaluated in two steps.
First, the Tcl interpreter breaks the command into \fIwords\fR
and performs substitutions as described below.
These substitutions are performed in the same way for all
commands.
Secondly, the first word is used to locate a routine to
carry out the command, and the remaining words of the command are
passed to that routine.
The routine is free to interpret each of its words
in any way it likes, such as an integer, variable name, list,
or Tcl script.
Different commands interpret their words differently.
.IP "[3] \fBWords.\fR"
Words of a command are separated by white space (except for
newlines, which are command separators).
.IP "[4] \fBDouble quotes.\fR"
If the first character of a word is double-quote
.PQ \N'34'
then the word is terminated by the next double-quote character.
If semi-colons, close brackets, or white space characters
(including newlines) appear between the quotes then they are treated
as ordinary characters and included in the word.
Command substitution, variable substitution, and backslash substitution
are performed on the characters between the quotes as described below.
The double-quotes are not retained as part of the word.
.IP "[5] \fBArgument expansion.\fR"
If a word starts with the string
.QW {*}
followed by a non-whitespace character, then the leading
.QW {*}
is removed and the rest of the word is parsed and substituted as any other
word. After substitution, the word is parsed as a list (without command or
variable substitutions; backslash substitutions are performed as is normal for
a list and individual internal words may be surrounded by either braces or
double-quote characters), and its words are added to the command being
substituted. For instance,
.QW "cmd a {*}{b [c]} d {*}{$e f {g h}}"
is equivalent to
.QW "cmd a b {[c]} d {$e} f {g h}" .
.IP "[6] \fBBraces.\fR"
If the first character of a word is an open brace
.
.IP "[1] \fBScript.\fR"
A script is composed of zero or more commands delimited by semi-colons or
newlines.
.IP "[2] \fBCommand.\fR"
A command is composed of zero or more words delimited by whitespace. The
replacement for a substitution is included verbatim in the word. For example, a
space in the replacement is included in the word rather than becoming a
delimiter, and \fI\\\\\fR becomes a single backslash in the word. Each word is
processed from left to right and each substitution is performed as soon as it
is complete.
For example, the command
.RS
.PP
.CS
set y [set x 0][incr x][incr x]
.CE
.PP
is composed of three words, and sets the value of \fIy\fR to \fI012\fR.
.PP
If hash
.PQ #
is the first character of what would otherwise be the first word of a command,
all characters up to the next newline are ignored.
.RE
.
.IP "[3] \fBBraced word.\fR"
If a word is enclosed in braces
.PQ {
and rule [5] does not apply, then
the word is terminated by the matching close brace
.PQ } "" .
Braces nest within the word: for each additional open
brace there must be an additional close brace (however,
if an open brace or close brace within the word is
quoted with a backslash then it is not counted in locating the
matching close brace).
No substitutions are performed on the characters between the
braces except for backslash-newline substitutions described
below, nor do semi-colons, newlines, close brackets,
or white space receive any special interpretation.
The word will consist of exactly the characters between the
outer braces, not including the braces themselves.
.IP "[7] \fBCommand substitution.\fR"
If a word contains an open bracket
and
.PQ } ""
, the braces are removed and the enclosed characters become the word. No
substitutions are performed. Nested pairs of braces may occur within the word.
A brace preceded by an odd number of backslashes is not considered part of a
pair, and neither brace nor the backslashes are removed from the word.
.
.IP "[4] \fBQuoted word.\fR"
If a word is enclosed in double quotes
.PQ \N'34'
, the double quotes are removed and the enclosed characters become the word.
Substitutions are performed.
.
.IP "[5] \fBList.\fR"
A list has the form of a single command. Newline is whitespace, and semicolon
has no special interpretation. There is no script evaluation so there is no
argument expansion, variable substitution, or command substitution: Dollar-sign
and open bracket have no special interpretation, and what would be argument
expansion in a script is invalid in a list.
.
.IP "[6] \fBArgument expansion.\fR"
If
.QW {*}
prefixes a word, it is removed. After any remaining enclosing braces or quotes
are processed and applicable substitutions performed, the word, which must
be a list, is removed from the command, and in its place each word in the
list becomes an additional word in the command. For example,
.CS
cmd a {*}{b [c]} d {*}{$e f {g h}}
.CE
is equivalent to
.CS
cmd a b {[c]} d {$e} f {g h} .
.CE
.
.IP "[7] \fBEvaluation.\fR"
To evaluate a script, an interpreter evaluates each successive command. The
first word identifies a procedure, and the remaining words are passed to that
procedure for further evaluation. The procedure interprets each argument in
its own way, e.g. as an integer, variable name, list, mathematical expression,
script, or in some other arbitrary way. The result of the last command is the
result of the script.
.
.IP "[8] \fBCommand substitution.\fR"
Each pair of brackets
.PQ [
then Tcl performs \fIcommand substitution\fR.
To do this it invokes the Tcl interpreter recursively to process
the characters following the open bracket as a Tcl script.
The script may contain any number of commands and must be terminated
by a close bracket
.PQ ] "" .
The result of the script (i.e. the result of its last command) is
substituted into the word in place of the brackets and all of the
characters between them.
There may be any number of command substitutions in a single word.
Command substitution is not performed on words enclosed in braces.
.IP "[8] \fBVariable substitution.\fR"
If a word contains a dollar-sign
and
.PQ ] ""
encloses a script and is replaced by the result of that script.
.IP "[9] \fBVariable substitution.\fR"
Each of the following forms begins with dollar sign
.PQ $
followed by one of the forms
described below, then Tcl performs \fIvariable
substitution\fR: the dollar-sign and the following characters are
replaced in the word by the value of a variable.
Variable substitution may take any of the following forms:
and is replaced by the value of the identified variable. \fIname\fR names the
variable and is composed of ASCII letters (\fBA\fR\(en\fBZ\fR and
\fBa\fR\(en\fBz\fR), digits (\fB0\fR\(en\fB9\fR), underscores, or namespace
delimiters (two or more colons). \fIindex\fR is the name of an individual
variable within an array variable, and may be empty.
.RS
.TP 15
\fB$\fIname\fR
.
\fIName\fR is the name of a scalar variable; the name is a sequence
of one or more characters that are a letter, digit, underscore,
or namespace separators (two or more colons).
Letters and digits are \fIonly\fR the standard ASCII ones (\fB0\fR\(en\fB9\fR,
\fBA\fR\(en\fBZ\fR and \fBa\fR\(en\fBz\fR).
\fIname\fR may not be empty.
.TP 15
\fB$\fIname\fB(\fIindex\fB)\fR
.
\fIName\fR gives the name of an array variable and \fIindex\fR gives
the name of an element within that array.
\fIName\fR must contain only letters, digits, underscores, and
namespace separators, and may be an empty string.
Letters and digits are \fIonly\fR the standard ASCII ones (\fB0\fR\(en\fB9\fR,
\fBA\fR\(en\fBZ\fR and \fBa\fR\(en\fBz\fR).
Command substitutions, variable substitutions, and backslash
substitutions are performed on the characters of \fIindex\fR.
\fIname\fR may be empty. Substitutions are performed on \fIindex\fR.
.TP 15
\fB${\fIname\fB}\fR
\fIname\fR may be empty.
.TP 15
\fB${\fIname(index)\fB}\fR
.
\fIName\fR is the name of a scalar variable or array element. It may contain
any characters whatsoever except for close braces. It indicates an array
element if \fIname\fR is in the form
.QW \fIarrayName\fB(\fIindex\fB)\fR
where \fIarrayName\fR does not contain any open parenthesis characters,
.QW \fB(\fR ,
or close brace characters,
.QW \fB}\fR ,
and \fIindex\fR can be any sequence of characters except for close brace
characters. No further
substitutions are performed during the parsing of \fIname\fR.
.PP
There may be any number of variable substitutions in a single word.
Variable substitution is not performed on words enclosed in braces.
.PP
Note that variables may contain character sequences other than those listed
above, but in that case other mechanisms must be used to access them (e.g.,
via the \fBset\fR command's single-argument form).
\fIname\fR may be empty. No substitutions are performed.
.RE
.IP "[9] \fBBackslash substitution.\fR"
If a backslash
Variables that are not accessible through one of the forms above may be
accessed through other mechanisms, e.g. the \fBset\fR command.
.IP "[10] \fBBackslash substitution.\fR"
Each backslash
.PQ \e
appears within a word then \fIbackslash substitution\fR occurs.
In all cases but those described below the backslash is dropped and
the following character is treated as an ordinary
character and included in the word.
This allows characters such as double quotes, close brackets,
and dollar signs to be included in words without triggering
special processing.
The following table lists the backslash sequences that are
handled specially, along with the value that replaces each sequence.
that is not part of one of the forms listed below is removed, and the next
character is included in the word verbatim, which allows the inclusion of
characters that would normally be interpreted, namely whitespace, braces,
brackets, double quote, dollar sign, and backslash. The following sequences
are replaced as described:
.RS
.RS
.RS
.TP 7
\e\fBa\fR
Audible alert (bell) (Unicode U+000007).
Audible alert (bell) (U+7).
.TP 7
\e\fBb\fR
Backspace (Unicode U+000008).
Backspace (U+8).
.TP 7
\e\fBf\fR
Form feed (Unicode U+00000C).
Form feed (U+C).
.TP 7
\e\fBn\fR
Newline (Unicode U+00000A).
Newline (U+A).
.TP 7
\e\fBr\fR
Carriage-return (Unicode U+00000D).
Carriage-return (U+D).
.TP 7
\e\fBt\fR
Tab (Unicode U+000009).
Tab (U+9).
.TP 7
\e\fBv\fR
Vertical tab (Unicode U+00000B).
Vertical tab (U+B).
.TP 7
\e\fB<newline>\fIwhiteSpace\fR
.
A single space character replaces the backslash, newline, and all spaces
and tabs after the newline. This backslash sequence is unique in that it
is replaced in a separate pre-pass before the command is actually parsed.
This means that it will be replaced even when it occurs between braces,
and the resulting space will be treated as a word separator if it is not
in braces or quotes.
Newline preceded by an odd number of backslashes, along with the consecutive
spaces and tabs that immediately follow it, is replaced by a single space.
Because this happens before the command is split into words, it occurs even
within braced words, and if the resulting space may subsequently be treated as
a word delimiter.
.TP 7
\e\e
Backslash
@@ -193,83 +170,30 @@ Backslash
.TP 7
\e\fIooo\fR
.
The digits \fIooo\fR (one, two, or three of them) give a eight-bit octal
value for the Unicode character that will be inserted, in the range
\fI000\fR\(en\fI377\fR (i.e., the range U+000000\(enU+0000FF).
The parser will stop just before this range overflows, or when
the maximum of three digits is reached. The upper bits of the Unicode
character will be 0.
Up to three octal digits form an eight-bit value for a Unicode character in the
range \fI0\fR\(en\fI377\fR, i.e. U+0\(enU+FF. Only the digits that result in a
number in this range are consumed.
.TP 7
\e\fBx\fIhh\fR
.
The hexadecimal digits \fIhh\fR (one or two of them) give an eight-bit
hexadecimal value for the Unicode character that will be inserted. The upper
bits of the Unicode character will be 0 (i.e., the character will be in the
range U+000000\(enU+0000FF).
Up to two hexadecimal digits form an eight-bit value for a Unicode character in
the range \fI0\fR\(en\fIFF\fR.
.TP 7
\e\fBu\fIhhhh\fR
.
The hexadecimal digits \fIhhhh\fR (one, two, three, or four of them) give a
sixteen-bit hexadecimal value for the Unicode character that will be
inserted. The upper bits of the Unicode character will be 0 (i.e., the
character will be in the range U+000000\(enU+00FFFF).
Up to four hexadecimal digits form a 16-bit value for a Unicode character in
the range \fI0\fR\(en\fIFFFF\fR.
.TP 7
\e\fBU\fIhhhhhhhh\fR
.
The hexadecimal digits \fIhhhhhhhh\fR (one up to eight of them) give a
twenty-one-bit hexadecimal value for the Unicode character that will be
inserted, in the range U+000000\(enU+10FFFF. The parser will stop just
before this range overflows, or when the maximum of eight digits
is reached. The upper bits of the Unicode character will be 0.
.RS
.PP
The range U+00D800\(enU+00DFFF is reserved for surrogates, which
are illegal on their own. Therefore, such sequences will result in
the replacement character U+FFFD. Surrogate pairs should be
encoded as single \e\fBU\fIhhhhhhhh\fR character.
Up to eight hexadecimal digits form a 21-bit value for a Unicode character in
the range \fI0\fR\(en\fI10FFFF\fR. Only the digits that result in a number in
this range are consumed.
.RE
.RE
.PP
Backslash substitution is not performed on words enclosed in braces,
except for backslash-newline as described above.
.RE
.IP "[10] \fBComments.\fR"
If a hash character
.PQ #
appears at a point where Tcl is
expecting the first character of the first word of a command,
then the hash character and the characters that follow it, up
through the next newline, are treated as a comment and ignored.
The comment character only has significance when it appears
at the beginning of a command.
.IP "[11] \fBOrder of substitution.\fR"
Each character is processed exactly once by the Tcl interpreter
as part of creating the words of a command.
For example, if variable substitution occurs then no further
substitutions are performed on the value of the variable; the
value is inserted into the word verbatim.
If command substitution occurs then the nested command is
processed entirely by the recursive call to the Tcl interpreter;
no substitutions are performed before making the recursive
call and no additional substitutions are performed on the result
of the nested script.
.RS
.PP
Substitutions take place from left to right, and each substitution is
evaluated completely before attempting to evaluate the next. Thus, a
sequence like
.PP
.CS
set y [set x 0][incr x][incr x]
.CE
.PP
will always set the variable \fIy\fR to the value, \fI012\fR.
.RE
.IP "[12] \fBSubstitution and word boundaries.\fR"
Substitutions do not affect the word boundaries of a command,
except for argument expansion as specified in rule [5].
For example, during variable substitution the entire value of
the variable becomes part of a single word, even if the variable's
value contains spaces.
.
.SH KEYWORDS
backslash, command, comment, script, substitution, variable
'\" Local Variables:
+10
View File
@@ -156,6 +156,16 @@ applied to input only.
The default value is the empty string, except that under Windows the default
value for reading is Control-z (\ex1A). The acceptable range is \ex01 -
\ex7f. A value outside this range results in an error.
.VS "TCL8.7 TIP656"
.TP
\fB\-profile\fR \fIprofile\fR
.
Specifies the encoding profile to be used on the channel. The encoding
transforms in use for the channel's input and output will then be subject to the
rules of that profile. Any failures will result in a channel error. See
\fBPROFILES\fR in the \fBencoding(n)\fR documentation for details about encoding
profiles.
.VE "TCL8.7 TIP656"
.TP
\fB\-translation\fR \fItranslation\fR
.TP
+146 -93
View File
@@ -28,73 +28,41 @@ formats.
Performs one of several encoding related operations, depending on
\fIoption\fR. The legal \fIoption\fRs are:
.TP
\fBencoding convertfrom\fR ?\fB-strict\fR? ?\fB-failindex var\fR? ?\fIencoding\fR? \fIdata\fR
\fBencoding convertfrom\fR \fB-nocomplain\fR ?\fIencoding\fR? \fIdata\fR
.
Convert \fIdata\fR to a Unicode string from the specified \fIencoding\fR. The
characters in \fIdata\fR are 8 bit binary data. The resulting
sequence of bytes is a string created by applying the given \fIencoding\fR
to the data. If \fIencoding\fR is not specified, the current
system encoding is used.
.VS "TCL8.7 TIP346, TIP607, TIP601"
.PP
.RS
The command does not fail on encoding errors. Instead, any not convertable bytes
(like incomplete UTF-8 sequences, see example below) are put as byte values into
the output stream.
.PP
If the option \fB-failindex\fR with a variable name is given, the error reporting
is changed in the following manner:
in case of a conversion error, the position of the input byte causing the error
is returned in the given variable. The return value of the command are the
converted characters until the first error position.
In case of no error, the value \fI-1\fR is written to the variable. This option
may not be used together with \fB-nocomplain\fR.
.PP
The option \fB-nocomplain\fR has no effect and is available for compatibility with
TCL 9. In TCL 9, the encoding command fails with an error on any encoding issue.
This switch restores the TCL8.7 behaviour.
.PP
The \fB-strict\fR option follows more strict rules in conversion. For the \fButf-8\fR
encoder, it disallows invalid byte sequences and surrogates (which -
otherwise - are just passed through). This option may not be used together
with \fB-nocomplain\fR.
.VE "TCL8.7 TIP346, TIP607, TIP601"
.RE
\fBencoding convertfrom\fR ?\fIencoding\fR? \fIdata\fR
.TP
\fBencoding convertto\fR ?\fB-strict\fR? ?\fB-failindex var\fR? ?\fIencoding\fR? \fIdata\fR
\fBencoding convertto\fR \fB-nocomplain\fR ?\fIencoding\fR? \fIdata\fR
\fBencoding convertfrom\fR ?\fB-profile \fIprofile\fR? ?\fB-failindex var\fR? \fIencoding\fR \fIdata\fR
.
Convert \fIstring\fR from Unicode to the specified \fIencoding\fR.
The result is a sequence of bytes that represents the converted
string. Each byte is stored in the lower 8-bits of a Unicode
character (indeed, the resulting string is a binary string as far as
Tcl is concerned, at least initially). If \fIencoding\fR is not
specified, the current system encoding is used.
.VS "TCL8.7 TIP346, TIP607, TIP601"
.PP
.RS
The command does not fail on encoding errors. Instead, the replacement character
\fB?\fR is output for any not representable character (like the dot \fB\\U2022\fR
in \fBiso-8859-1\fR encoding, see example below).
.PP
If the option \fB-failindex\fR with a variable name is given, the error reporting
is changed in the following manner:
in case of a conversion error, the position of the input character causing the error
is returned in the given variable. The return value of the command are the
converted bytes until the first error position. No error condition is raised.
In case of no error, the value \fI-1\fR is written to the variable. This option
may not be used together with \fB-nocomplain\fR.
.PP
The option \fB-nocomplain\fR has no effect and is available for compatibility with
TCL 9. In TCL 9, the encoding command fails with an error on any encoding issue.
This switch restores the TCL8.7 behaviour.
.PP
The \fB-strict\fR option follows more strict rules in conversion. For the \fButf-8\fR
encoder, it disallows surrogates (which - otherwise - are just passed through). This
option may not be used together with \fB-nocomplain\fR.
.VE "TCL8.7 TIP346, TIP607, TIP601"
.RE
Converts \fIdata\fR, which should be in binary string encoded as per
\fIencoding\fR, to a Tcl string. If \fIencoding\fR is not specified, the current
system encoding is used.
.VS "TCL8.7 TIP607, TIP656"
The \fB-profile\fR option determines the command behavior in the presence
of conversion errors. See \fBPROFILES\fR for details. Any premature
termination of processing due to errors is reported through an exception if
the \fB-failindex\fR option is not specified.
If the \fB-failindex\fR is specified, instead of an exception being raised
on premature termination, the result of the conversion up to the point of the
error is returned as the result of the command. In addition, the index
of the source byte triggering the error is stored in \fBvar\fR. If no
errors are encountered, the entire result of the conversion is returned and
the value \fB-1\fR is stored in \fBvar\fR.
.VE "TCL8.7 TIP607, TIP656"
.TP
\fBencoding convertto\fR ?\fIencoding\fR? \fIdata\fR
.TP
\fBencoding convertto\fR ?\fB-profile \fIprofile\fR? ?\fB-failindex var\fR? \fIencoding\fR \fIdata\fR
.
Convert \fIstring\fR to the specified \fIencoding\fR. The result is a Tcl binary
string that contains the sequence of bytes representing the converted string in
the specified encoding. If \fIencoding\fR is not specified, the current system
encoding is used.
.VS "TCL8.7 TIP607, TIP656"
The \fB-profile\fR and \fB-failindex\fR options have the same effect as
described for the \fBencoding convertfrom\fR command.
.VE "TCL8.7 TIP607, TIP656"
.TP
\fBencoding dirs\fR ?\fIdirectoryList\fR?
.
@@ -123,55 +91,140 @@ are guaranteed to be present in the list.
Set the system encoding to \fIencoding\fR. If \fIencoding\fR is
omitted then the command returns the current system encoding. The
system encoding is used whenever Tcl passes strings to system calls.
.SH EXAMPLE
.TP
.VS "TCL8.7 TIP656"
\fBencoding profiles\fR
Returns a list of the names of encoding profiles. See \fBPROFILES\fR below.
.VE "TCL8.7 TIP656"
\" Do not put .VS on whole section as that messes up the bullet list alignment
.SH PROFILES
.PP
.VS "TCL8.7 TIP656"
Operations involving encoding transforms may encounter several types of
errors such as invalid sequences in the source data, characters that
cannot be encoded in the target encoding and so on.
A \fIprofile\fR prescribes the strategy for dealing with such errors
in one of two ways:
.VE "TCL8.7 TIP656"
.
.IP \(bu
.VS "TCL8.7 TIP656"
Terminating further processing of the source data. The profile does not
determine how this premature termination is conveyed to the caller. By default,
this is signalled by raising an exception. If the \fB-failindex\fR option
is specified, errors are reported through that mechanism.
.VE "TCL8.7 TIP656"
.IP \(bu
.VS "TCL8.7 TIP656"
Continue further processing of the source data using a fallback strategy such
as replacing or discarding the offending bytes in a profile-defined manner.
.VE "TCL8.7 TIP656"
.PP
The following profiles are currently implemented with \fBtcl8\fR being
the default if the \fB-profile\fR is not specified.
.VS "TCL8.7 TIP656"
.TP
\fBtcl8\fR
.
The \fBtcl8\fR profile always follows the first strategy above and corresponds
to the behavior of encoding transforms in Tcl 8.6. When converting from an
external encoding \fBother than utf-8\fR to Tcl strings with the \fBencoding
convertfrom\fR command, invalid bytes are mapped to their numerically equivalent
code points. For example, the byte 0x80 which is invalid in ASCII would be
mapped to code point U+0080. When converting from \fButf-8\fR, invalid bytes
that are defined in CP1252 are mapped to their Unicode equivalents while those
that are not fall back to the numerical equivalents. For example, byte 0x80 is
defined by CP1252 and is therefore mapped to its Unicode equivalent U+20AC while
byte 0x81 which is not defined by CP1252 is mapped to U+0081. As an additional
special case, the sequence 0xC0 0x80 is mapped to U+0000.
When converting from Tcl strings to an external encoding format using
\fBencoding convertto\fR, characters that cannot be represented in the
target encoding are replaced by an encoding-dependent character, usually
the question mark \fB?\fR.
.TP
\fBstrict\fR
.
The \fBstrict\fR profile always stops processing when an conversion error is
encountered. The error is signalled via an exception or the \fB-failindex\fR
option mechanism. The \fBstrict\fR profile implements a Unicode standard
conformant behavior.
.TP
\fBreplace\fR
.
Like the \fBtcl8\fR profile, the \fBreplace\fR profile always continues
processing on conversion errors but follows a Unicode standard conformant
method for error handling.
When converting an encoded byte sequence to a Tcl string using
\fBencoding convertfrom\fR, invalid bytes
are replaced by the U+FFFD REPLACEMENT CHARACTER code point.
When encoding a Tcl string with \fBencoding convertto\fR,
code points that cannot be represented in the
target encoding are transformed to an encoding-specific fallback character,
U+FFFD REPLACEMENT CHARACTER for UTF targets and generally `?` for other
encodings.
.VE "TCL8.7 TIP656"
.SH EXAMPLES
.PP
These examples use the utility proc below that prints the Unicode code points
comprising a Tcl string.
.PP
.CS
proc codepoints {s} {join [lmap c [split $s ""] {
string cat U+ [format %.6X [scan $c %c]]}]
}
.CE
.PP
Example 1: convert a byte sequence in Japanese euc-jp encoding to a TCL string:
.PP
.CS
set s [\fBencoding convertfrom\fR euc-jp "\exA4\exCF"]
% codepoints [\fBencoding convertfrom\fR euc-jp "\exA4\exCF"]
U+00306F
.CE
.PP
The result is the unicode codepoint:
The result is the unicode codepoint
.QW "\eu306F" ,
which is the Hiragana letter HA.
.VS "TCL8.7 TIP346, TIP607, TIP601"
.VS "TCL8.7 TIP607, TIP656"
.PP
Example 2: detect the error location in an incomplete UTF-8 sequence:
Example 2: Error handling based on profiles:
.PP
The letter \fBA\fR is Unicode character U+0041 and the byte "\ex80" is invalid
in ASCII encoding.
.CS
% set s [\fBencoding convertfrom\fR -failindex i utf-8 "A\exC3"]
A
% set i
1
.PP
% codepoints [encoding convertfrom -profile tcl8 ascii A\ex80]
U+000041 U+000080
% codepoints [encoding convertfrom -profile replace ascii A\ex80]
U+000041 U+00FFFD
% codepoints [encoding convertfrom -profile strict ascii A\ex80]
unexpected byte sequence starting at index 1: '\ex80'
.CE
.PP
Example 3: return the incomplete UTF-8 sequence by raw bytes:
Example 3: Get partial data and the error location:
.PP
.CS
% set s [\fBencoding convertfrom\fR -nocomplain utf-8 "A\exC3"]
.CE
The result is "A" followed by the byte \exC3. The option \fB-nocomplain\fR
has no effect, but assures to get the same result with TCL9.
.PP
Example 4: detect the error location while transforming to ISO8859-1
(ISO-Latin 1):
.PP
.CS
% set s [\fBencoding convertto\fR -failindex i utf-8 "A\eu0141"]
A
% set i
1
% codepoints [encoding convertfrom -profile strict -failindex idx ascii AB\ex80]
U+000041 U+000042
% set idx
2
.CE
.PP
Example 5: replace a not representable character by the replacement character:
Example 4: Encode a character that is not representable in ISO8859-1:
.PP
.CS
% set s [\fBencoding convertto\fR -nocomplain utf-8 "A\eu0141"]
% encoding convertto iso8859-1 A\eu0141
A?
% encoding convertto -profile strict iso8859-1 A\eu0141
unexpected character at index 1: 'U+000141'
% encoding convertto -profile strict -failindex idx iso8859-1 A\eu0141
A
% set idx
1
.CE
The option \fB-nocomplain\fR has no effect, but assures to get the same result
with TCL9.
.VE "TCL8.7 TIP346, TIP607, TIP601"
.VE "TCL8.7 TIP607, TIP656"
.PP
.SH "SEE ALSO"
Tcl_GetEncoding(3), fconfigure(n)
+10 -27
View File
@@ -101,8 +101,6 @@ locale-dependent system encoding used for interfacing with the operating
system, as returned by \fBencoding system\fR.
.RE
.TP
\fB\-eofchar\fR \fIchar\fR
.TP
\fB\-eofchar\fR \fB{\fIchar outChar\fB}\fR
.
This option supports DOS file systems that use Control-z (\ex1A) as an
@@ -122,31 +120,16 @@ reading and the empty string for writing.
The acceptable range for \fB\-eofchar\fR values is \ex01 - \ex7F;
attempting to set \fB\-eofchar\fR to a value outside of this range will
generate an error.
.VS "TCL8.7 TIP633"
.VS "TCL8.7 TIP656"
.TP
\fB\-nocomplainencoding\fR \fIbool\fR
\fB\-profile\fR \fIprofile\fR
.
Reporting mode of encoding errors.
If set to a \fItrue\fR value, encoding errors are resolved by a replacement
character (output) or verbatim bytes (input). No error is thrown.
This is the only available mode in Tcl 8.7.
.RS
.PP
Starting from TCL 9.0, this value may be set to a \fIfalse\fR value to throw errors
in case of encoding errors.
.RE
.VE "TCL8.7 TIP633"
.VS "TCL8.7 TIP346"
.TP
\fB\-strictencoding\fR \fIbool\fR
.
Activate additional stricter encoding application rules.
Default value is \fIfalse\fR.
.RS
.PP
See the \fI\-strict\fR option of the \fBencoding\fR command for more information.
.VE "TCL8.7 TIP346"
.RE
Specifies the encoding profile to be used on the channel. The encoding
transforms in use for the channel's input and output will then be subject to the
rules of that profile. Any failures will result in a channel error. See
\fBPROFILES\fR in the \fBencoding(n)\fR documentation for details about encoding
profiles.
.VE "TCL8.7 TIP656"
.TP
\fB\-translation\fR \fImode\fR
.TP
@@ -303,11 +286,11 @@ set data [read $f $numDataBytes]
close $f
.CE
.SH "SEE ALSO"
close(n), flush(n), gets(n), open(n), puts(n), read(n), socket(n),
close(n), encoding(n), flush(n), gets(n), open(n), puts(n), read(n), socket(n),
Tcl_StandardChannels(3)
.SH KEYWORDS
blocking, buffering, carriage return, end of line, flushing, linemode,
newline, nonblocking, platform, translation, encoding, filter, byte array,
newline, nonblocking, platform, profile, translation, encoding, filter, byte array,
binary
'\" Local Variables:
'\" mode: nroff
+3 -2
View File
@@ -26,8 +26,9 @@ network sockets.
The \fBfcopy\fR
command transfers data from \fIinchan\fR until end of file
or \fIsize\fR bytes or characters have been
transferred; \fIsize\fR is in bytes if the two channels are using the
same encoding, and is in characters otherwise.
transferred; \fIsize\fR is in bytes if the input channel is in binary mode,
or if the two channels are using the same encoding and -strict is not specified.
Otherwise, size is in characters.
If no \fB\-size\fR argument is given,
then the copy goes until end of file.
All the data read from \fIinchan\fR is copied to \fIoutchan\fR.
+3 -1
View File
@@ -9716,6 +9716,7 @@ TclNRYieldToObjCmd(
*/
iPtr->execEnvPtr = corPtr->callerEEPtr;
/* Not calling Tcl_IncrRefCount(listPtr) here because listPtr is private */
TclSetTailcall(interp, listPtr);
corPtr->yieldPtr = listPtr;
iPtr->execEnvPtr = corPtr->eePtr;
@@ -9918,8 +9919,8 @@ TclNRCoroutineActivateCallback(
if (corPtr->yieldPtr) {
for (runPtr = TOP_CB(interp); runPtr; runPtr = runPtr->nextPtr) {
if (runPtr->data[1] == corPtr->yieldPtr) {
Tcl_DecrRefCount((Tcl_Obj *)runPtr->data[1]);
runPtr->data[1] = NULL;
Tcl_DecrRefCount(corPtr->yieldPtr);
corPtr->yieldPtr = NULL;
break;
}
@@ -10520,6 +10521,7 @@ TclNRCoroutineObjCmd(
corPtr->running.lineLABCPtr = corPtr->lineLABCPtr;
corPtr->stackLevel = NULL;
corPtr->auxNumLevels = 0;
corPtr->yieldPtr = NULL;
/*
* Create the coro's execEnv, switch to it to push the exit and coro
+2 -2
View File
@@ -656,7 +656,7 @@ EncodingConvertfromObjCmd(
char buf[TCL_INTEGER_SPACE];
sprintf(buf, "%u", result);
Tcl_SetObjResult(interp, Tcl_ObjPrintf("unexpected byte sequence starting at index %"
"u: '\\x%X'", result, UCHAR(bytesPtr[result])));
"u: '\\x%02X'", result, UCHAR(bytesPtr[result])));
Tcl_SetErrorCode(interp, "TCL", "ENCODING", "ILLEGALSEQUENCE",
buf, NULL);
Tcl_DStringFree(&ds);
@@ -732,7 +732,7 @@ EncodingConverttoObjCmd(
if (objc == 2) {
encoding = Tcl_GetEncoding(interp, NULL);
data = objv[1];
} else if (objc > 2 && objc < 6) {
} else if (objc > 2 && objc < 7) {
int objcUnprocessed = objc;
data = objv[objc - 1];
stringPtr = Tcl_GetString(objv[1]);
+2 -2
View File
@@ -4317,14 +4317,14 @@ extern const TclStubs *tclStubsPtr;
/* Handle Win64 tk.dll being loaded in Cygwin64. */
# define Tcl_GetTime(t) \
do { \
union { \
struct { \
Tcl_Time now; \
long long reserved; \
} _t; \
_t.reserved = -1; \
tclStubsPtr->tcl_GetTime((&_t.now)); \
if (_t.reserved != -1) { \
_t.now.usec = _t.reserved; \
_t.now.usec = (long) _t.reserved; \
} \
*(t) = _t.now; \
} while (0)
+221 -84
View File
@@ -36,7 +36,7 @@ typedef struct {
* encoding is deleted. */
void *clientData; /* Arbitrary value associated with encoding
* type. Passed to conversion functions. */
int nullSize; /* Number of 0x00 bytes that signify
Tcl_Size nullSize; /* Number of 0x00 bytes that signify
* end-of-string in this encoding. This number
* is used to determine the source string
* length when the srcLen argument is
@@ -237,8 +237,13 @@ static Tcl_EncodingConvertProc Iso88591ToUtfProc;
*/
static const Tcl_ObjType encodingType = {
"encoding", FreeEncodingInternalRep, DupEncodingInternalRep, NULL, NULL
"encoding",
FreeEncodingInternalRep,
DupEncodingInternalRep,
NULL,
NULL
};
#define EncodingSetInternalRep(objPtr, encoding) \
do { \
Tcl_ObjInternalRep ir; \
@@ -369,7 +374,7 @@ int
Tcl_SetEncodingSearchPath(
Tcl_Obj *searchPath)
{
int dummy;
Tcl_Size dummy;
if (TCL_ERROR == TclListObjLengthM(NULL, searchPath, &dummy)) {
return TCL_ERROR;
@@ -416,7 +421,7 @@ void
TclSetLibraryPath(
Tcl_Obj *path)
{
int dummy;
Tcl_Size dummy;
if (TCL_ERROR == TclListObjLengthM(NULL, path, &dummy)) {
return;
@@ -452,7 +457,7 @@ TclSetLibraryPath(
static void
FillEncodingFileMap(void)
{
int i, numDirs = 0;
Tcl_Size i, numDirs = 0;
Tcl_Obj *map, *searchPath;
searchPath = Tcl_GetEncodingSearchPath();
@@ -461,13 +466,13 @@ FillEncodingFileMap(void)
map = Tcl_NewDictObj();
Tcl_IncrRefCount(map);
for (i = numDirs-1; i >= 0; i--) {
for (i = numDirs-1; i != TCL_INDEX_NONE; i--) {
/*
* Iterate backwards through the search path so as we overwrite
* entries found, we favor files earlier on the search path.
*/
int j, numFiles;
Tcl_Size j, numFiles;
Tcl_Obj *directory, *matchFileList;
Tcl_Obj **filev;
Tcl_GlobTypeData readableFiles = {
@@ -519,7 +524,8 @@ FillEncodingFileMap(void)
/* Since TCL_ENCODING_MODIFIED is only used for utf-8/cesu-8 and
* TCL_ENCODING_LE is only used for utf-16/utf-32/ucs-2. re-use the same value */
#define TCL_ENCODING_LE TCL_ENCODING_MODIFIED /* Little-endian encoding */
#define TCL_ENCODING_UTF 0x200 /* For UTF-8 encoding, allow 4-byte output sequences */
#define ENCODING_UTF 0x200 /* For UTF-8 encoding, allow 4-byte output sequences */
#define ENCODING_INPUT 0x400 /* For UTF-8/CESU-8 encoding, means external -> internal */
void
TclInitEncodingSubsystem(void)
@@ -561,9 +567,9 @@ TclInitEncodingSubsystem(void)
type.fromUtfProc = UtfToUtfProc;
type.freeProc = NULL;
type.nullSize = 1;
type.clientData = INT2PTR(TCL_ENCODING_UTF);
type.clientData = INT2PTR(ENCODING_UTF);
Tcl_CreateEncoding(&type);
type.clientData = INT2PTR(TCL_ENCODING_NOCOMPLAIN);
type.clientData = INT2PTR(0);
type.encodingName = "cesu-8";
Tcl_CreateEncoding(&type);
@@ -572,13 +578,13 @@ TclInitEncodingSubsystem(void)
type.freeProc = NULL;
type.nullSize = 2;
type.encodingName = "ucs-2le";
type.clientData = INT2PTR(TCL_ENCODING_LE|TCL_ENCODING_NOCOMPLAIN);
type.clientData = INT2PTR(TCL_ENCODING_LE);
Tcl_CreateEncoding(&type);
type.encodingName = "ucs-2be";
type.clientData = INT2PTR(TCL_ENCODING_NOCOMPLAIN);
type.clientData = INT2PTR(0);
Tcl_CreateEncoding(&type);
type.encodingName = "ucs-2";
type.clientData = INT2PTR(isLe.c|TCL_ENCODING_NOCOMPLAIN);
type.clientData = INT2PTR(isLe.c);
Tcl_CreateEncoding(&type);
type.toUtfProc = Utf32ToUtfProc;
@@ -600,13 +606,13 @@ TclInitEncodingSubsystem(void)
type.freeProc = NULL;
type.nullSize = 2;
type.encodingName = "utf-16le";
type.clientData = INT2PTR(TCL_ENCODING_LE);
type.clientData = INT2PTR(TCL_ENCODING_LE|ENCODING_UTF);
Tcl_CreateEncoding(&type);
type.encodingName = "utf-16be";
type.clientData = INT2PTR(0);
type.clientData = INT2PTR(ENCODING_UTF);
Tcl_CreateEncoding(&type);
type.encodingName = "utf-16";
type.clientData = INT2PTR(isLe.c);
type.clientData = INT2PTR(isLe.c|ENCODING_UTF);
Tcl_CreateEncoding(&type);
#ifndef TCL_NO_DEPRECATED
@@ -999,7 +1005,7 @@ Tcl_GetEncodingNames(
*
*---------------------------------------------------------------------------
*/
int
Tcl_Size
Tcl_GetEncodingNulLength(
Tcl_Encoding encoding)
{
@@ -1165,7 +1171,7 @@ Tcl_ExternalToUtfDString(
Tcl_Encoding encoding, /* The encoding for the source string, or NULL
* for the default system encoding. */
const char *src, /* Source string in specified encoding. */
int srcLen, /* Source string length in bytes, or < 0 for
Tcl_Size srcLen, /* Source string length in bytes, or < 0 for
* encoding-specific string length. */
Tcl_DString *dstPtr) /* Uninitialized or free DString in which the
* converted string is stored. */
@@ -1181,7 +1187,7 @@ Tcl_ExternalToUtfDString(
* Tcl_ExternalToUtfDStringEx --
*
* Convert a source buffer from the specified encoding into UTF-8.
* The parameter flags controls the behavior, if any of the bytes in
* The parameter flags controls the behavior, if any of the bytes in
* the source buffer are invalid or cannot be represented in utf-8.
* Possible flags values:
* TCL_ENCODING_STOPONERROR: don't replace invalid characters/bytes but
@@ -1204,12 +1210,12 @@ Tcl_ExternalToUtfDString(
*-------------------------------------------------------------------------
*/
int
Tcl_Size
Tcl_ExternalToUtfDStringEx(
Tcl_Encoding encoding, /* The encoding for the source string, or NULL
* for the default system encoding. */
const char *src, /* Source string in specified encoding. */
int srcLen, /* Source string length in bytes, or < 0 for
Tcl_Size srcLen, /* Source string length in bytes, or < 0 for
* encoding-specific string length. */
int flags, /* Conversion control flags. */
Tcl_DString *dstPtr) /* Uninitialized or free DString in which the
@@ -1218,7 +1224,8 @@ Tcl_ExternalToUtfDStringEx(
char *dst;
Tcl_EncodingState state;
const Encoding *encodingPtr;
int dstLen, result, soFar, srcRead, dstWrote, dstChars;
int result, soFar, srcRead, dstWrote, dstChars;
Tcl_Size dstLen;
const char *srcStart = src;
Tcl_DStringInit(dstPtr);
@@ -1238,7 +1245,7 @@ Tcl_ExternalToUtfDStringEx(
flags |= TCL_ENCODING_START | TCL_ENCODING_END;
if (encodingPtr->toUtfProc == UtfToUtfProc) {
flags |= TCL_ENCODING_MODIFIED | TCL_ENCODING_UTF;
flags |= ENCODING_INPUT;
}
while (1) {
@@ -1249,7 +1256,7 @@ Tcl_ExternalToUtfDStringEx(
src += srcRead;
if (result != TCL_CONVERT_NOSPACE) {
Tcl_DStringSetLength(dstPtr, soFar);
return (result == TCL_OK) ? TCL_INDEX_NONE : (int)(src - srcStart);
return (result == TCL_OK) ? TCL_INDEX_NONE : (Tcl_Size)(src - srcStart);
}
flags &= ~TCL_ENCODING_START;
srcLen -= srcRead;
@@ -1286,7 +1293,7 @@ Tcl_ExternalToUtf(
Tcl_Encoding encoding, /* The encoding for the source string, or NULL
* for the default system encoding. */
const char *src, /* Source string in specified encoding. */
int srcLen, /* Source string length in bytes, or < 0 for
Tcl_Size srcLen, /* Source string length in bytes, or < 0 for
* encoding-specific string length. */
int flags, /* Conversion control flags. */
Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
@@ -1296,7 +1303,7 @@ Tcl_ExternalToUtf(
* routine under control of flags argument. */
char *dst, /* Output buffer in which converted string is
* stored. */
int dstLen, /* The maximum length of output buffer in
Tcl_Size dstLen, /* The maximum length of output buffer in
* bytes. */
int *srcReadPtr, /* Filled with the number of bytes from the
* source string that were converted. This may
@@ -1345,6 +1352,9 @@ Tcl_ExternalToUtf(
}
if (!noTerminate) {
if (dstLen < 1) {
return TCL_CONVERT_NOSPACE;
}
/*
* If there are any null characters in the middle of the buffer,
* they will converted to the UTF-8 null character (\xC0\x80). To get
@@ -1353,9 +1363,13 @@ Tcl_ExternalToUtf(
*/
dstLen--;
} else {
if (dstLen < 0) {
return TCL_CONVERT_NOSPACE;
}
}
if (encodingPtr->toUtfProc == UtfToUtfProc) {
flags |= TCL_ENCODING_MODIFIED | TCL_ENCODING_UTF;
flags |= ENCODING_INPUT;
}
do {
Tcl_EncodingState savedState = *statePtr;
@@ -1403,7 +1417,7 @@ Tcl_UtfToExternalDString(
Tcl_Encoding encoding, /* The encoding for the converted string, or
* NULL for the default system encoding. */
const char *src, /* Source string in UTF-8. */
int srcLen, /* Source string length in bytes, or < 0 for
Tcl_Size srcLen, /* Source string length in bytes, or < 0 for
* strlen(). */
Tcl_DString *dstPtr) /* Uninitialized or free DString in which the
* converted string is stored. */
@@ -1443,22 +1457,23 @@ Tcl_UtfToExternalDString(
*-------------------------------------------------------------------------
*/
int
Tcl_Size
Tcl_UtfToExternalDStringEx(
Tcl_Encoding encoding, /* The encoding for the converted string, or
* NULL for the default system encoding. */
const char *src, /* Source string in UTF-8. */
int srcLen, /* Source string length in bytes, or < 0 for
Tcl_Size srcLen, /* Source string length in bytes, or < 0 for
* strlen(). */
int flags, /* Conversion control flags. */
int flags, /* Conversion control flags. */
Tcl_DString *dstPtr) /* Uninitialized or free DString in which the
* converted string is stored. */
{
char *dst;
Tcl_EncodingState state;
const Encoding *encodingPtr;
int dstLen, result, soFar, srcRead, dstWrote, dstChars;
int result, soFar, srcRead, dstWrote, dstChars;
const char *srcStart = src;
Tcl_Size dstLen;
Tcl_DStringInit(dstPtr);
dst = Tcl_DStringValue(dstPtr);
@@ -1487,7 +1502,7 @@ Tcl_UtfToExternalDStringEx(
while (i >= soFar) {
Tcl_DStringSetLength(dstPtr, i--);
}
return (result == TCL_OK) ? TCL_INDEX_NONE : (int)(src - srcStart);
return (result == TCL_OK) ? TCL_INDEX_NONE : (Tcl_Size)(src - srcStart);
}
flags &= ~TCL_ENCODING_START;
@@ -1525,7 +1540,7 @@ Tcl_UtfToExternal(
Tcl_Encoding encoding, /* The encoding for the converted string, or
* NULL for the default system encoding. */
const char *src, /* Source string in UTF-8. */
int srcLen, /* Source string length in bytes, or < 0 for
Tcl_Size srcLen, /* Source string length in bytes, or < 0 for
* strlen(). */
int flags, /* Conversion control flags. */
Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
@@ -1535,7 +1550,7 @@ Tcl_UtfToExternal(
* routine under control of flags argument. */
char *dst, /* Output buffer in which converted string
* is stored. */
int dstLen, /* The maximum length of output buffer in
Tcl_Size dstLen, /* The maximum length of output buffer in
* bytes. */
int *srcReadPtr, /* Filled with the number of bytes from the
* source string that were converted. This may
@@ -1577,10 +1592,17 @@ Tcl_UtfToExternal(
dstCharsPtr = &dstChars;
}
if (dstLen < encodingPtr->nullSize) {
return TCL_CONVERT_NOSPACE;
}
dstLen -= encodingPtr->nullSize;
result = encodingPtr->fromUtfProc(encodingPtr->clientData, src, srcLen,
flags, statePtr, dst, dstLen, srcReadPtr,
dstWrotePtr, dstCharsPtr);
/*
* Buffer is terminated irrespective of result. Not sure this is
* reasonable but keep for historical/compatibility reasons.
*/
memset(&dst[*dstWrotePtr], '\0', encodingPtr->nullSize);
return result;
@@ -1646,7 +1668,7 @@ OpenEncodingFileChannel(
Tcl_Obj *map = TclGetProcessGlobalValue(&encodingFileMap);
Tcl_Obj **dir, *path, *directory = NULL;
Tcl_Channel chan = NULL;
int i, numDirs;
Tcl_Size i, numDirs;
TclListObjGetElementsM(NULL, searchPath, &numDirs, &dir);
Tcl_IncrRefCount(nameObj);
@@ -1911,7 +1933,7 @@ LoadTableEncoding(
for (i = 0; i < numPages; i++) {
int ch;
const char *p;
int expected = 3 + 16 * (16 * 4 + 1);
Tcl_Size expected = 3 + 16 * (16 * 4 + 1);
if (Tcl_ReadChars(chan, objPtr, expected, 0) != expected) {
return NULL;
@@ -2147,7 +2169,7 @@ LoadEscapeEncoding(
Tcl_DStringInit(&escapeData);
while (1) {
int argc;
Tcl_Size argc;
const char **argv;
char *line;
Tcl_DString lineString;
@@ -2302,9 +2324,9 @@ BinaryProc(
*
* UtfToUtfProc --
*
* Convert from UTF-8 to UTF-8. Note that the UTF-8 to UTF-8 translation
* is not a no-op, because it will turn a stream of improperly formed
* UTF-8 into a properly formed stream.
* Converts from UTF-8 to UTF-8. Note that the UTF-8 to UTF-8 translation
* is not a no-op, because it turns a stream of improperly formed
* UTF-8 into a properly-formed stream.
*
* Results:
* Returns TCL_OK if conversion was successful.
@@ -2363,7 +2385,7 @@ UtfToUtfProc(
dstStart = dst;
flags |= PTR2INT(clientData);
dstEnd = dst + dstLen - ((flags & TCL_ENCODING_UTF) ? TCL_UTF_MAX : 6);
dstEnd = dst + dstLen - ((flags & ENCODING_UTF) ? TCL_UTF_MAX : 6);
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
@@ -2379,7 +2401,7 @@ UtfToUtfProc(
result = TCL_CONVERT_NOSPACE;
break;
}
if (UCHAR(*src) < 0x80 && !((UCHAR(*src) == 0) && (flags & TCL_ENCODING_MODIFIED))) {
if (UCHAR(*src) < 0x80 && !((UCHAR(*src) == 0) && (flags & ENCODING_INPUT))) {
/*
* Copy 7bit characters, but skip null-bytes when we are in input
* mode, so that they get converted to 0xC080.
@@ -2387,11 +2409,13 @@ UtfToUtfProc(
*dst++ = *src++;
} else if ((UCHAR(*src) == 0xC0) && (src + 1 < srcEnd)
&& (UCHAR(src[1]) == 0x80) && (!(flags & TCL_ENCODING_MODIFIED) || ((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT) || (flags & ENCODING_FAILINDEX))) {
&& (UCHAR(src[1]) == 0x80) && !(flags & TCL_ENCODING_MODIFIED) && (!(flags & ENCODING_INPUT)
|| ((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT)
|| (flags & ENCODING_FAILINDEX))) {
/*
* If in input mode, and -strict or -failindex is specified: This is an error.
*/
if (flags & TCL_ENCODING_MODIFIED) {
if ((STOPONERROR) && (flags & ENCODING_INPUT)) {
result = TCL_CONVERT_SYNTAX;
break;
}
@@ -2409,33 +2433,37 @@ UtfToUtfProc(
* unless the user has explicitly asked to be told.
*/
if (flags & TCL_ENCODING_MODIFIED) {
if (flags & ENCODING_INPUT) {
if ((STOPONERROR) && (flags & TCL_ENCODING_CHAR_LIMIT)) {
result = TCL_CONVERT_MULTIBYTE;
break;
}
if (((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT) || (flags & ENCODING_FAILINDEX)) {
result = TCL_CONVERT_SYNTAX;
break;
}
ch = UCHAR(*src++);
} else {
char chbuf[2];
chbuf[0] = UCHAR(*src++); chbuf[1] = 0;
TclUtfToUCS4(chbuf, &ch);
if (((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT) || (flags & ENCODING_FAILINDEX)) {
result = TCL_CONVERT_SYNTAX;
break;
}
}
char chbuf[2];
chbuf[0] = UCHAR(*src++); chbuf[1] = 0;
TclUtfToUCS4(chbuf, &ch);
dst += Tcl_UniCharToUtf(ch, dst);
} else {
int low;
const char *saveSrc = src;
size_t len = TclUtfToUCS4(src, &ch);
if ((len < 2) && (ch != 0) && (flags & TCL_ENCODING_MODIFIED)
&& (((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT))) {
result = TCL_CONVERT_SYNTAX;
break;
if (flags & ENCODING_INPUT) {
if ((len < 2) && (ch != 0)
&& (((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT) || (flags & ENCODING_FAILINDEX))) {
goto utf8Syntax;
} else if ((ch > 0xFFFF) && !(flags & ENCODING_UTF)
&& (((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT) || (flags & ENCODING_FAILINDEX))) {
utf8Syntax:
result = TCL_CONVERT_SYNTAX;
break;
}
}
const char *saveSrc = src;
src += len;
if (!(flags & TCL_ENCODING_UTF) && (ch > 0x3FF)) {
if (!(flags & ENCODING_UTF) && !(flags & ENCODING_INPUT) && (ch > 0x3FF)) {
if (ch > 0xFFFF) {
/* CESU-8 6-byte sequence for chars > U+FFFF */
ch -= 0x10000;
@@ -2450,6 +2478,11 @@ UtfToUtfProc(
* A surrogate character is detected, handle especially.
*/
if (((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT) && (flags & ENCODING_UTF)) {
result = TCL_CONVERT_UNKNOWN;
src = saveSrc;
break;
}
low = ch;
len = (src <= srcEnd-3) ? TclUtfToUCS4(src, &low) : 0;
@@ -2469,12 +2502,12 @@ UtfToUtfProc(
src += len;
dst += Tcl_UniCharToUtf(ch, dst);
ch = low;
} else if (STOPONERROR && !(flags & TCL_ENCODING_MODIFIED) && (((ch & ~0x7FF) == 0xD800))) {
} else if (STOPONERROR && !(flags & ENCODING_INPUT) && (((ch & ~0x7FF) == 0xD800))) {
result = TCL_CONVERT_UNKNOWN;
src = saveSrc;
break;
} else if (((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT)
&& (flags & TCL_ENCODING_MODIFIED) && ((ch & ~0x7FF) == 0xD800)) {
&& (flags & ENCODING_INPUT) && ((ch & ~0x7FF) == 0xD800)) {
result = TCL_CONVERT_SYNTAX;
src = saveSrc;
break;
@@ -2531,7 +2564,7 @@ Utf32ToUtfProc(
const char *srcStart, *srcEnd;
const char *dstEnd, *dstStart;
int result, numChars, charLimit = INT_MAX;
int ch;
int ch = 0, bytesLeft = srcLen % 4;
flags |= PTR2INT(clientData);
if (flags & TCL_ENCODING_CHAR_LIMIT) {
@@ -2543,9 +2576,22 @@ Utf32ToUtfProc(
* Check alignment with utf-32 (4 == sizeof(UTF-32))
*/
if ((srcLen % 4) != 0) {
if (bytesLeft != 0) {
result = TCL_CONVERT_MULTIBYTE;
srcLen &= -4;
srcLen -= bytesLeft;
}
/*
* If last code point is a high surrogate, we cannot handle that yet,
* unless we are at the end.
*/
if (!(flags & TCL_ENCODING_END) && (srcLen >= 4) &&
((src[srcLen - ((flags & TCL_ENCODING_LE)?3:2)] & 0xFC) == 0xD8) &&
((src[srcLen - ((flags & TCL_ENCODING_LE)?2:3)]) == 0) &&
((src[srcLen - ((flags & TCL_ENCODING_LE)?1:4)]) == 0)) {
result = TCL_CONVERT_MULTIBYTE;
srcLen-= 4;
}
srcStart = src;
@@ -2560,17 +2606,28 @@ Utf32ToUtfProc(
break;
}
int prev = ch;
if (flags & TCL_ENCODING_LE) {
ch = (src[3] & 0xFF) << 24 | (src[2] & 0xFF) << 16 | (src[1] & 0xFF) << 8 | (src[0] & 0xFF);
} else {
ch = (src[0] & 0xFF) << 24 | (src[1] & 0xFF) << 16 | (src[2] & 0xFF) << 8 | (src[3] & 0xFF);
}
if ((unsigned)ch > 0x10FFFF || (((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT)
&& ((ch & ~0x7FF) == 0xD800))) {
if (STOPONERROR) {
if (((prev & ~0x3FF) == 0xD800) && ((ch & ~0x3FF) != 0xDC00)) {
/* Bug [10c2c17c32]. If Hi surrogate not followed by Lo surrogate, finish 3-byte UTF-8 */
dst += Tcl_UniCharToUtf(-1, dst);
}
if ((unsigned)ch > 0x10FFFF) {
ch = 0xFFFD;
if ((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT) {
result = TCL_CONVERT_SYNTAX;
break;
}
} else if (((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT)
&& ((ch & ~0x7FF) == 0xD800)) {
result = TCL_CONVERT_SYNTAX;
ch = 0;
break;
}
/*
@@ -2586,6 +2643,27 @@ Utf32ToUtfProc(
src += sizeof(unsigned int);
}
if ((ch & ~0x3FF) == 0xD800) {
/* Bug [10c2c17c32]. If Hi surrogate, finish 3-byte UTF-8 */
dst += Tcl_UniCharToUtf(-1, dst);
}
if ((flags & TCL_ENCODING_END) && (result == TCL_CONVERT_MULTIBYTE)) {
/* We have a single byte 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 ((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT) {
result = TCL_CONVERT_SYNTAX;
} else {
result = TCL_OK;
dst += Tcl_UniCharToUtf(0xFFFD, dst);
numChars++;
src += bytesLeft;
}
}
}
*srcReadPtr = src - srcStart;
*dstWrotePtr = dst - dstStart;
*dstCharsPtr = numChars;
@@ -2730,7 +2808,7 @@ Utf16ToUtfProc(
const char *srcStart, *srcEnd;
const char *dstEnd, *dstStart;
int result, numChars, charLimit = INT_MAX;
unsigned short ch;
unsigned short ch = 0;
flags |= PTR2INT(clientData);
if (flags & TCL_ENCODING_CHAR_LIMIT) {
@@ -2748,10 +2826,11 @@ Utf16ToUtfProc(
}
/*
* If last code point is a high surrogate, we cannot handle that yet.
* If last code point is a high surrogate, we cannot handle that yet,
* unless we are at the end.
*/
if ((srcLen >= 2) &&
if (!(flags & TCL_ENCODING_END) && (srcLen >= 2) &&
((src[srcLen - ((flags & TCL_ENCODING_LE)?1:2)] & 0xFC) == 0xD8)) {
result = TCL_CONVERT_MULTIBYTE;
srcLen-= 2;
@@ -2769,25 +2848,71 @@ Utf16ToUtfProc(
break;
}
unsigned short prev = ch;
if (flags & TCL_ENCODING_LE) {
ch = (src[1] & 0xFF) << 8 | (src[0] & 0xFF);
} else {
ch = (src[0] & 0xFF) << 8 | (src[1] & 0xFF);
}
if (((prev & ~0x3FF) == 0xD800) && ((ch & ~0x3FF) != 0xDC00)) {
if (((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT)) {
result = TCL_CONVERT_UNKNOWN;
src -= 2; /* Go back to beginning of high surrogate */
dst--; /* Also undo writing a single byte too much */
numChars--;
break;
}
/* Bug [10c2c17c32]. If Hi surrogate not followed by Lo surrogate, finish 3-byte UTF-8 */
dst += Tcl_UniCharToUtf(-1, dst);
}
/*
* Special case for 1-byte utf chars for speed. Make sure we work with
* unsigned short-size data.
*/
if (ch && ch < 0x80) {
if ((unsigned)ch - 1 < 0x7F) {
*dst++ = (ch & 0xFF);
} else if (((prev & ~0x3FF) == 0xD800) || ((ch & ~0x3FF) == 0xD800)) {
dst += Tcl_UniCharToUtf(ch, dst);
} else if (((ch & ~0x3FF) == 0xDC00) && ((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT)) {
/* Lo surrogate not preceded by Hi surrogate */
result = TCL_CONVERT_UNKNOWN;
break;
} else {
*dst = 0; /* In case of lower surrogate, don't try to combine */
dst += Tcl_UniCharToUtf(ch, dst);
}
src += sizeof(unsigned short);
}
if ((ch & ~0x3FF) == 0xD800) {
if ((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT) {
result = TCL_CONVERT_UNKNOWN;
src -= 2;
dst--;
numChars--;
} else {
/* Bug [10c2c17c32]. If Hi surrogate, finish 3-byte UTF-8 */
dst += Tcl_UniCharToUtf(-1, dst);
}
}
if ((flags & TCL_ENCODING_END) && (result == TCL_CONVERT_MULTIBYTE)) {
/* We have a single byte 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 (((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT)) {
result = TCL_CONVERT_SYNTAX;
} else {
result = TCL_OK;
dst += Tcl_UniCharToUtf(0xFFFD, dst);
numChars++;
src++;
}
}
}
*srcReadPtr = src - srcStart;
*dstWrotePtr = dst - dstStart;
*dstCharsPtr = numChars;
@@ -2939,10 +3064,7 @@ UtfToUcs2Proc(
* output buffer. */
{
const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd;
int result, numChars;
#if TCL_UTF_MAX < 4
int len;
#endif
int result, numChars, len;
Tcl_UniChar ch = 0;
flags |= PTR2INT(clientData);
@@ -2972,17 +3094,32 @@ UtfToUcs2Proc(
break;
}
#if TCL_UTF_MAX < 4
src += (len = TclUtfToUniChar(src, &ch));
len = TclUtfToUniChar(src, &ch);
if ((ch >= 0xD800) && (len < 3)) {
if (STOPONERROR) {
result = TCL_CONVERT_UNKNOWN;
break;
}
src += len;
src += TclUtfToUniChar(src, &ch);
ch = 0xFFFD;
}
#else
src += TclUtfToUniChar(src, &ch);
len = TclUtfToUniChar(src, &ch);
if (ch > 0xFFFF) {
if (STOPONERROR) {
result = TCL_CONVERT_UNKNOWN;
break;
}
ch = 0xFFFD;
}
#endif
if (STOPONERROR && ((ch & ~0x7FF) == 0xD800)) {
result = TCL_CONVERT_SYNTAX;
break;
}
src += len;
/*
* Need to handle this in a way that won't cause misalignment by
@@ -3084,7 +3221,8 @@ TableToUtfProc(
ch = pageZero[byte];
}
if ((ch == 0) && (byte != 0)) {
if (STOPONERROR) {
if ((flags & ENCODING_FAILINDEX)
|| ((flags & TCL_ENCODING_STRICT) == TCL_ENCODING_STRICT)) {
result = TCL_CONVERT_SYNTAX;
break;
}
@@ -3823,8 +3961,7 @@ EscapeFromUtfProc(
result = TCL_CONVERT_NOSPACE;
break;
}
memcpy(dst, subTablePtr->sequence,
subTablePtr->sequenceLen);
memcpy(dst, subTablePtr->sequence, subTablePtr->sequenceLen);
dst += subTablePtr->sequenceLen;
}
}
@@ -4042,11 +4179,11 @@ unilen4(
static void
InitializeEncodingSearchPath(
char **valuePtr,
unsigned int *lengthPtr,
TCL_HASH_TYPE *lengthPtr,
Tcl_Encoding *encodingPtr)
{
const char *bytes;
int i, numDirs, numBytes;
Tcl_Size i, numDirs, numBytes;
Tcl_Obj *libPathObj, *encodingObj, *searchPathObj;
TclNewLiteralStringObj(encodingObj, "encoding");
+1 -1
View File
@@ -2503,8 +2503,8 @@ TEBCresume(
* 'yieldParameter').
*/
Tcl_IncrRefCount(valuePtr);
iPtr->execEnvPtr = corPtr->callerEEPtr;
Tcl_IncrRefCount(valuePtr);
TclSetTailcall(interp, valuePtr);
corPtr->yieldPtr = valuePtr;
iPtr->execEnvPtr = corPtr->eePtr;
+88 -38
View File
@@ -165,6 +165,7 @@ static int CheckForDeadChannel(Tcl_Interp *interp,
static void CheckForStdChannelsBeingClosed(Tcl_Channel chan);
static void CleanupChannelHandlers(Tcl_Interp *interp,
Channel *chanPtr);
static void CleanupTimerHandler(ChannelState *statePtr);
static int CloseChannel(Tcl_Interp *interp, Channel *chanPtr,
int errorCode);
static int CloseChannelPart(Tcl_Interp *interp, Channel *chanPtr,
@@ -172,6 +173,7 @@ static int CloseChannelPart(Tcl_Interp *interp, Channel *chanPtr,
static int CloseWrite(Tcl_Interp *interp, Channel *chanPtr);
static void CommonGetsCleanup(Channel *chanPtr);
static int CopyData(CopyState *csPtr, int mask);
static void DeleteTimerHandler(ChannelState *statePtr);
static int MoveBytes(CopyState *csPtr);
static void MBCallback(CopyState *csPtr, Tcl_Obj *errObj);
@@ -1730,6 +1732,7 @@ Tcl_CreateChannel(
statePtr->scriptRecordPtr = NULL;
statePtr->bufSize = CHANNELBUFFER_DEFAULT_SIZE;
statePtr->timer = NULL;
statePtr->timerChanPtr = NULL;
statePtr->csPtrR = NULL;
statePtr->csPtrW = NULL;
statePtr->outputStage = NULL;
@@ -3187,8 +3190,8 @@ CloseChannel(
/*
* Cancel any outstanding timer.
*/
DeleteTimerHandler(statePtr);
Tcl_DeleteTimerHandler(statePtr->timer);
/*
* Mark the channel as deleted by clearing the type structure.
@@ -3540,7 +3543,7 @@ Tcl_Close(
/*
* Cancel any outstanding timer.
*/
Tcl_DeleteTimerHandler(statePtr->timer);
DeleteTimerHandler(statePtr);
/*
* Invoke the registered close callbacks and delete their records.
@@ -4015,8 +4018,7 @@ Tcl_ClearChannelHandlers(
/*
* Cancel any outstanding timer.
*/
Tcl_DeleteTimerHandler(statePtr->timer);
DeleteTimerHandler(statePtr);
/*
* Remove any references to channel handlers for this channel that may be
@@ -7588,7 +7590,11 @@ Tcl_Eof(
ChannelState *statePtr = ((Channel *) chan)->state;
/* State of real channel structure. */
return (GotFlag(statePtr, CHANNEL_EOF) && !GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) ? 1 : 0;
if (GotFlag(statePtr, CHANNEL_NONBLOCKING|CHANNEL_FCOPY)
&& GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) {
return 0;
}
return GotFlag(statePtr, CHANNEL_EOF) ? 1 : 0;
}
/*
@@ -8354,7 +8360,7 @@ Tcl_SetChannelOption(
#ifdef TCL_NO_DEPRECATED
ResetFlag(statePtr, CHANNEL_ENCODING_NOCOMPLAIN);
#else
if (SetFlag(statePtr, CHANNEL_ENCODING_STRICT)) {
if (GotFlag(statePtr, CHANNEL_ENCODING_STRICT) != CHANNEL_ENCODING_STRICT) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"bad value for -nocomplainencoding: only true allowed",
@@ -8800,8 +8806,10 @@ UpdateInterest(
mask &= ~TCL_EXCEPTION;
if (!statePtr->timer) {
TclChannelPreserve((Tcl_Channel)chanPtr);
statePtr->timerChanPtr = chanPtr;
statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
ChannelTimerProc, chanPtr);
ChannelTimerProc, chanPtr);
}
}
}
@@ -8810,6 +8818,8 @@ UpdateInterest(
&& mask & TCL_WRITABLE
&& GotFlag(statePtr, CHANNEL_NONBLOCKING)) {
TclChannelPreserve((Tcl_Channel)chanPtr);
statePtr->timerChanPtr = chanPtr;
statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
ChannelTimerProc,chanPtr);
}
@@ -8840,48 +8850,75 @@ ChannelTimerProc(
void *clientData)
{
Channel *chanPtr = (Channel *)clientData;
/* State info for channel */
ChannelState *statePtr = chanPtr->state;
/* Preserve chanPtr to guard against deallocation in Tcl_NotifyChannel. */
TclChannelPreserve((Tcl_Channel)chanPtr);
Tcl_Preserve(statePtr);
statePtr->timer = NULL;
if (statePtr->interestMask & TCL_WRITABLE
&& GotFlag(statePtr, CHANNEL_NONBLOCKING)
&& !GotFlag(statePtr, BG_FLUSH_SCHEDULED)
) {
/*
* Restart the timer in case a channel handler reenters the event loop
* before UpdateInterest gets called by Tcl_NotifyChannel.
*/
statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
ChannelTimerProc,chanPtr);
Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_WRITABLE);
}
/* TclChannelPreserve() must be called before the current function was
* scheduled, is already in effect. In this function it guards against
* deallocation in Tcl_NotifyChannel and also keps the channel preserved
* until ChannelTimerProc is later called again.
*/
/* The channel may have just been closed from within Tcl_NotifyChannel */
if (!GotFlag(statePtr, CHANNEL_INCLOSE)) {
if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA)
&& (statePtr->interestMask & TCL_READABLE)
&& (statePtr->inQueueHead != NULL)
&& IsBufferReady(statePtr->inQueueHead)) {
if (chanPtr->typePtr == NULL) {
CleanupTimerHandler(statePtr);
} else {
Tcl_Preserve(statePtr);
statePtr->timer = NULL;
if (statePtr->interestMask & TCL_WRITABLE
&& GotFlag(statePtr, CHANNEL_NONBLOCKING)
&& !GotFlag(statePtr, BG_FLUSH_SCHEDULED)
) {
/*
* Restart the timer in case a channel handler reenters the event loop
* before UpdateInterest gets called by Tcl_NotifyChannel.
*/
statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
ChannelTimerProc,chanPtr);
Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_READABLE);
ChannelTimerProc,chanPtr);
Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_WRITABLE);
} else {
UpdateInterest(chanPtr);
}
}
/* The channel may have just been closed from within Tcl_NotifyChannel */
if (!GotFlag(statePtr, CHANNEL_INCLOSE)) {
if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA)
&& (statePtr->interestMask & TCL_READABLE)
&& (statePtr->inQueueHead != NULL)
&& IsBufferReady(statePtr->inQueueHead)) {
/*
* Restart the timer in case a channel handler reenters the event loop
* before UpdateInterest gets called by Tcl_NotifyChannel.
*/
Tcl_Release(statePtr);
TclChannelRelease((Tcl_Channel)chanPtr);
statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
ChannelTimerProc,chanPtr);
Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_READABLE);
} else {
CleanupTimerHandler(statePtr);
UpdateInterest(chanPtr);
}
} else {
CleanupTimerHandler(statePtr);
}
}
Tcl_Release(statePtr);
}
}
static void
DeleteTimerHandler(
ChannelState *statePtr
)
{
if (statePtr->timer != NULL) {
Tcl_DeleteTimerHandler(statePtr->timer);
CleanupTimerHandler(statePtr);
}
}
static void
CleanupTimerHandler(
ChannelState *statePtr
){
TclChannelRelease((Tcl_Channel)statePtr->timerChanPtr);
statePtr->timer = NULL;
statePtr->timerChanPtr = NULL;
}
/*
@@ -9799,6 +9836,7 @@ CopyData(
* the bottom of the stack.
*/
SetFlag(inStatePtr, CHANNEL_FCOPY);
inBinary = (inStatePtr->encoding == NULL);
outBinary = (outStatePtr->encoding == NULL);
sameEncoding = inStatePtr->encoding == outStatePtr->encoding
@@ -9820,12 +9858,20 @@ CopyData(
Tcl_SetErrno(inStatePtr->unreportedError);
inStatePtr->unreportedError = 0;
goto readError;
} else if (inStatePtr->flags & CHANNEL_ENCODING_ERROR) {
Tcl_SetErrno(EILSEQ);
inStatePtr->flags &= ~CHANNEL_ENCODING_ERROR;
goto readError;
}
Tcl_GetChannelError(outChan, &msg);
if ((outStatePtr->unreportedError != 0) || (msg != NULL)) {
Tcl_SetErrno(outStatePtr->unreportedError);
outStatePtr->unreportedError = 0;
goto writeError;
} else if (outStatePtr->flags & CHANNEL_ENCODING_ERROR) {
Tcl_SetErrno(EILSEQ);
outStatePtr->flags &= ~CHANNEL_ENCODING_ERROR;
goto writeError;
}
if (cmdPtr && (mask == 0)) {
@@ -9906,6 +9952,7 @@ CopyData(
TclDecrRefCount(bufObj);
bufObj = NULL;
}
ResetFlag(inStatePtr, CHANNEL_FCOPY);
return TCL_OK;
}
}
@@ -9997,6 +10044,7 @@ CopyData(
TclDecrRefCount(bufObj);
bufObj = NULL;
}
ResetFlag(inStatePtr, CHANNEL_FCOPY);
return TCL_OK;
}
@@ -10019,6 +10067,7 @@ CopyData(
TclDecrRefCount(bufObj);
bufObj = NULL;
}
ResetFlag(inStatePtr, CHANNEL_FCOPY);
return TCL_OK;
}
} /* while */
@@ -10071,6 +10120,7 @@ CopyData(
}
}
}
ResetFlag(inStatePtr, CHANNEL_FCOPY);
return result;
}
+5
View File
@@ -188,6 +188,9 @@ typedef struct ChannelState {
* handlers ("fileevent") on this channel. */
Tcl_Size bufSize; /* What size buffers to allocate? */
Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */
Channel *timerChanPtr; /* Needed in order to decrement the refCount of
the right channel when the timer is
deleted. */
struct CopyState *csPtrR; /* State of background copy for which channel
* is input, or NULL. */
struct CopyState *csPtrW; /* State of background copy for which channel
@@ -233,6 +236,8 @@ typedef struct ChannelState {
* flushed after every newline. */
#define CHANNEL_UNBUFFERED (1<<5) /* Output to the channel must always
* be flushed immediately. */
#define CHANNEL_FCOPY (1<<6) /* Channel is currently doing an fcopy
* mode. */
#define BG_FLUSH_SCHEDULED (1<<7) /* A background flush of the queued
* output buffers has been
* scheduled. */
+2
View File
@@ -2830,6 +2830,7 @@ DeleteThreadReflectedChannelMap(
Tcl_ThreadId self = Tcl_GetCurrentThread();
ReflectedChannelMap *rcmPtr; /* The map */
ForwardingResult *resultPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
/*
* The origin thread for one or more reflected channels is gone.
@@ -2909,6 +2910,7 @@ DeleteThreadReflectedChannelMap(
*/
rcmPtr = GetThreadReflectedChannelMap();
tsdPtr->rcmPtr = NULL;
for (hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch);
hPtr != NULL;
hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch)) {
+2
View File
@@ -417,6 +417,8 @@ Tcl_PopCallFrame(
framePtr->nsPtr = NULL;
if (framePtr->tailcallPtr) {
/* Reusing the existing reference count from framePtr->tailcallPtr, so
* no need to Tcl_IncrRefCount(framePtr->tailcallPtr)*/
TclSetTailcall(interp, framePtr->tailcallPtr);
}
}
+1
View File
@@ -4849,6 +4849,7 @@ ExtendStringRepWithUnicode(
copyBytes:
dst = objPtr->bytes + origLength;
*dst = '\0';
for (i = 0; i < numChars; i++) {
dst += Tcl_UniCharToUtf(unicode[i], dst);
}
+295 -17
View File
@@ -70,6 +70,7 @@ static Tcl_Interp *delInterp;
typedef struct TestCommandTokenRef {
int id; /* Identifier for this reference. */
Tcl_Command token; /* Tcl's token for the command. */
const char *value;
struct TestCommandTokenRef *nextPtr;
/* Next in list of references. */
} TestCommandTokenRef;
@@ -1178,6 +1179,18 @@ TestcmdinfoCmd(
return TCL_OK;
}
static int
CmdProc0(
void *clientData, /* String to return. */
Tcl_Interp *interp, /* Current interpreter. */
TCL_UNUSED(int) /*argc*/,
TCL_UNUSED(const char **) /*argv*/)
{
TestCommandTokenRef *refPtr = (TestCommandTokenRef *) clientData;
Tcl_AppendResult(interp, "CmdProc1 ", refPtr->value, NULL);
return TCL_OK;
}
static int
CmdProc1(
void *clientData, /* String to return. */
@@ -1189,6 +1202,7 @@ CmdProc1(
return TCL_OK;
}
static int
CmdProc2(
void *clientData, /* String to return. */
@@ -1200,6 +1214,28 @@ CmdProc2(
return TCL_OK;
}
static void
CmdDelProc0(
void *clientData) /* String to save. */
{
TestCommandTokenRef *thisRefPtr, *prevRefPtr = NULL;
TestCommandTokenRef *refPtr = (TestCommandTokenRef *) clientData;
int id = refPtr->id;
for (thisRefPtr = firstCommandTokenRef; refPtr != NULL;
thisRefPtr = thisRefPtr->nextPtr) {
if (thisRefPtr->id == id) {
if (prevRefPtr != NULL) {
prevRefPtr->nextPtr = thisRefPtr->nextPtr;
} else {
firstCommandTokenRef = thisRefPtr->nextPtr;
}
break;
}
prevRefPtr = thisRefPtr;
}
ckfree(refPtr);
}
static void
CmdDelProc1(
void *clientData) /* String to save. */
@@ -1253,17 +1289,16 @@ TestcmdtokenCmd(
}
if (strcmp(argv[1], "create") == 0) {
refPtr = (TestCommandTokenRef *)Tcl_Alloc(sizeof(TestCommandTokenRef));
refPtr->token = Tcl_CreateCommand(interp, argv[2], CmdProc1,
(void *) "original", NULL);
refPtr->token = Tcl_CreateCommand(interp, argv[2], CmdProc0,
refPtr, CmdDelProc0);
refPtr->id = nextCommandTokenRefId;
refPtr->value = "original";
nextCommandTokenRefId++;
refPtr->nextPtr = firstCommandTokenRef;
firstCommandTokenRef = refPtr;
sprintf(buf, "%d", refPtr->id);
Tcl_AppendResult(interp, buf, NULL);
} else if (strcmp(argv[1], "name") == 0) {
Tcl_Obj *objPtr;
} else {
if (sscanf(argv[2], "%d", &id) != 1) {
Tcl_AppendResult(interp, "bad command token \"", argv[2],
"\"", NULL);
@@ -1283,18 +1318,23 @@ TestcmdtokenCmd(
return TCL_ERROR;
}
objPtr = Tcl_NewObj();
Tcl_GetCommandFullName(interp, refPtr->token, objPtr);
if (strcmp(argv[1], "name") == 0) {
Tcl_Obj *objPtr;
Tcl_AppendElement(interp,
Tcl_GetCommandName(interp, refPtr->token));
Tcl_AppendElement(interp, Tcl_GetString(objPtr));
Tcl_DecrRefCount(objPtr);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be create or name", NULL);
return TCL_ERROR;
objPtr = Tcl_NewObj();
Tcl_GetCommandFullName(interp, refPtr->token, objPtr);
Tcl_AppendElement(interp,
Tcl_GetCommandName(interp, refPtr->token));
Tcl_AppendElement(interp, Tcl_GetString(objPtr));
Tcl_DecrRefCount(objPtr);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be create, name, or free", NULL);
return TCL_ERROR;
}
}
return TCL_OK;
}
@@ -1974,6 +2014,238 @@ static void SpecialFree(
) {
ckfree(blockPtr - 16);
}
/*
*------------------------------------------------------------------------
*
* UtfTransformFn --
*
* Implements a direct call into Tcl_UtfToExternal and Tcl_ExternalToUtf
* as otherwise there is no script level command that directly exercises
* these functions (i/o command cannot test all combinations)
* The arguments at the script level are roughly those of the above
* functions:
* encodingname srcbytes flags state dstlen ?srcreadvar? ?dstwrotevar? ?dstcharsvar?
*
* Results:
* TCL_OK or TCL_ERROR. This any errors running the test, NOT the
* result of Tcl_UtfToExternal or Tcl_ExternalToUtf.
*
* Side effects:
*
* The result in the interpreter is a list of the return code from the
* Tcl_UtfToExternal/Tcl_ExternalToUtf functions, the encoding state, and
* an encoded binary string of length dstLen. Note the string is the
* entire output buffer, not just the part containing the decoded
* portion. This allows for additional checks at test script level.
*
* If any of the srcreadvar, dstwrotevar and
* dstcharsvar are specified and not empty, they are treated as names
* of variables where the *srcRead, *dstWrote and *dstChars output
* from the functions are stored.
*
* The function also checks internally whether nuls are correctly
* appended as requested but the TCL_ENCODING_NO_TERMINATE flag
* and that no buffer overflows occur.
*------------------------------------------------------------------------
*/
typedef int
UtfTransformFn(Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, int flags, Tcl_EncodingState *statePtr,
char *dst, Tcl_Size dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr);
static int UtfExtWrapper(
Tcl_Interp *interp, UtfTransformFn *transformer, int objc, Tcl_Obj *const objv[])
{
Tcl_Encoding encoding;
Tcl_EncodingState encState, *encStatePtr;
Tcl_Size srcLen, bufLen;
const unsigned char *bytes;
unsigned char *bufPtr;
int srcRead, dstLen, dstWrote, dstChars;
Tcl_Obj *srcReadVar, *dstWroteVar, *dstCharsVar;
int result;
int flags;
Tcl_Obj **flagObjs;
int nflags;
if (objc < 7 || objc > 10) {
Tcl_WrongNumArgs(interp,
2,
objv,
"encoding srcbytes flags state dstlen ?srcreadvar? ?dstwrotevar? ?dstcharsvar?");
return TCL_ERROR;
}
if (Tcl_GetEncodingFromObj(interp, objv[2], &encoding) != TCL_OK) {
return TCL_ERROR;
}
/* Flags may be specified as list of integers and keywords */
flags = 0;
if (Tcl_ListObjGetElements(interp, objv[4], &nflags, &flagObjs) != TCL_OK) {
return TCL_ERROR;
}
struct {
const char *flagKey;
int flag;
} flagMap[] = {
{"start", TCL_ENCODING_START},
{"end", TCL_ENCODING_END},
{"stoponerror", TCL_ENCODING_STOPONERROR},
{"noterminate", TCL_ENCODING_NO_TERMINATE},
{"charlimit", TCL_ENCODING_CHAR_LIMIT},
{NULL, 0}
};
int i;
for (i = 0; i < nflags; ++i) {
int flag;
if (Tcl_GetIntFromObj(NULL, flagObjs[i], &flag) == TCL_OK) {
flags |= flag;
}
else {
int idx;
if (Tcl_GetIndexFromObjStruct(interp,
flagObjs[i],
flagMap,
sizeof(flagMap[0]),
"flag",
0,
&idx) != TCL_OK) {
return TCL_ERROR;
}
flags |= flagMap[idx].flag;
}
}
/* Assumes state is integer if not "" */
Tcl_WideInt wide;
if (Tcl_GetWideIntFromObj(interp, objv[5], &wide) == TCL_OK) {
encState = (Tcl_EncodingState) wide;
encStatePtr = &encState;
} else if (Tcl_GetCharLength(objv[5]) == 0) {
encStatePtr = NULL;
} else {
return TCL_ERROR;
}
if (Tcl_GetIntFromObj(interp, objv[6], &dstLen) != TCL_OK) {
return TCL_ERROR;
}
srcReadVar = NULL;
dstWroteVar = NULL;
dstCharsVar = NULL;
if (objc > 7) {
/* Has caller requested srcRead? */
if (Tcl_GetCharLength(objv[7])) {
srcReadVar = objv[7];
}
if (objc > 8) {
/* Ditto for dstWrote */
if (Tcl_GetCharLength(objv[8])) {
dstWroteVar = objv[8];
}
if (objc > 9) {
if (Tcl_GetCharLength(objv[9])) {
dstCharsVar = objv[9];
}
}
}
}
if (flags & TCL_ENCODING_CHAR_LIMIT) {
/* Caller should have specified the dest char limit */
Tcl_Obj *valueObj;
if (dstCharsVar == NULL ||
(valueObj = Tcl_ObjGetVar2(interp, dstCharsVar, NULL, 0)) == NULL
) {
Tcl_SetResult(interp,
"dstCharsVar must be specified with integer value if "
"TCL_ENCODING_CHAR_LIMIT set in flags.", TCL_STATIC);
return TCL_ERROR;
}
if (Tcl_GetIntFromObj(interp, valueObj, &dstChars) != TCL_OK) {
return TCL_ERROR;
}
} else {
dstChars = 0; /* Only used for output */
}
bufLen = dstLen + 4; /* 4 -> overflow detection */
bufPtr = (unsigned char *)Tcl_Alloc(bufLen);
memset(bufPtr, 0xFF, dstLen); /* Need to check nul terminator */
memmove(bufPtr + dstLen, "\xAB\xCD\xEF\xAB", 4); /* overflow detection */
bytes = Tcl_GetByteArrayFromObj(objv[3], &srcLen); /* Last! to avoid shimmering */
result = (*transformer)(interp, encoding, (const char *) bytes, srcLen, flags,
encStatePtr, (char *) bufPtr, dstLen,
srcReadVar ? &srcRead : NULL,
&dstWrote,
dstCharsVar ? &dstChars : NULL);
if (memcmp(bufPtr + bufLen - 4, "\xAB\xCD\xEF\xAB", 4)) {
Tcl_SetResult(interp,
"Tcl_ExternalToUtf wrote past output buffer",
TCL_STATIC);
result = TCL_ERROR;
} else if (result != TCL_ERROR) {
Tcl_Obj *resultObjs[3];
switch (result) {
case TCL_OK:
resultObjs[0] = Tcl_NewStringObj("ok", -1);
break;
case TCL_CONVERT_MULTIBYTE:
resultObjs[0] = Tcl_NewStringObj("multibyte", -1);
break;
case TCL_CONVERT_SYNTAX:
resultObjs[0] = Tcl_NewStringObj("syntax", -1);
break;
case TCL_CONVERT_UNKNOWN:
resultObjs[0] = Tcl_NewStringObj("unknown", -1);
break;
case TCL_CONVERT_NOSPACE:
resultObjs[0] = Tcl_NewStringObj("nospace", -1);
break;
default:
resultObjs[0] = Tcl_NewIntObj(result);
break;
}
result = TCL_OK;
resultObjs[1] =
encStatePtr ? Tcl_NewWideIntObj((Tcl_WideInt)encState) : Tcl_NewObj();
resultObjs[2] = Tcl_NewByteArrayObj(bufPtr, dstLen);
if (srcReadVar) {
if (Tcl_ObjSetVar2(interp,
srcReadVar,
NULL,
Tcl_NewIntObj(srcRead),
TCL_LEAVE_ERR_MSG) == NULL) {
result = TCL_ERROR;
}
}
if (dstWroteVar) {
if (Tcl_ObjSetVar2(interp,
dstWroteVar,
NULL,
Tcl_NewIntObj(dstWrote),
TCL_LEAVE_ERR_MSG) == NULL) {
result = TCL_ERROR;
}
}
if (dstCharsVar) {
if (Tcl_ObjSetVar2(interp,
dstCharsVar,
NULL,
Tcl_NewIntObj(dstChars),
TCL_LEAVE_ERR_MSG) == NULL) {
result = TCL_ERROR;
}
}
Tcl_SetObjResult(interp, Tcl_NewListObj(3, resultObjs));
}
ckfree(bufPtr);
Tcl_FreeEncoding(encoding); /* Free returned reference */
return result;
}
/*
*----------------------------------------------------------------------
@@ -2004,10 +2276,10 @@ TestencodingObjCmd(
const char *string;
TclEncoding *encodingPtr;
static const char *const optionStrings[] = {
"create", "delete", "nullength", NULL
"create", "delete", "nullength", "Tcl_ExternalToUtf", "Tcl_UtfToExternal", NULL
};
enum options {
ENC_CREATE, ENC_DELETE, ENC_NULLENGTH
ENC_CREATE, ENC_DELETE, ENC_NULLENGTH, ENC_EXTTOUTF, ENC_UTFTOEXT
};
if (objc < 2) {
@@ -2076,6 +2348,12 @@ TestencodingObjCmd(
Tcl_SetObjResult(interp,
Tcl_NewIntObj(Tcl_GetEncodingNulLength(encoding)));
Tcl_FreeEncoding(encoding);
break;
case ENC_EXTTOUTF:
return UtfExtWrapper(interp,Tcl_ExternalToUtf,objc,objv);
case ENC_UTFTOEXT:
return UtfExtWrapper(interp,Tcl_UtfToExternal,objc,objv);
}
return TCL_OK;
}
+19 -2
View File
@@ -1269,7 +1269,7 @@ TeststringobjCmd(
static const char *const options[] = {
"append", "appendstrings", "get", "get2", "length", "length2",
"set", "set2", "setlength", "maxchars", "range", "appendself",
"appendself2", NULL
"appendself2", "newunicode", NULL
};
if (objc < 3) {
@@ -1513,7 +1513,24 @@ TeststringobjCmd(
Tcl_AppendUnicodeToObj(varPtr[varIndex], unicode + length, size - length);
Tcl_SetObjResult(interp, varPtr[varIndex]);
break;
}
case 13: /* newunicode*/
unicode = (unsigned short *) ckalloc((objc - 3) * sizeof(unsigned short));
for (i = 0; i < (objc - 3); ++i) {
int val;
if (Tcl_GetIntFromObj(interp, objv[i + 3], &val) != TCL_OK) {
break;
}
unicode[i] = (unsigned short)val;
}
if (i < (objc-3)) {
ckfree(unicode);
return TCL_ERROR;
}
SetVarToObj(varPtr, varIndex, Tcl_NewUnicodeObj(unicode, objc - 3));
Tcl_SetObjResult(interp, varPtr[varIndex]);
ckfree(unicode);
break;
}
return TCL_OK;
}
+36 -35
View File
@@ -182,25 +182,22 @@ Invalid(
*
* Tcl_UniCharToUtf --
*
* Store the given Tcl_UniChar as a sequence of UTF-8 bytes in the
* Stores the given Tcl_UniChar as a sequence of UTF-8 bytes in the
* provided buffer. Equivalent to Plan 9 runetochar().
*
* Special handling of Surrogate pairs is handled as follows:
* When this function is called for ch being a high surrogate,
* the first byte of the 4-byte UTF-8 sequence is produced and
* the function returns 1. Calling the function again with a
* low surrogate, the remaining 3 bytes of the 4-byte UTF-8
* sequence is produced, and the function returns 3. The buffer
* is used to remember the high surrogate between the two calls.
* Surrogate pairs are handled as follows: When ch is a high surrogate,
* the first byte of the 4-byte UTF-8 sequence is stored in the buffer and
* the function returns 1. If the function is called again with a low
* surrogate and the same buffer, the remaining 3 bytes of the 4-byte
* UTF-8 sequence are produced.
*
* If no low surrogate follows the high surrogate (which is actually
* illegal), this can be handled reasonably by calling Tcl_UniCharToUtf
* again with ch = -1. This will produce a 3-byte UTF-8 sequence
* again with ch = -1. This produces a 3-byte UTF-8 sequence
* representing the high surrogate.
*
* Results:
* The return values is the number of bytes in the buffer that were
* consumed.
* Returns the number of bytes stored into the buffer.
*
* Side effects:
* None.
@@ -223,18 +220,19 @@ Tcl_UniCharToUtf(
}
if (ch >= 0) {
if (ch <= 0x7FF) {
buf[1] = (char) ((ch | 0x80) & 0xBF);
buf[0] = (char) ((ch >> 6) | 0xC0);
buf[1] = (char) (0x80 | (0x3F & ch));
buf[0] = (char) (0xC0 | (ch >> 6));
return 2;
}
if (ch <= 0xFFFF) {
if ((ch & 0xF800) == 0xD800) {
if (ch & 0x0400) {
/* Low surrogate */
if (((buf[0] & 0xC0) == 0x80) && ((buf[1] & 0xCF) == 0)) {
if ( (0x80 == (0xC0 & buf[0]))
&& (0 == (0xCF & buf[1]))) {
/* Previous Tcl_UniChar was a high surrogate, so combine */
buf[2] = (char) ((ch & 0x3F) | 0x80);
buf[1] |= (char) (((ch >> 6) & 0x0F) | 0x80);
buf[2] = (char) (0x80 | (0x3F & ch));
buf[1] |= (char) (0x80 | (0x0F & (ch >> 6)));
return 3;
}
/* Previous Tcl_UniChar was not a high surrogate, so just output */
@@ -244,37 +242,40 @@ Tcl_UniCharToUtf(
/* Fill buffer with specific 3-byte (invalid) byte combination,
so following low surrogate can recognize it and combine */
buf[2] = (char) ((ch << 4) & 0x30);
buf[1] = (char) (((ch >> 2) & 0x3F) | 0x80);
buf[0] = (char) (((ch >> 8) & 0x07) | 0xF0);
buf[1] = (char) (0x80 | (0x3F & (ch >> 2)));
buf[0] = (char) (0xF0 | (0x07 & (ch >> 8)));
return 1;
}
}
goto three;
}
if (ch <= 0x10FFFF) {
buf[3] = (char) ((ch | 0x80) & 0xBF);
buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF);
buf[1] = (char) (((ch >> 12) | 0x80) & 0xBF);
buf[0] = (char) ((ch >> 18) | 0xF0);
buf[3] = (char) (0x80 | (0x3F & ch));
buf[2] = (char) (0x80 | (0x3F & (ch >> 6)));
buf[1] = (char) (0x80 | (0x3F & (ch >> 12)));
buf[0] = (char) (0xF0 | (ch >> 18));
return 4;
}
} else if (ch == -1) {
if (((buf[0] & 0xC0) == 0x80) && ((buf[1] & 0xCF) == 0)
&& ((buf[-1] & 0xF8) == 0xF0)) {
ch = 0xD7C0 + ((buf[-1] & 0x07) << 8) + ((buf[0] & 0x3F) << 2)
+ ((buf[1] & 0x30) >> 4);
buf[1] = (char) ((ch | 0x80) & 0xBF);
buf[0] = (char) (((ch >> 6) | 0x80) & 0xBF);
buf[-1] = (char) ((ch >> 12) | 0xE0);
if ( (0x80 == (0xC0 & buf[0]))
&& (0 == (0xCF & buf[1]))
&& (0xF0 == (0xF8 & buf[-1]))) {
ch = 0xD7C0
+ ((0x07 & buf[-1]) << 8)
+ ((0x3F & buf[0]) << 2)
+ ((0x30 & buf[1]) >> 4);
buf[1] = (char) (0x80 | (0x3F & ch));
buf[0] = (char) (0x80 | (0x3F & (ch >> 6)));
buf[-1] = (char) (0xE0 | (ch >> 12));
return 2;
}
}
ch = 0xFFFD;
three:
buf[2] = (char) ((ch | 0x80) & 0xBF);
buf[1] = (char) (((ch >> 6) | 0x80) & 0xBF);
buf[0] = (char) ((ch >> 12) | 0xE0);
buf[2] = (char) (0x80 | (0x3F & ch));
buf[1] = (char) (0x80 | (0x3F & (ch >> 6)));
buf[0] = (char) (0xE0 | (ch >> 12));
return 3;
}
@@ -2948,7 +2949,7 @@ TclUniCharMatch(
*
* TclUtfToUCS4 --
*
* Extract the 4-byte codepoint from the leading bytes of the
* Extracts the 4-byte codepoint from the leading bytes of the
* Modified UTF-8 string "src". This is a utility routine to
* contain the surrogate gymnastics in one place.
*
@@ -2960,8 +2961,8 @@ TclUniCharMatch(
* enough bytes remain in the string.
*
* Results:
* *usc4Ptr is filled with the UCS4 code point, and the return value is
* the number of bytes from the UTF-8 string that were consumed.
* Fills *usc4Ptr with the UCS4 code point and returns the number of bytes
* consumed from the source string.
*
* Side effects:
* None.
+47 -9
View File
@@ -442,10 +442,25 @@ GenerateHeader(
if (GetValue(interp, dictObj, "comment", &value) != TCL_OK) {
goto error;
} else if (value != NULL) {
Tcl_EncodingState state;
valueStr = TclGetStringFromObj(value, &len);
Tcl_UtfToExternal(NULL, latin1enc, valueStr, len, 0, NULL,
result = Tcl_UtfToExternal(NULL, latin1enc, valueStr, len,
TCL_ENCODING_START|TCL_ENCODING_END|TCL_ENCODING_STOPONERROR, &state,
headerPtr->nativeCommentBuf, MAX_COMMENT_LEN-1, NULL, &len,
NULL);
if (result != TCL_OK) {
if (interp) {
if (result == TCL_CONVERT_UNKNOWN) {
Tcl_AppendResult(
interp, "Comment contains characters > 0xFF", NULL);
}
else {
Tcl_AppendResult(interp, "Comment too large for zip", NULL);
}
}
result = TCL_ERROR; /* TCL_CONVERT_* -> TCL_ERROR*/
goto error;
}
headerPtr->nativeCommentBuf[len] = '\0';
headerPtr->header.comment = (Bytef *) headerPtr->nativeCommentBuf;
if (extraSizePtr != NULL) {
@@ -463,9 +478,26 @@ GenerateHeader(
if (GetValue(interp, dictObj, "filename", &value) != TCL_OK) {
goto error;
} else if (value != NULL) {
Tcl_EncodingState state;
valueStr = TclGetStringFromObj(value, &len);
Tcl_UtfToExternal(NULL, latin1enc, valueStr, len, 0, NULL,
headerPtr->nativeFilenameBuf, MAXPATHLEN-1, NULL, &len, NULL);
result = Tcl_UtfToExternal(NULL, latin1enc, valueStr, len,
TCL_ENCODING_START|TCL_ENCODING_END|TCL_ENCODING_STOPONERROR, &state,
headerPtr->nativeFilenameBuf, MAXPATHLEN-1, NULL, &len,
NULL);
if (result != TCL_OK) {
if (interp) {
if (result == TCL_CONVERT_UNKNOWN) {
Tcl_AppendResult(
interp, "Filename contains characters > 0xFF", NULL);
}
else {
Tcl_AppendResult(
interp, "Filename too large for zip", NULL);
}
}
result = TCL_ERROR; /* TCL_CONVERT_* -> TCL_ERROR*/
goto error;
}
headerPtr->nativeFilenameBuf[len] = '\0';
headerPtr->header.name = (Bytef *) headerPtr->nativeFilenameBuf;
if (extraSizePtr != NULL) {
@@ -1196,7 +1228,8 @@ Tcl_ZlibStreamPut(
{
ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;
char *dataTmp = NULL;
int e, size, outSize, toStore;
int e;
int size, outSize, toStore;
unsigned char *bytes;
if (zshPtr->streamEnd) {
@@ -1325,7 +1358,8 @@ Tcl_ZlibStreamGet(
* may get less! */
{
ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;
int e, i, listLen, itemLen, dataPos = 0;
int e;
int i, listLen, itemLen, dataPos = 0;
Tcl_Obj *itemObj;
unsigned char *dataPtr, *itemPtr;
int existing;
@@ -1576,7 +1610,8 @@ Tcl_ZlibDeflate(
int level,
Tcl_Obj *gzipHeaderDictObj)
{
int wbits = 0, inLen = 0, e = 0, extraSize = 0;
int wbits = 0, e = 0, extraSize = 0;
int inLen = 0;
Byte *inData = NULL;
z_stream stream;
GzipHeader header;
@@ -1730,7 +1765,8 @@ Tcl_ZlibInflate(
int bufferSize,
Tcl_Obj *gzipHeaderDictObj)
{
int wbits = 0, inLen = 0, e = 0, newBufferSize;
int wbits = 0, e = 0;
int inLen = 0, newBufferSize;
Byte *inData = NULL, *outData = NULL, *newOutData = NULL;
z_stream stream;
gz_header header, *headerPtr = NULL;
@@ -2400,7 +2436,8 @@ ZlibPushSubcmd(
const char *const *pushOptions = pushDecompressOptions;
enum pushOptionsEnum {poDictionary, poHeader, poLevel, poLimit};
Tcl_Obj *headerObj = NULL, *compDictObj = NULL;
int limit = DEFAULT_BUFFER_SIZE, dummy;
int limit = DEFAULT_BUFFER_SIZE;
int dummy;
if (objc < 4) {
Tcl_WrongNumArgs(interp, 2, objv, "mode channel ?options...?");
@@ -2942,7 +2979,8 @@ ZlibTransformClose(
int flags)
{
ZlibChannelData *cd = (ZlibChannelData *)instanceData;
int e, written, result = TCL_OK;
int e, result = TCL_OK;
int written;
if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
return EINVAL;
+1 -1
View File
@@ -9,7 +9,7 @@ S
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E0000
0070007100720073007400750076007700780079007A007B007C007D007E007F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
+2 -2
View File
@@ -10,8 +10,8 @@ M
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
+2 -2
View File
@@ -10,8 +10,8 @@ S
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0083201E2026202020210088203001602039015A0164017D0179
009020182019201C201D202220132014009821220161203A015B0165017E017A
20AC0000201A0000201E2026202020210000203001602039015A0164017D0179
000020182019201C201D202220132014000021220161203A015B0165017E017A
00A002C702D8014100A4010400A600A700A800A9015E00AB00AC00AD00AE017B
00B000B102DB014200B400B500B600B700B80105015F00BB013D02DD013E017C
015400C100C2010200C40139010600C7010C00C9011800CB011A00CD00CE010E
+1 -1
View File
@@ -11,7 +11,7 @@ S
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
04020403201A0453201E20262020202120AC203004092039040A040C040B040F
045220182019201C201D202220132014009821220459203A045A045C045B045F
045220182019201C201D202220132014000021220459203A045A045C045B045F
00A0040E045E040800A4049000A600A7040100A9040400AB00AC00AD00AE0407
00B000B104060456049100B500B600B704512116045400BB0458040504550457
0410041104120413041404150416041704180419041A041B041C041D041E041F
+2 -2
View File
@@ -10,8 +10,8 @@ S
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030016020390152008D017D008F
009020182019201C201D20222013201402DC21220161203A0153009D017E0178
20AC0000201A0192201E20262020202102C620300160203901520000017D0000
000020182019201C201D20222013201402DC21220161203A01530000017E0178
00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF
00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF
+2 -2
View File
@@ -10,8 +10,8 @@ S
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202100882030008A2039008C008D008E008F
009020182019201C201D20222013201400982122009A203A009C009D009E009F
20AC0000201A0192201E20262020202100002030000020390000000000000000
000020182019201C201D202220132014000021220000203A0000000000000000
00A00385038600A300A400A500A600A700A800A9000000AB00AC00AD00AE2015
00B000B100B200B3038400B500B600B703880389038A00BB038C00BD038E038F
0390039103920393039403950396039703980399039A039B039C039D039E039F
+2 -2
View File
@@ -10,8 +10,8 @@ S
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030016020390152008D008E008F
009020182019201C201D20222013201402DC21220161203A0153009D009E0178
20AC0000201A0192201E20262020202102C62030016020390152000000000000
000020182019201C201D20222013201402DC21220161203A0153000000000178
00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF
00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF
+2 -2
View File
@@ -10,8 +10,8 @@ S
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030008A2039008C008D008E008F
009020182019201C201D20222013201402DC2122009A203A009C009D009E009F
20AC0000201A0192201E20262020202102C62030000020390000000000000000
000020182019201C201D20222013201402DC21220000203A0000000000000000
00A000A100A200A320AA00A500A600A700A800A900D700AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900F700BB00BC00BD00BE00BF
05B005B105B205B305B405B505B605B705B805B9000005BB05BC05BD05BE05BF
+2 -2
View File
@@ -10,8 +10,8 @@ S
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0083201E20262020202100882030008A2039008C00A802C700B8
009020182019201C201D20222013201400982122009A203A009C00AF02DB009F
20AC0000201A0000201E2026202020210000203000002039000000A802C700B8
000020182019201C201D202220132014000021220000203A000000AF02DB0000
00A0000000A200A300A4000000A600A700D800A9015600AB00AC00AD00AE00C6
00B000B100B200B300B400B500B600B700F800B9015700BB00BC00BD00BE00E6
0104012E0100010600C400C501180112010C00C90179011601220136012A013B
+2 -2
View File
@@ -10,8 +10,8 @@ S
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030008A20390152008D008E008F
009020182019201C201D20222013201402DC2122009A203A0153009D009E0178
20AC0000201A0192201E20262020202102C62030000020390152000000000000
000020182019201C201D20222013201402DC21220000203A0153000000000178
00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF
00C000C100C2010200C400C500C600C700C800C900CA00CB030000CD00CE00CF
+1 -1
View File
@@ -11,7 +11,7 @@ S
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
00B000B72219221A259225002502253C2524252C251C25342510250C25142518
03B2221E03C600B100BD00BC224800AB00BBFEF7FEF8009B009CFEFBFEFC009F
03B2221E03C600B100BD00BC224800AB00BBFEF7FEF800000000FEFBFEFC0000
00A000ADFE8200A300A4FE8400000000FE8EFE8FFE95FE99060CFE9DFEA1FEA5
0660066106620663066406650666066706680669FED1061BFEB1FEB5FEB9061F
00A2FE80FE81FE83FE85FECAFE8BFE8DFE91FE93FE97FE9BFE9FFEA3FEA7FEA9
+2 -2
View File
@@ -10,8 +10,8 @@ S
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850386008700B700AC00A620182019038820150389
038A03AA038C00930094038E03AB00A9038F00B200B303AC00A303AD03AE03AF
0000000000000000000000000386000000B700AC00A620182019038820150389
038A03AA038C00000000038E03AB00A9038F00B200B303AC00A303AD03AE03AF
03CA039003CC03CD039103920393039403950396039700BD0398039900AB00BB
25912592259325022524039A039B039C039D256325512557255D039E039F2510
25142534252C251C2500253C03A003A1255A25542569256625602550256C03A3
+2 -2
View File
@@ -10,8 +10,8 @@ S
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC008100820083008420260086008700880089008A008B008C008D008E008F
009020182019201C201D20222013201400980099009A009B009C009D009E009F
20AC000000000000000020260000000000000000000000000000000000000000
000020182019201C201D20222013201400000000000000000000000000000000
00A00E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F
0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F
0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F
+1 -1
View File
@@ -10,7 +10,7 @@ M
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080000000000000000000850086000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
+1 -1
View File
@@ -10,7 +10,7 @@ M
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
+2 -2
View File
@@ -10,8 +10,8 @@ M
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
+2 -2
View File
@@ -10,8 +10,8 @@ S
2730273127322733273427352736273727382739273A273B273C273D273E273F
2740274127422743274427452746274727482749274A274B25CF274D25A0274F
27502751275225B225BC25C6275625D727582759275A275B275C275D275E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000276127622763276427652766276726632666266526602460246124622463
2464246524662467246824692776277727782779277A277B277C277D277E277F
2780278127822783278427852786278727882789278A278B278C278D278E278F
+1
View File
@@ -1,3 +1,4 @@
# Encoding file: ebcdic, single-byte
S
006F 0 1
00
+2 -2
View File
@@ -10,8 +10,8 @@ M
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
+2 -2
View File
@@ -10,8 +10,8 @@ M
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D0000008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
+2 -2
View File
@@ -10,8 +10,8 @@ M
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
+2 -2
View File
@@ -10,8 +10,8 @@ S
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D203E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
+2 -2
View File
@@ -10,8 +10,8 @@ S
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D203E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
+2 -2
View File
@@ -10,8 +10,8 @@ S
2730273127322733273427352736273727382739273A273B273C273D273E273F
2740274127422743274427452746274727482749274A274B25CF274D25A0274F
27502751275225B225BC25C6275625D727582759275A275B275C275D275E007F
F8D7F8D8F8D9F8DAF8DBF8DCF8DDF8DEF8DFF8E0F8E1F8E2F8E3F8E4008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
F8D7F8D8F8D9F8DAF8DBF8DCF8DDF8DEF8DFF8E0F8E1F8E2F8E3F8E400000000
0000000000000000000000000000000000000000000000000000000000000000
0000276127622763276427652766276726632666266526602460246124622463
2464246524662467246824692776277727782779277A277B277C277D277E277F
2780278127822783278427852786278727882789278A278B278C278D278E278F
+1 -1
View File
@@ -10,7 +10,7 @@ M
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00A0FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
+1 -1
View File
@@ -10,7 +10,7 @@ M
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080000000000000000000850086008700000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
+2 -2
View File
@@ -10,8 +10,8 @@ S
03A0039803A103A303A403A503C203A9039E03A80396005B2234005D22A5005F
F8E503B103B203C703B403B503C603B303B703B903D503BA03BB03BC03BD03BF
03C003B803C103C303C403C503D603C903BE03C803B6007B007C007D223C007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000003D2203222642044221E0192266326662665266021942190219121922193
00B000B12033226500D7221D2202202200F72260226122482026F8E6F8E721B5
21352111211C21182297229522052229222A2283228722842282228622082209
+1 -1
View File
@@ -9,7 +9,7 @@ S
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E0000
0070007100720073007400750076007700780079007A007B007C007D007E007F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F
+1 -1
View File
@@ -12,7 +12,7 @@ apply {{dir} {
0 tcl::idna 1.0.1 {cookiejar idna.tcl}
0 platform 1.0.19 {platform platform.tcl}
0 platform::shell 1.1.4 {platform shell.tcl}
1 tcltest 2.5.5 {tcltest tcltest.tcl}
1 tcltest 2.5.6 {tcltest tcltest.tcl}
} {
if {$isafe && !$safe} continue
package ifneeded $package $version [list source [file join $dir {*}$file]]
+1 -1
View File
@@ -9,4 +9,4 @@
# full path name of this file's directory.
if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded tcltest 2.5.5 [list source [file join $dir tcltest.tcl]]
package ifneeded tcltest 2.5.6 [list source [file join $dir tcltest.tcl]]
+36 -3
View File
@@ -22,7 +22,7 @@ namespace eval tcltest {
# When the version number changes, be sure to update the pkgIndex.tcl file,
# and the install directory in the Makefiles. When the minor version
# changes (new feature) be sure to update the man page as well.
variable Version 2.5.5
variable Version 2.5.6
# Compatibility support for dumb variables defined in tcltest 1
# Do not use these. Call [package provide Tcl] and [info patchlevel]
@@ -1134,6 +1134,39 @@ proc tcltest::SafeFetch {n1 n2 op} {
}
}
# tcltest::Asciify --
#
# Transforms the passed string to contain only printable ascii characters.
# Useful for printing to terminals. Non-printables are mapped to
# \x, \u or \U sequences.
#
# Arguments:
# s - string to transform
#
# Results:
# The transformed strings
#
# Side effects:
# None.
proc tcltest::Asciify {s} {
set print ""
foreach c [split $s ""] {
set i [scan $c %c]
if {[string is print $c] && ($i <= 127)} {
append print $c
} elseif {$i <= 0xFF} {
append print \\x[format %02X $i]
} elseif {$i <= 0xFFFF} {
append print \\u[format %04X $i]
} else {
append print \\U[format %08X $i]
}
}
return $print
}
# tcltest::ConstraintInitializer --
#
# Get or set a script that when evaluated in the tcltest namespace
@@ -2221,9 +2254,9 @@ proc tcltest::test {name description args} {
if {$scriptCompare} {
puts [outputChannel] "---- Error testing result: $scriptMatch"
} else {
puts [outputChannel] "---- Result was:\n$actualAnswer"
puts [outputChannel] "---- Result was:\n[Asciify $actualAnswer]"
puts [outputChannel] "---- Result should have been\
($match matching):\n$result"
($match matching):\n[Asciify $result]"
}
}
if {$errorCodeFailure} {
+1 -1
View File
@@ -348,7 +348,7 @@ test basic-20.2 {Tcl_GetCommandInfo, names for commands created outside namespac
test basic-20.3 {Tcl_GetCommandInfo, #-quoting} testcmdtoken {
catch {rename \# ""}
set x [testcmdtoken create \#]
testcmdtoken name $x
return [testcmdtoken name $x]
} {{#} ::#}
test basic-21.1 {Tcl_GetCommandName} {emptyTest} {
+24 -22
View File
@@ -50,6 +50,8 @@ namespace eval ::tcl::test::io {
testConstraint notWinCI [expr {
$::tcl_platform(platform) ne "windows" || ![info exists ::env(CI)]}]
testConstraint notOSX [expr {$::tcl_platform(os) ne "Darwin"}]
# File permissions broken on wsl without some "exotic" wsl configuration
testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]
testConstraint specialfiles [expr {[file exists /dev/zero] || [file exists NUL]}]
# You need a *very* special environment to do some tests. In particular,
@@ -119,7 +121,7 @@ test chan-io-1.6 {Tcl_WriteChars: WriteBytes} {
chan puts -nonewline $f "a\x4D\x00"
chan close $f
contents $path(test1)
} "aM\x00"
} aM\x00
test chan-io-1.7 {Tcl_WriteChars: WriteChars} {
set f [open $path(test1) w]
chan configure $f -encoding shiftjis
@@ -284,7 +286,7 @@ test chan-io-3.6 {WriteChars: (stageRead + dstWrote == 0)} -body {
# last byte of A plus the all of B) appended.
set f [open $path(test1) w]
chan configure $f -encoding shiftjis -buffersize 16
chan puts -nonewline $f "12345678901234AB"
chan puts -nonewline $f 12345678901234AB
set x [list [contents $path(test1)]]
chan close $f
lappend x [contents $path(test1)]
@@ -1216,7 +1218,7 @@ test chan-io-8.7 {PeekAhead: cleanup} -setup {
chan puts -nonewline $f "abcdefghijklmno\r"
# here
lappend x [chan gets $f line] $line [testchannel queuedcr $f]
chan puts -nonewline $f "\x1A"
chan puts -nonewline $f \x1A
lappend x [chan gets $f line] $line
} -cleanup {
chan close $f
@@ -1372,22 +1374,22 @@ test chan-io-12.4 {ReadChars: split-up char} -setup {
chan configure $f -encoding shiftjis
vwait [namespace which -variable x]
chan configure $f -encoding binary -blocking 1
chan puts -nonewline $f "\x7B"
chan puts -nonewline $f \x7B
after 500 ;# Give the cat process time to catch up
chan configure $f -encoding shiftjis -blocking 0
vwait [namespace which -variable x]
return $x
} -cleanup {
chan close $f
} -result [list "123456789012345" 1 "本" 0]
} -result [list "123456789012345" 1 本 0]
test chan-io-12.5 {ReadChars: chan events on partial characters} -setup {
variable x {}
} -constraints {stdio fileevent} -body {
set path(test1) [makeFile {
chan configure stdout -encoding binary -buffering none
chan gets stdin; chan puts -nonewline "\xE7"
chan gets stdin; chan puts -nonewline "\x89"
chan gets stdin; chan puts -nonewline "\xA6"
chan gets stdin; chan puts -nonewline \xE7
chan gets stdin; chan puts -nonewline \x89
chan gets stdin; chan puts -nonewline \xA6
} test1]
set f [openpipe r+ $path(test1)]
chan event $f readable [namespace code {
@@ -4980,7 +4982,7 @@ test chan-io-38.2 {Tcl_SetChannelBufferSize, Tcl_GetChannelBufferSize} -setup {
test chan-io-38.3 {Tcl_SetChannelBufferSize, changing buffersize between reads} {
# This test crashes the interp if Bug #427196 is not fixed
set chan [open [info script] r]
chan configure $chan -buffersize 10
chan configure $chan -buffersize 10 -encoding utf-8
set var [chan read $chan 2]
chan configure $chan -buffersize 32
append var [chan read $chan]
@@ -5211,7 +5213,7 @@ test chan-io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_
} -constraints {stdio fileevent} -body {
set f [openpipe r+ $path(cat)]
chan configure $f -encoding binary
chan puts -nonewline $f "\xE7"
chan puts -nonewline $f \xE7
chan flush $f
chan configure $f -encoding utf-8 -blocking 0
chan event $f readable [namespace code { lappend x [chan read $f] }]
@@ -5348,7 +5350,7 @@ test chan-io-40.1 {POSIX open access modes: RDWR} -setup {
} -result {zzy abzzy}
test chan-io-40.2 {POSIX open access modes: CREAT} -setup {
file delete $path(test3)
} -constraints {unix} -body {
} -constraints {unix notWsl} -body {
set f [open $path(test3) {WRONLY CREAT} 0o600]
file stat $path(test3) stats
set x [format 0o%03o [expr {$stats(mode) & 0o777}]]
@@ -5361,7 +5363,7 @@ test chan-io-40.2 {POSIX open access modes: CREAT} -setup {
} -result {0o600 {line 1}}
test chan-io-40.3 {POSIX open access modes: CREAT} -setup {
file delete $path(test3)
} -constraints {unix umask} -body {
} -constraints {unix umask notWsl} -body {
# This test only works if your umask is 2, like ouster's.
chan close [open $path(test3) {WRONLY CREAT}]
file stat $path(test3) stats
@@ -6736,8 +6738,8 @@ test chan-io-52.5 {TclCopyChannel, all} -constraints {fcopy} -setup {
} -body {
set f1 [open $thisScript]
set f2 [open $path(test1) w]
chan configure $f1 -translation lf -blocking 0
chan configure $f2 -translation lf -blocking 0
chan configure $f1 -translation lf -encoding iso8859-1 -blocking 0
chan configure $f2 -translation lf -encoding iso8859-1 -blocking 0
chan copy $f1 $f2 -size -1 ;# -1 means 'copy all', same as if no -size specified.
set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
chan close $f1
@@ -6752,8 +6754,8 @@ test chan-io-52.5a {TclCopyChannel, all, other negative value} -setup {
} -constraints {fcopy} -body {
set f1 [open $thisScript]
set f2 [open $path(test1) w]
chan configure $f1 -translation lf -blocking 0
chan configure $f2 -translation lf -blocking 0
chan configure $f1 -translation lf -encoding iso8859-1 -blocking 0
chan configure $f2 -translation lf -encoding iso8859-1 -blocking 0
chan copy $f1 $f2 -size -2 ;# < 0 behaves like -1, copy all
set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
chan close $f1
@@ -6768,8 +6770,8 @@ test chan-io-52.5b {TclCopyChannel, all, wrap to negative value} -setup {
} -constraints {fcopy} -body {
set f1 [open $thisScript]
set f2 [open $path(test1) w]
chan configure $f1 -translation lf -blocking 0
chan configure $f2 -translation lf -blocking 0
chan configure $f1 -translation lf -encoding iso8859-1 -blocking 0
chan configure $f2 -translation lf -encoding iso8859-1 -blocking 0
chan copy $f1 $f2 -size 3221176172 ;# Wrapped to < 0, behaves like -1, copy all
set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
chan close $f1
@@ -6802,8 +6804,8 @@ test chan-io-52.7 {TclCopyChannel} -constraints {fcopy} -setup {
} -body {
set f1 [open $thisScript]
set f2 [open $path(test1) w]
chan configure $f1 -translation lf -blocking 0
chan configure $f2 -translation lf -blocking 0
chan configure $f1 -translation lf -encoding iso8859-1 -blocking 0
chan configure $f2 -translation lf -encoding iso8859-1 -blocking 0
chan copy $f1 $f2
set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
if {[file size $thisScript] == [file size $path(test1)]} {
@@ -6848,7 +6850,7 @@ set path(utf8-rp.txt) [makeFile {} utf8-rp.txt]
# Create kyrillic file, use lf translation to avoid os eol issues
set out [open $path(kyrillic.txt) w]
chan configure $out -encoding koi8-r -translation lf
chan puts $out "АА"
chan puts $out АА
chan close $out
test chan-io-52.9 {TclCopyChannel & encodings} {fcopy} {
# Copy kyrillic to UTF-8, using chan copy.
@@ -6886,7 +6888,7 @@ test chan-io-52.10 {TclCopyChannel & encodings} {fcopy} {
test chan-io-52.11 {TclCopyChannel & encodings} -setup {
set f [open $path(utf8-fcopy.txt) w]
fconfigure $f -encoding utf-8 -translation lf
puts $f "АА"
puts $f АА
close $f
} -constraints {fcopy} -body {
# binary to encoding => the input has to be in utf-8 to make sense to the
+5 -3
View File
@@ -32,6 +32,8 @@ testConstraint linkDirectory [expr {
&& [lindex [file system [temporaryDirectory]] 1] eq "NTFS")
}]
testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}]
# File permissions broken on wsl without some "exotic" wsl configuration
testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]
global env
set cmdAHwd [pwd]
@@ -1019,7 +1021,7 @@ test cmdAH-16.2 {Tcl_FileObjCmd: readable} {
-result 1
}
test cmdAH-16.3 {Tcl_FileObjCmd: readable} {
-constraints {unix notRoot testchmod}
-constraints {unix notRoot testchmod notWsl}
-setup {testchmod 0o333 $gorpfile}
-body {file readable $gorpfile}
-result 0
@@ -1052,7 +1054,7 @@ set gorpfile [makeFile abcde gorp.file]
test cmdAH-18.1 {Tcl_FileObjCmd: executable} -returnCodes error -body {
file executable a b
} -result {wrong # args: should be "file executable name"}
test cmdAH-18.2 {Tcl_FileObjCmd: executable} {notRoot} {
test cmdAH-18.2 {Tcl_FileObjCmd: executable} {notRoot notWsl} {
file executable $gorpfile
} 0
test cmdAH-18.3 {Tcl_FileObjCmd: executable} {unix testchmod} {
@@ -1600,7 +1602,7 @@ test cmdAH-28.4 {Tcl_FileObjCmd: stat} -setup {
file stat $gorpfile stat
list $stat(nlink) $stat(size) $stat(type)
} -result {1 12 file}
test cmdAH-28.5 {Tcl_FileObjCmd: stat} -constraints {unix} -setup {
test cmdAH-28.5 {Tcl_FileObjCmd: stat} -constraints {unix notWsl} -setup {
unset -nocomplain stat
} -body {
file stat $gorpfile stat
+32
View File
@@ -211,6 +211,38 @@ test dstring-2.15 {appending list elements} -constraints testdstring -setup {
} -cleanup {
testdstring free
} -result {x #}
test dstring-2.16 {appending list elements - bug [46dda6fc29] segfault} -constraints testdstring -setup {
testdstring free
} -body {
testdstring element "\\\n"; # Will setfault
testdstring get
} -cleanup {
testdstring free
} -result \\\\\\n
test dstring-2.17 {appending list elements - bug [46dda6fc29] segfault} -constraints testdstring -setup {
testdstring free
} -body {
testdstring element "\\\{"; # Will setfault
testdstring get
} -cleanup {
testdstring free
} -result [list [list \{]]
test dstring-2.18 {appending list elements - bug [46dda6fc29] segfault} -constraints testdstring -setup {
testdstring free
} -body {
testdstring element "\\\}"; # Will setfault
testdstring get
} -cleanup {
testdstring free
} -result [list [list \}]]
test dstring-2.19 {appending list elements - bug [46dda6fc29] segfault} -constraints testdstring -setup {
testdstring free
} -body {
testdstring element "\\\\"; # Will setfault
testdstring get
} -cleanup {
testdstring free
} -result [list [list \\]]
test dstring-3.1 {nested sublists} -constraints testdstring -setup {
testdstring free
+196 -13
View File
@@ -171,7 +171,7 @@ test encoding-6.2 {Tcl_CreateEncoding: replace encoding} {testencoding} {
test encoding-7.1 {Tcl_ExternalToUtfDString: small buffer} {
encoding convertfrom jis0208 8c8c8c8c
} "吾吾吾吾"
} 吾吾吾吾
test encoding-7.2 {Tcl_UtfToExternalDString: big buffer} {
set a 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C
append a $a
@@ -193,7 +193,7 @@ test encoding-8.1 {Tcl_ExternalToUtf} {
close $f
file delete [file join [temporaryDirectory] dummy]
return $x
} "ab乎g"
} ab乎g
test encoding-9.1 {Tcl_UtfToExternalDString: small buffer} {
encoding convertto jis0208 "吾吾吾吾"
@@ -213,7 +213,7 @@ test encoding-9.2 {Tcl_UtfToExternalDString: big buffer} {
test encoding-10.1 {Tcl_UtfToExternal} {
set f [open [file join [temporaryDirectory] dummy] w]
fconfigure $f -translation binary -encoding shiftjis
puts -nonewline $f "ab乎g"
puts -nonewline $f ab乎g
close $f
set f [open [file join [temporaryDirectory] dummy] r]
fconfigure $f -translation binary -encoding iso8859-1
@@ -248,7 +248,7 @@ test encoding-11.1 {LoadEncodingFile: unknown encoding} {testencoding} {
} {1 {unknown encoding "jis0208"} 8C}
test encoding-11.2 {LoadEncodingFile: single-byte} {
encoding convertfrom jis0201 \xA1
} "。"
} 。
test encoding-11.3 {LoadEncodingFile: double-byte} {
encoding convertfrom jis0208 8C
} 乎
@@ -452,6 +452,27 @@ test encoding-15.24 {UtfToUtfProc CESU-8 bug [048dd20b4171c8da]} {
binary scan $y H* z
list [string length $y] $z
} {2 cfbf}
test encoding-15.25 {UtfToUtfProc CESU-8} {
encoding convertfrom cesu-8 \x00
} \x00
test encoding-15.26 {UtfToUtfProc CESU-8} {
encoding convertfrom cesu-8 \xC0\x80
} \x00
test encoding-15.27 {UtfToUtfProc -strict CESU-8} {
encoding convertfrom -strict cesu-8 \x00
} \x00
test encoding-15.28 {UtfToUtfProc -strict CESU-8} -body {
encoding convertfrom -strict cesu-8 \xC0\x80
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xC0'}
test encoding-15.29 {UtfToUtfProc CESU-8} {
encoding convertto cesu-8 \x00
} \x00
test encoding-15.30 {UtfToUtfProc -strict CESU-8} {
encoding convertto -strict cesu-8 \x00
} \x00
test encoding-15.31 {UtfToUtfProc -strict CESU-8 (bytes F0-F4 are invalid)} -body {
encoding convertfrom -strict cesu-8 \xF1\x86\x83\x9C
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xF1'}
test encoding-16.1 {Utf16ToUtfProc} -body {
set val [encoding convertfrom utf-16 NN]
@@ -481,11 +502,83 @@ test encoding-16.7 {Utf32ToUtfProc} -body {
set val [encoding convertfrom utf-32be \0\0NN]
list $val [format %x [scan $val %c]]
} -result "乎 4e4e"
test encoding-16.8 {Utf32ToUtfProc} -body {
set val [encoding convertfrom -nocomplain utf-32 \x41\x00\x00\x41]
list $val [format %x [scan $val %c]]
} -result "\uFFFD fffd"
test encoding-16.9 {Utf32ToUtfProc} -body {
encoding convertfrom utf-32le \x00\xD8\x00\x00
} -result \uD800
test encoding-16.10 {Utf32ToUtfProc} -body {
encoding convertfrom utf-32le \x00\xDC\x00\x00
} -result \uDC00
test encoding-16.11 {Utf32ToUtfProc} -body {
encoding convertfrom utf-32le \x00\xD8\x00\x00\x00\xDC\x00\x00
} -result \uD800\uDC00
test encoding-16.12 {Utf32ToUtfProc} -body {
encoding convertfrom utf-32le \x00\xDC\x00\x00\x00\xD8\x00\x00
} -result \uDC00\uD800
test encoding-16.13 {Utf16ToUtfProc} -body {
encoding convertfrom utf-16le \x00\xD8
} -result \uD800
test encoding-16.14 {Utf16ToUtfProc} -body {
encoding convertfrom utf-16le \x00\xDC
} -result \uDC00
test encoding-16.15 {Utf16ToUtfProc} -body {
encoding convertfrom utf-16le \x00\xD8\x00\xDC
} -result \uD800\uDC00
test encoding-16.16 {Utf16ToUtfProc} -body {
encoding convertfrom utf-16le \x00\xDC\x00\xD8
} -result \uDC00\uD800
test encoding-16.17 {Utf32ToUtfProc} -body {
list [encoding convertfrom -strict -failindex idx utf-32le \x41\x00\x00\x00\x00\xD8\x00\x00\x42\x00\x00\x00] [set idx]
} -result {A 4}
test encoding-16.18 {
Utf16ToUtfProc, Tcl_UniCharToUtf, surrogate pairs in utf-16
} -body {
apply [list {} {
for {set i 0xD800} {$i < 0xDBFF} {incr i} {
for {set j 0xDC00} {$j < 0xDFFF} {incr j} {
set string [binary format S2 [list $i $j]]
set status [catch {
set decoded [encoding convertfrom utf-16be $string]
set encoded [encoding convertto utf-16be $decoded]
}]
if {$status || ( $encoded ne $string )} {
return [list [format %x $i] [format %x $j]]
}
}
}
return done
} [namespace current]]
} -result done
test encoding-16.19 {Utf16ToUtfProc, bug [d19fe0a5b]} -body {
encoding convertfrom utf-16 "\x41\x41\x41"
} -result \u4141\uFFFD
test encoding-16.20 {Utf16ToUtfProc, bug [d19fe0a5b]} -constraints deprecated -body {
encoding convertfrom utf-16 "\xD8\xD8"
} -result \uD8D8
test encoding-16.21 {Utf16ToUtfProc, bug [d19fe0a5b]} -body {
encoding convertfrom utf-32 "\x00\x00\x00\x00\x41\x41"
} -result \x00\uFFFD
test encoding-16.22 {Utf16ToUtfProc, strict, bug [db7a085bd9]} -body {
encoding convertfrom -strict utf-16le \x00\xD8
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\x00'}
test encoding-16.23 {Utf16ToUtfProc, strict, bug [db7a085bd9]} -body {
encoding convertfrom -strict utf-16le \x00\xDC
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\x00'}
test encoding-16.24 {Utf32ToUtfProc} -body {
encoding convertfrom utf-32 "\xFF\xFF\xFF\xFF"
} -result \uFFFD
test encoding-16.25 {Utf32ToUtfProc} -body {
encoding convertfrom utf-32 "\x01\x00\x00\x01"
} -result \uFFFD
test encoding-17.1 {UtfToUtf16Proc} -body {
encoding convertto utf-16 "\U460DC"
} -result "\xD8\xD8\xDC\xDC"
test encoding-17.2 {UtfToUcs2Proc} -body {
test encoding-17.2 {UtfToUcs2Proc, invalid testcase, see [5607d6482c]} -constraints deprecated -body {
encoding convertfrom utf-16 [encoding convertto ucs-2 "\U460DC"]
} -result "\uFFFD"
test encoding-17.3 {UtfToUtf16Proc} -body {
@@ -512,15 +605,50 @@ test encoding-17.9 {Utf32ToUtfProc} -body {
test encoding-17.10 {Utf32ToUtfProc} -body {
encoding convertfrom -nocomplain utf-32 "\xFF\xFF\xFF\xFF"
} -result \uFFFD
test encoding-17.11 {Utf32ToUtfProc} -body {
encoding convertfrom -strict utf-32le "\x00\xD8\x00\x00"
} -returnCodes error -result {unexpected byte sequence starting at index 0: '\x00'}
test encoding-17.12 {Utf32ToUtfProc} -body {
encoding convertfrom -strict utf-32le "\x00\xDC\x00\x00"
} -returnCodes error -result {unexpected byte sequence starting at index 0: '\x00'}
test encoding-18.1 {TableToUtfProc error on invalid input with -strict} -body {
test encoding-18.1 {TableToUtfProc on invalid input} -constraints deprecated -body {
list [catch {encoding convertto jis0208 \\} res] $res
} -result {0 !)}
test encoding-18.2 {TableToUtfProc on invalid input with -strict} -body {
list [catch {encoding convertto -strict jis0208 \\} res] $res
} -result {1 {unexpected character at index 0: 'U+00005C'}}
test encoding-18.3 {TableToUtfProc on invalid input with -strict -failindex} -body {
list [catch {encoding convertto -strict -failindex pos jis0208 \\} res] $res $pos
} -result {0 {} 0}
test encoding-18.4 {TableToUtfProc on invalid input with -failindex -strict} -body {
list [catch {encoding convertto -failindex pos -strict jis0208 \\} res] $res $pos
} -result {0 {} 0}
test encoding-18.5 {TableToUtfProc on invalid input with -failindex} -body {
list [catch {encoding convertto -failindex pos jis0208 \\} res] $res $pos
} -result {0 {} 0}
test encoding-18.6 {TableToUtfProc on invalid input with -nocomplain} -body {
list [catch {encoding convertto -nocomplain jis0208 \\} res] $res
} -result {0 !)}
test encoding-19.1 {TableFromUtfProc} {
} {}
test encoding-19.1 {TableFromUtfProc} -body {
encoding convertfrom ascii AÁ
} -result AÁ
test encoding-19.2 {TableFromUtfProc} -body {
encoding convertfrom -nocomplain ascii AÁ
} -result AÁ
test encoding-19.3 {TableFromUtfProc} -body {
encoding convertfrom -strict ascii AÁ
} -returnCodes 1 -result {unexpected byte sequence starting at index 1: '\xC1'}
test encoding-19.4 {TableFromUtfProc} -body {
list [encoding convertfrom -failindex idx ascii AÁ] [set idx]
} -result {A 1}
test encoding-19.5 {TableFromUtfProc} -body {
list [encoding convertfrom -failindex idx -strict ascii AÁ] [set idx]
} -result {A 1}
test encoding-19.6 {TableFromUtfProc} -body {
list [encoding convertfrom -failindex idx -strict ascii AÁB] [set idx]
} -result {A 1}
test encoding-20.1 {TableFreefProc} {
} {}
@@ -663,7 +791,7 @@ test encoding-24.14 {Parse valid or invalid utf-8} {
} 1
test encoding-24.15 {Parse valid or invalid utf-8} -constraints deprecated -body {
encoding convertfrom utf-8 "Z\xE0\x80"
} -result Z\xE0\x80
} -result Z\xE0\u20AC
test encoding-24.16 {Parse valid or invalid utf-8} -constraints testbytestring -body {
encoding convertto utf-8 [testbytestring "Z\u4343\x80"]
} -returnCodes 1 -result {expected byte sequence but character 1 was '䍃€' (U+004343)}
@@ -739,6 +867,21 @@ test encoding-24.39 {Try to generate invalid utf-8 with -strict} -body {
test encoding-24.40 {Try to generate invalid utf-8 with -nocomplain} -body {
encoding convertto -nocomplain utf-8 \uD800
} -result \xED\xA0\x80
test encoding-24.41 {Parse invalid utf-8 with -strict} -body {
encoding convertfrom -strict utf-8 \xED\xA0\x80\xED\xB0\x80
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xED'}
test encoding-24.42 {Parse invalid utf-8, fallback to cp1252 [885c86a9a0]} -body {
encoding convertfrom -nocomplain utf-8 \xF0\x80\x80\x80
} -result \xF0\u20AC\u20AC\u20AC
test encoding-24.43 {Parse invalid utf-8, fallback to cp1252 [885c86a9a0]} -body {
encoding convertfrom -nocomplain utf-8 \x80
} -result \u20AC
test encoding-24.44 {Try to generate invalid ucs-2 with -strict} -body {
encoding convertto -strict ucs-2 \uD800
} -returnCodes 1 -result {unexpected character at index 0: 'U+00D800'}
test encoding-24.45 {Try to generate invalid ucs-2 with -strict} -body {
encoding convertto -strict ucs-2 \U10000
} -returnCodes 1 -result {unexpected character at index 0: 'U+010000'}
file delete [file join [temporaryDirectory] iso2022.txt]
@@ -893,7 +1036,9 @@ test encoding-27.2 {encoding dirs basic behavior} -returnCodes error -body {
test encoding-28.0 {all encodings load} -body {
set string hello
foreach name [encoding names] {
incr count
if {$name ne "unicode"} {
incr count
}
encoding convertto -nocomplain $name $string
# discard the cached internal representation of Tcl_Encoding
@@ -901,10 +1046,48 @@ test encoding-28.0 {all encodings load} -body {
llength $name
}
return $count
} -result [expr {[info exists ::tcl_precision] ? 92 : 91}]
} -result 91
runtests
test encoding-bug-183a1adcc0-1 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
testencoding
} -body {
# Note - buffers are initialized to \xff
list [catch {testencoding Tcl_UtfToExternal utf-16 A {start end} {} 1} result] $result
} -result [list 0 [list nospace {} \xff]]
test encoding-bug-183a1adcc0-2 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
testencoding
} -body {
# Note - buffers are initialized to \xff
list [catch {testencoding Tcl_UtfToExternal utf-16 A {start end} {} 0} result] $result
} -result [list 0 [list nospace {} {}]]
test encoding-bug-183a1adcc0-3 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
testencoding
} -body {
# Note - buffers are initialized to \xff
list [catch {testencoding Tcl_UtfToExternal utf-16 A {start end} {} 2} result] $result
} -result [list 0 [list nospace {} \x00\x00]]
test encoding-bug-183a1adcc0-4 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
testencoding
} -body {
# Note - buffers are initialized to \xff
list [catch {testencoding Tcl_UtfToExternal utf-16 A {start end} {} 3} result] $result
} -result [list 0 [list nospace {} \x00\x00\xff]]
test encoding-bug-183a1adcc0-5 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
testencoding ucs2 knownBug
} -body {
# The knownBug constraint is because test depends on TCL_UTF_MAX and
# also UtfToUtf16 assumes space required in destination buffer is
# sizeof(Tcl_UniChar) which is incorrect when TCL_UTF_MAX==4
# Note - buffers are initialized to \xff
list [catch {testencoding Tcl_UtfToExternal utf-16 A {start end} {} 4} result] $result
} -result [list 0 [list ok {} [expr {$::tcl_platform(byteOrder) eq "littleEndian" ? "\x41\x00" : "\x00\x41"}]\x00\x00]]
}
test encoding-29.0 {get encoding nul terminator lengths} -constraints {
+124 -55
View File
@@ -27,7 +27,7 @@ testConstraint winLessThan10 0
testConstraint notNetworkFilesystem 0
testConstraint reg 0
if {[testConstraint win]} {
catch {
if {[catch {
# Is the registry extension already static to this shell?
try {
load {} Registry
@@ -38,10 +38,16 @@ if {[testConstraint win]} {
load $::reglib Registry
}
testConstraint reg 1
} regError]} {
catch {package require registry; testConstraint reg 1}
}
}
testConstraint notInCIenv [expr {![info exists ::env(CI)] || !$::env(CI)}]
# File permissions broken on wsl without some "exotic" wsl configuration
testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]
set tmpspace /tmp;# default value
# Find a group that exists on this Unix system, or else skip tests that
# require Unix groups.
@@ -97,6 +103,45 @@ if {[testConstraint unix]} {
}
}
# Try getting a lower case glob pattern that will match the home directory of
# a given user to test ~user and [file tildeexpand ~user]. Note this may not
# be the same as ~ even when "user" is current user. For example, on Unix
# platforms ~ will return HOME envvar, but ~user will lookup password file
# bypassing HOME. If home directory not found, returns *$user* so caller can
# succeed by using glob matching under the hope that the path contains
# the user name.
proc gethomedirglob {user} {
if {[testConstraint unix]} {
if {![catch {
exec {*}[auto_execok sh] -c "echo ~$user"
} home]} {
set home [string trim $home]
if {$home ne ""} {
# Expect exact match (except case), no glob * added
return [string tolower $home]
}
}
} elseif {[testConstraint reg]} {
# Windows with registry extension loaded
if {![catch {
set sid [exec {*}[auto_execok powershell] -Command "(Get-LocalUser -Name '$user')\[0\].sid.Value"]
set sid [string trim $sid]
# Get path from the Windows registry
set home [registry get "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\$sid" ProfileImagePath]
set home [string trim [string tolower $home]]
} result]} {
if {$home ne ""} {
# file join for \ -> /
return [file join [string tolower $home]]
}
}
}
# Caller will need to use glob matching and hope user
# name is in the home directory path
return *[string tolower $user]*
}
proc createfile {file {string a}} {
set f [open $file w]
puts -nonewline $f $string
@@ -354,7 +399,7 @@ test fCmd-4.10 {TclFileMakeDirsCmd: exists, is dir} -setup {
} -result {1 1}
test fCmd-4.11 {TclFileMakeDirsCmd: doesn't exist: errno != ENOENT} -setup {
cleanup
} -constraints {unix notRoot testchmod} -returnCodes error -body {
} -constraints {unix notRoot testchmod notWsl} -returnCodes error -body {
file mkdir td1/td2/td3
testchmod 0 td1/td2
file mkdir td1/td2/td3/td4
@@ -372,7 +417,7 @@ test fCmd-4.13 {TclFileMakeDirsCmd: doesn't exist: errno == ENOENT} -setup {
test fCmd-4.14 {TclFileMakeDirsCmd: TclpCreateDirectory fails} -setup {
cleanup
file delete -force foo
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
file mkdir foo
file attr foo -perm 0o40000
file mkdir foo/tf1
@@ -384,7 +429,7 @@ test fCmd-4.16 {TclFileMakeDirsCmd: TclpCreateDirectory succeeds} -setup {
} -constraints {notRoot} -body {
file mkdir tf1
file exists tf1
} -result {1}
} -result 1
test fCmd-5.1 {TclFileDeleteCmd: FileForceOption fails} -constraints {notRoot} -body {
file delete -xyz
@@ -497,7 +542,7 @@ test fCmd-6.5 {CopyRenameOneFile: lstat(target) != 0} -setup {
} -result {tf2}
test fCmd-6.6 {CopyRenameOneFile: errno != ENOENT} -setup {
cleanup
} -constraints {unix notRoot testchmod} -body {
} -constraints {unix notRoot testchmod notWsl} -body {
file mkdir td1
testchmod 0 td1
createfile tf1
@@ -616,7 +661,7 @@ test fCmd-6.22 {CopyRenameOneFile: copy/rename: !S_ISDIR(source)} -setup {
} -result [file join $tmpspace tf1]
test fCmd-6.23 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
cleanup $tmpspace
} -constraints {xdev notRoot} -body {
} -constraints {xdev notRoot notWsl} -body {
file mkdir td1/td2/td3
file attributes td1 -permissions 0
file rename td1 $tmpspace
@@ -668,7 +713,7 @@ test fCmd-6.27 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
} -match glob -result {error renaming "td1" to "/tmp/tcl*/td1": file already exists}
test fCmd-6.28 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
cleanup $tmpspace
} -constraints {notRoot xdev} -body {
} -constraints {notRoot xdev notWsl} -body {
file mkdir td1/td2/td3
file attributes td1/td2/td3 -permissions 0
file rename td1 $tmpspace
@@ -685,7 +730,7 @@ test fCmd-6.29 {CopyRenameOneFile: TclpCopyDirectory passed} -setup {
} -result [file join $tmpspace td1 td2]
test fCmd-6.30 {CopyRenameOneFile: TclpRemoveDirectory failed} -setup {
cleanup $tmpspace
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
file mkdir foo/bar
file attr foo -perm 0o40555
file rename foo/bar $tmpspace
@@ -760,7 +805,7 @@ test fCmd-8.3 {file copy and path translation: ensure correct error} -body {
test fCmd-9.1 {file rename: comprehensive: EACCES} -setup {
cleanup
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
file mkdir td1
file mkdir td2
file attr td2 -perm 0o40000
@@ -786,7 +831,7 @@ test fCmd-9.3 {file rename: comprehensive: file to new name} -setup {
} -result {{tf3 tf4} 1 0}
test fCmd-9.4 {file rename: comprehensive: dir to new name} -setup {
cleanup
} -constraints {unix notRoot testchmod notDarwin9} -body {
} -constraints {unix notRoot testchmod notDarwin9 notWsl} -body {
file mkdir td1 td2
testchmod 0o555 td2
file rename td1 td3
@@ -807,7 +852,7 @@ test fCmd-9.5 {file rename: comprehensive: file to self} -setup {
} -result {tf1 tf2 1 0}
test fCmd-9.6 {file rename: comprehensive: dir to self} -setup {
cleanup
} -constraints {unix notRoot testchmod} -body {
} -constraints {unix notRoot testchmod notWsl} -body {
file mkdir td1
file mkdir td2
testchmod 0o555 td2
@@ -1001,7 +1046,7 @@ test fCmd-10.2 {file copy: comprehensive: file to new name} -setup {
} -result {{tf1 tf2 tf3 tf4} tf1 tf2 1 0}
test fCmd-10.3 {file copy: comprehensive: dir to new name} -setup {
cleanup
} -constraints {unix notRoot testchmod} -body {
} -constraints {unix notRoot testchmod notWsl} -body {
file mkdir [file join td1 tdx]
file mkdir [file join td2 tdy]
testchmod 0o555 td2
@@ -1020,6 +1065,7 @@ test fCmd-10.3.1 {file copy: comprehensive: dir to new name} -setup {
file mkdir [file join td1 tdx]
file mkdir [file join td2 tdy]
testchmod 0o555 td2
testchmod 0o555 td2/tdy; # Above line removes inherited perms. So restore.
file copy td1 td3
file copy td2 td4
list [lsort [glob td*]] [glob -directory td3 t*] \
@@ -1041,10 +1087,19 @@ test fCmd-10.4 {file copy: comprehensive: file to existing file} -setup {
createfile tfd2
createfile tfd3
createfile tfd4
testchmod 0o444 tfs3
testchmod 0o444 tfs4
testchmod 0o444 tfd2
testchmod 0o444 tfd4
if {$::tcl_platform(platform) eq "windows"} {
# On Windows testchmode will attach an ACL which file copy cannot handle
# so use good old attributes which file copy does understand
file attribute tfs3 -readonly 1
file attribute tfs4 -readonly 1
file attribute tfd2 -readonly 1
file attribute tfd4 -readonly 1
} else {
testchmod 0o444 tfs3
testchmod 0o444 tfs4
testchmod 0o444 tfd2
testchmod 0o444 tfd4
}
set msg [list [catch {file copy tf1 tf2} msg] $msg]
file copy -force tfs1 tfd1
file copy -force tfs2 tfd2
@@ -1078,7 +1133,7 @@ test fCmd-10.5 {file copy: comprehensive: dir to empty dir} -setup {
} -result [subst {{td1 td2 tdd1 tdd2 tdd3 tdd4 tds1 tds2 tds3 tds4} {1 {error copying "td1" to "[file join td2 td1]": file already exists}} {1 {error copying "tds1" to "[file join tdd1 tds1]": file already exists}} 1 1 1}]
test fCmd-10.6 {file copy: comprehensive: dir to non-empty dir} -setup {
cleanup
} -constraints {notRoot unixOrWin testchmod} -body {
} -constraints {notRoot unixOrWin testchmod notWsl} -body {
file mkdir tds1
file mkdir tds2
file mkdir [file join tdd1 tds1 xxx]
@@ -1102,7 +1157,7 @@ test fCmd-10.7 {file rename: comprehensive: file to new name and dir} -setup {
} -result [subst {{tf1 tf2} {[file join td1 tf3] [file join td1 tf4]} 1 0}]
test fCmd-10.8 {file rename: comprehensive: dir to new name and dir} -setup {
cleanup
} -constraints {unix notRoot testchmod} -body {
} -constraints {unix notRoot testchmod notWsl} -body {
file mkdir td1
file mkdir td2
file mkdir td3
@@ -1194,7 +1249,7 @@ test fCmd-11.5 {TclFileRenameCmd: > 1 source & target is not a dir} -setup {
catch {file rename tfa1 tfa2 tfa3}
} -cleanup {
file delete tfa1 tfa2 tfa3
} -result {1}
} -result 1
test fCmd-11.6 {TclFileRenameCmd: : single file into directory} -setup {
catch {file delete -force -- tfa1 tfad}
} -constraints {notRoot} -body {
@@ -1239,7 +1294,7 @@ test fCmd-12.1 {renamefile: source filename translation failing} -setup {
catch {file rename ~/tfa1 tfa2}
} -cleanup {
set ::env(HOME) $temp
} -result {1}
} -result 1
test fCmd-12.2 {renamefile: src filename translation failing} -setup {
set temp $::env(HOME)
} -constraints {notRoot} -body {
@@ -1251,7 +1306,7 @@ test fCmd-12.2 {renamefile: src filename translation failing} -setup {
} -cleanup {
set ::env(HOME) $temp
file delete -force tfad
} -result {1}
} -result 1
test fCmd-12.3 {renamefile: stat failing on source} -setup {
catch {file delete -force -- tfa1 tfa2}
} -constraints {notRoot} -body {
@@ -1296,10 +1351,10 @@ test fCmd-12.7 {renamefile: renaming directory into offspring} -setup {
catch {file rename tfad tfad/dir}
} -cleanup {
file delete -force tfad
} -result {1}
} -result 1
test fCmd-12.8 {renamefile: generic error} -setup {
catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
file mkdir tfa
file mkdir tfa/dir
file attributes tfa -permissions 0o555
@@ -1307,7 +1362,7 @@ test fCmd-12.8 {renamefile: generic error} -setup {
} -cleanup {
catch {file attributes tfa -permissions 0o777}
file delete -force tfa
} -result {1}
} -result 1
test fCmd-12.9 {renamefile: moving a file across volumes} -setup {
cleanup $tmpspace
} -constraints {unix notRoot} -body {
@@ -1369,7 +1424,7 @@ test fCmd-13.5 {TclCopyFilesCmd: target filename translation failing} -setup {
catch { file copy tfa ~/foobar }
} -cleanup {
set ::env(HOME) $temp
} -result {1}
} -result 1
test fCmd-13.6 {TclCopyFilesCmd: > 1 source & target is not a dir} -setup {
catch {file delete -force -- tfa1 tfa2 tfa3}
} -constraints {notRoot} -body {
@@ -1379,7 +1434,7 @@ test fCmd-13.6 {TclCopyFilesCmd: > 1 source & target is not a dir} -setup {
catch {file copy tfa1 tfa2 tfa3}
} -cleanup {
file delete tfa1 tfa2 tfa3
} -result {1}
} -result 1
test fCmd-13.7 {TclCopyFilesCmd: single file into directory} -setup {
catch {file delete -force -- tfa1 tfad}
} -constraints {notRoot} -body {
@@ -1425,7 +1480,7 @@ test fCmd-14.1 {copyfile: source filename translation failing} -setup {
catch {file copy ~/tfa1 tfa2}
} -cleanup {
set ::env(HOME) $temp
} -result {1}
} -result 1
test fCmd-14.2 {copyfile: dst filename translation failing} -setup {
set temp $::env(HOME)
} -constraints {notRoot} -body {
@@ -1486,14 +1541,14 @@ test fCmd-14.7 {copyfile: copy directory succeeding} -setup {
} -result {1 1}
test fCmd-14.8 {copyfile: copy directory failing} -setup {
catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
file mkdir tfa/dir/a/b/c
file attributes tfa/dir -permissions 0
catch {file copy tfa tfa2}
} -cleanup {
file attributes tfa/dir -permissions 0o777
file delete -force tfa tfa2
} -result {1}
} -result 1
#
# Coverage tests for TclMkdirCmd()
@@ -1506,7 +1561,7 @@ test fCmd-15.1 {TclMakeDirsCmd: target filename translation failing} -setup {
catch {file mkdir ~/tfa}
} -cleanup {
set ::env(HOME) $temp
} -result {1}
} -result 1
#
# Can Tcl_SplitPath return argc == 0? If so them we need a test for that code.
#
@@ -1517,7 +1572,7 @@ test fCmd-15.2 {TclMakeDirsCmd - one directory} -setup {
file isdirectory tfa
} -cleanup {
file delete tfa
} -result {1}
} -result 1
test fCmd-15.3 {TclMakeDirsCmd: - two directories} -setup {
catch {file delete -force -- tfa1 tfa2}
} -constraints {notRoot} -body {
@@ -1536,7 +1591,7 @@ test fCmd-15.4 {TclMakeDirsCmd - stat failing} -setup {
} -cleanup {
file attributes tfa -permissions 0o777
file delete -force tfa
} -result {1}
} -result 1
test fCmd-15.5 {TclMakeDirsCmd: - making a directory several levels deep} -setup {
catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
@@ -1544,7 +1599,7 @@ test fCmd-15.5 {TclMakeDirsCmd: - making a directory several levels deep} -setup
file isdir tfa/a/b/c
} -cleanup {
file delete -force tfa
} -result {1}
} -result 1
test fCmd-15.6 {TclMakeDirsCmd: - trying to overwrite a file} -setup {
catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
@@ -1568,7 +1623,7 @@ test fCmd-15.8 {TclFileMakeDirsCmd: trying to create an existing dir} -body {
file isdir tfa
} -constraints {notRoot} -cleanup {
file delete tfa
} -result {1}
} -result 1
# Coverage tests for TclDeleteFilesCommand()
test fCmd-16.1 {test the -- argument} -constraints {notRoot} -setup {
@@ -1592,7 +1647,7 @@ test fCmd-16.3 {test bad option} -constraints {notRoot} -setup {
catch {file delete -dog tfa}
} -cleanup {
file delete tfa
} -result {1}
} -result 1
test fCmd-16.4 {accept zero files (TIP 323)} -body {
file delete
} -result {}
@@ -1607,7 +1662,7 @@ test fCmd-16.6 {delete: source filename translation failing} -setup {
catch {file delete ~/tfa}
} -cleanup {
set ::env(HOME) $temp
} -result {1}
} -result 1
test fCmd-16.7 {remove a non-empty directory without -force} -setup {
catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
@@ -1616,7 +1671,7 @@ test fCmd-16.7 {remove a non-empty directory without -force} -setup {
catch {file delete tfa}
} -cleanup {
file delete -force tfa
} -result {1}
} -result 1
test fCmd-16.8 {remove a normal file} -constraints {notRoot} -setup {
catch {file delete -force -- tfa}
} -body {
@@ -1625,10 +1680,10 @@ test fCmd-16.8 {remove a normal file} -constraints {notRoot} -setup {
catch {file delete tfa}
} -cleanup {
file delete -force tfa
} -result {1}
} -result 1
test fCmd-16.9 {error while deleting file} -setup {
catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
file mkdir tfa
createfile tfa/a
file attributes tfa -permissions 0o555
@@ -1641,7 +1696,7 @@ test fCmd-16.9 {error while deleting file} -setup {
} -cleanup {
file attributes tfa -permissions 0o777
file delete -force tfa
} -result {1}
} -result 1
test fCmd-16.10 {deleting multiple files} -constraints {notRoot} -setup {
catch {file delete -force -- tfa1 tfa2}
} -body {
@@ -1659,14 +1714,14 @@ test fCmd-16.11 {TclFileDeleteCmd: removing a nonexistant file} -setup {
# More coverage tests for mkpath()
test fCmd-17.1 {mkdir stat failing on target but not ENOENT} -setup {
catch {file delete -force -- tfa1}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
file mkdir tfa1
file attributes tfa1 -permissions 0o555
catch {file mkdir tfa1/tfa2}
} -cleanup {
file attributes tfa1 -permissions 0o777
file delete -force tfa1
} -result {1}
} -result 1
test fCmd-17.2 {mkdir several levels deep - relative} -setup {
catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
@@ -1683,7 +1738,7 @@ test fCmd-17.3 {mkdir several levels deep - absolute} -setup {
file isdir $f
} -cleanup {
file delete $f [file join [pwd] tfa]
} -result {1}
} -result 1
#
# Functionality tests for TclFileRenameCmd()
@@ -1844,7 +1899,7 @@ test fCmd-18.15 {TclFileRenameCmd : rename a file to a symlink dir} -setup {
checkcontent tfa1/tfa2 $s
} -cleanup {
file delete -force tfa1 tfalink
} -result {1}
} -result 1
test fCmd-18.16 {TclFileRenameCmd: rename a dangling symlink} -setup {
catch {file delete -force -- tfa1 tfalink}
} -constraints {unix notRoot} -body {
@@ -1869,7 +1924,7 @@ test fCmd-19.1 {remove empty directory} -constraints {notRoot} -setup {
} -result {0}
test fCmd-19.2 {rmdir error besides EEXIST} -setup {
catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
file mkdir tfa
file mkdir tfa/a
file attributes tfa -permissions 0o555
@@ -1877,7 +1932,7 @@ test fCmd-19.2 {rmdir error besides EEXIST} -setup {
} -cleanup {
file attributes tfa -permissions 0o777
file delete -force tfa
} -result {1}
} -result 1
test fCmd-19.3 {recursive remove} -constraints {notRoot} -setup {
catch {file delete -force -- tfa}
} -body {
@@ -1897,7 +1952,7 @@ test fCmd-19.3 {recursive remove} -constraints {notRoot} -setup {
#
test fCmd-20.1 {TraverseUnixTree : failure opening a subdirectory directory} -setup {
catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
file mkdir tfa
file mkdir tfa/a
file attributes tfa/a -permissions 00000
@@ -1905,7 +1960,7 @@ test fCmd-20.1 {TraverseUnixTree : failure opening a subdirectory directory} -se
} -cleanup {
file attributes tfa/a -permissions 0o777
file delete -force tfa
} -result {1}
} -result 1
test fCmd-20.2 {TraverseUnixTree : recursive delete of large directory: Bug 1034337} -setup {
catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
@@ -1958,7 +2013,7 @@ test fCmd-21.4 {copy : more than one source and target is not a directory} -setu
catch {file copy tfa1 tfa2 tfa3}
} -cleanup {
file delete tfa1 tfa2 tfa3
} -result {1}
} -result 1
test fCmd-21.5 {copy : multiple files into directory} -constraints {notRoot} -setup {
catch {file delete -force -- tfa1 tfa2 tfad}
} -body {
@@ -2083,7 +2138,7 @@ test fCmd-22.2 {TclpRenameFile: attempt to overwrite itself} -setup {
checkcontent tfa1 $s
} -cleanup {
file delete tfa1
} -result {1}
} -result 1
test fCmd-22.3 {TclpRenameFile: rename dir to existing dir} -setup {
catch {file delete -force -- d1 tfad}
} -constraints {notRoot} -body {
@@ -2543,7 +2598,7 @@ test fCmd-30.2 {file readable on 'NTUSER.DAT'} -constraints {win notWine} -body
expr {[info exists env(USERPROFILE)]
&& [file exists $env(USERPROFILE)/NTUSER.DAT]
&& [file readable $env(USERPROFILE)/NTUSER.DAT]}
} -result {1}
} -result 1
# At least one CI environment (GitHub Actions) is set up with the page file in
# an unusual location; skip the test if that is so.
test fCmd-30.3 {file readable on 'pagefile.sys'} -constraints {win notInCIenv} -body {
@@ -2599,13 +2654,20 @@ test fCmd-31.6 {file home USER} -body {
# env(HOME) even when user is current user. Assume result contains user
# name, else not sure how to check
string tolower [file home $::tcl_platform(user)]
} -match glob -result [string tolower "*$::tcl_platform(user)*"]
} -match glob -result [gethomedirglob $::tcl_platform(user)]
test fCmd-31.7 {file home UNKNOWNUSER} -body {
file home nosuchuser
} -returnCodes error -result {user "nosuchuser" doesn't exist}
test fCmd-31.8 {file home extra arg} -body {
file home $::tcl_platform(user) arg
} -returnCodes error -result {wrong # args: should be "file home ?user?"}
test fCmd-31.9 {file home USER does not follow env(HOME)} -setup {
set ::env(HOME) [file join $::env(HOME) foo]
} -cleanup {
set ::env(HOME) [file dirname $::env(HOME)]
} -body {
string tolower [file home $::tcl_platform(user)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]
test fCmd-32.1 {file tildeexpand ~} -body {
file tildeexpand ~
@@ -2641,7 +2703,7 @@ test fCmd-32.5 {file tildeexpand ~USER} -body {
# env(HOME) even when user is current user. Assume result contains user
# name, else not sure how to check
string tolower [file tildeexpand ~$::tcl_platform(user)]
} -match glob -result [string tolower "*$::tcl_platform(user)*"]
} -match glob -result [gethomedirglob $::tcl_platform(user)]
test fCmd-32.6 {file tildeexpand ~UNKNOWNUSER} -body {
file tildeexpand ~nosuchuser
} -returnCodes error -result {user "nosuchuser" doesn't exist}
@@ -2656,7 +2718,7 @@ test fCmd-32.9 {file tildeexpand ~USER/bar} -body {
# env(HOME) even when user is current user. Assume result contains user
# name, else not sure how to check
string tolower [file tildeexpand ~$::tcl_platform(user)/bar]
} -match glob -result [string tolower "*$::tcl_platform(user)*/bar"]
} -match glob -result [file join [gethomedirglob $::tcl_platform(user)] bar]
test fCmd-32.10 {file tildeexpand ~UNKNOWNUSER} -body {
file tildeexpand ~nosuchuser/foo
} -returnCodes error -result {user "nosuchuser" doesn't exist}
@@ -2680,7 +2742,14 @@ test fCmd-32.16 {file tildeexpand ~USER\\bar} -body {
# env(HOME) even when user is current user. Assume result contains user
# name, else not sure how to check
string tolower [file tildeexpand ~$::tcl_platform(user)\\bar]
} -constraints win -match glob -result [string tolower "*$::tcl_platform(user)*/bar"]
} -constraints win -match glob -result [file join [gethomedirglob $::tcl_platform(user)] bar]
test fCmd-32.17 {file tildeexpand ~USER does not mirror HOME} -setup {
set ::env(HOME) [file join $::env(HOME) foo]
} -cleanup {
set ::env(HOME) [file dirname $::env(HOME)]
} -body {
string tolower [file tildeexpand ~$::tcl_platform(user)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]
# cleanup
+10
View File
@@ -276,6 +276,16 @@ test filesystem-1.30.1 {normalisation of existing user} -body {
test filesystem-1.30.2 {normalisation of nonexistent user specified as user@domain} -body {
file normalize ~nonexistentuser@nonexistentdomain
} -returnCodes error -result {user "nonexistentuser@nonexistentdomain" doesn't exist}
test filesystem-1.30.3 {file normalization should distinguish between ~ and ~user} -setup {
set oldhome $::env(HOME)
set olduserhome [file normalize ~$::tcl_platform(user)]
set ::env(HOME) [file join $oldhome temp]
} -cleanup {
set env(HOME) $oldhome
} -body {
list [string equal [file normalize ~] $::env(HOME)] \
[string equal $olduserhome [file normalize ~$::tcl_platform(user)]]
} -result {1 1}
test filesystem-1.31 {link normalisation: link near filesystem root} {testsetplatform} {
testsetplatform unix
file normalize /foo/../bar
+121 -57
View File
@@ -48,6 +48,8 @@ testConstraint testservicemode [llength [info commands testservicemode]]
testConstraint notWinCI [expr {
$::tcl_platform(platform) ne "windows" || ![info exists ::env(CI)]}]
testConstraint notOSX [expr {$::tcl_platform(os) ne "Darwin"}]
# File permissions broken on wsl without some "exotic" wsl configuration
testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]
# You need a *very* special environment to do some tests. In
# particular, many file systems do not support large-files...
@@ -5474,7 +5476,7 @@ test io-38.3 {Tcl_SetChannelBufferSize, changing buffersize between reads} {
# This test crashes the interp if Bug #427196 is not fixed
set chan [open [info script] r]
fconfigure $chan -buffersize 10
fconfigure $chan -buffersize 10 -encoding utf-8
set var [read $chan 2]
fconfigure $chan -buffersize 32
append var [read $chan]
@@ -5675,13 +5677,20 @@ test io-39.15 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
close $f
set x
} 牦
test io-39.16 {Tcl_SetChannelOption: -encoding, errors} {
test io-39.16 {Tcl_SetChannelOption: -encoding (shortened to "-en"), errors} -body {
file delete $path(test1)
set f [open $path(test1) w]
set result [list [catch {fconfigure $f -encoding foobar} msg] $msg]
fconfigure $f -en foobar
} -cleanup {
close $f
set result
} {1 {unknown encoding "foobar"}}
} -returnCodes 1 -result {unknown encoding "foobar"}
test io-39.16a {Tcl_SetChannelOption: -encoding (invalid shortening to "-e"), errors} -body {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -e foobar
} -cleanup {
close $f
} -returnCodes 1 -match glob -result {bad option "-e": should be one of *}
test io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA} {stdio fileevent} {
set f [open "|[list [interpreter] $path(cat)]" r+]
fconfigure $f -encoding binary
@@ -5813,7 +5822,7 @@ test io-40.1 {POSIX open access modes: RDWR} {
close $f
set x
} {zzy abzzy}
test io-40.2 {POSIX open access modes: CREAT} {unix} {
test io-40.2 {POSIX open access modes: CREAT} {unix notWsl} {
file delete $path(test3)
set f [open $path(test3) {WRONLY CREAT} 0o600]
file stat $path(test3) stats
@@ -5825,7 +5834,7 @@ test io-40.2 {POSIX open access modes: CREAT} {unix} {
close $f
set x
} {0o600 {line 1}}
test io-40.3 {POSIX open access modes: CREAT} {unix umask} {
test io-40.3 {POSIX open access modes: CREAT} {unix umask notWsl} {
# This test only works if your umask is 2, like ouster's.
file delete $path(test3)
set f [open $path(test3) {WRONLY CREAT}]
@@ -7280,8 +7289,8 @@ test io-52.5 {TclCopyChannel, all} {fcopy} {
file delete $path(test1)
set f1 [open $thisScript]
set f2 [open $path(test1) w]
fconfigure $f1 -translation lf -blocking 0
fconfigure $f2 -translation lf -blocking 0
fconfigure $f1 -translation lf -encoding iso8859-1 -blocking 0
fconfigure $f2 -translation lf -encoding iso8859-1 -blocking 0
fcopy $f1 $f2 -size -1 ;# -1 means 'copy all', same as if no -size specified.
set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
close $f1
@@ -7297,8 +7306,8 @@ test io-52.5a {TclCopyChannel, all, other negative value} {fcopy} {
file delete $path(test1)
set f1 [open $thisScript]
set f2 [open $path(test1) w]
fconfigure $f1 -translation lf -blocking 0
fconfigure $f2 -translation lf -blocking 0
fconfigure $f1 -translation lf -encoding iso8859-1 -blocking 0
fconfigure $f2 -translation lf -encoding iso8859-1 -blocking 0
fcopy $f1 $f2 -size -2 ;# < 0 behaves like -1, copy all
set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
close $f1
@@ -7314,8 +7323,8 @@ test io-52.5b {TclCopyChannel, all, wrap to negative value} {fcopy} {
file delete $path(test1)
set f1 [open $thisScript]
set f2 [open $path(test1) w]
fconfigure $f1 -translation lf -blocking 0
fconfigure $f2 -translation lf -blocking 0
fconfigure $f1 -translation lf -encoding iso8859-1 -blocking 0
fconfigure $f2 -translation lf -encoding iso8859-1 -blocking 0
fcopy $f1 $f2 -size 3221176172 ;# Wrapped to < 0, behaves like -1, copy all
set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
close $f1
@@ -7348,8 +7357,8 @@ test io-52.7 {TclCopyChannel} {fcopy} {
file delete $path(test1)
set f1 [open $thisScript]
set f2 [open $path(test1) w]
fconfigure $f1 -translation lf -blocking 0
fconfigure $f2 -translation lf -blocking 0
fconfigure $f1 -translation lf -encoding iso8859-1 -blocking 0
fconfigure $f2 -translation lf -encoding iso8859-1 -blocking 0
fcopy $f1 $f2
set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
set s1 [file size $thisScript]
@@ -7609,6 +7618,103 @@ test io-52.19 {coverage of eofChar handling} {
close $out
file size $path(test2)
} 8
test io-52.20 {TclCopyChannel & encodings} -setup {
set out [open $path(utf8-fcopy.txt) w]
fconfigure $out -encoding utf-8 -translation lf
puts $out "Á"
close $out
} -constraints {fcopy} -body {
# binary to encoding => the input has to be
# in utf-8 to make sense to the encoder
set in [open $path(utf8-fcopy.txt) r]
set out [open $path(kyrillic.txt) w]
# Using "-encoding ascii" means reading the "Á" gives an error
fconfigure $in -encoding ascii -strictencoding 1
fconfigure $out -encoding koi8-r -translation lf
fcopy $in $out
} -cleanup {
close $in
close $out
} -returnCodes 1 -match glob -result {error reading "file*": illegal byte sequence}
test io-52.21 {TclCopyChannel & encodings} -setup {
set out [open $path(utf8-fcopy.txt) w]
fconfigure $out -encoding utf-8 -translation lf
puts $out "Á"
close $out
} -constraints {fcopy} -body {
# binary to encoding => the input has to be
# in utf-8 to make sense to the encoder
set in [open $path(utf8-fcopy.txt) r]
set out [open $path(kyrillic.txt) w]
# Using "-encoding ascii" means writing the "Á" gives an error
fconfigure $in -encoding utf-8
fconfigure $out -encoding ascii -translation lf -strictencoding 1
fcopy $in $out
} -cleanup {
close $in
close $out
} -returnCodes 1 -match glob -result {error writing "file*": illegal byte sequence}
test io-52.22 {TclCopyChannel & encodings} -setup {
set out [open $path(utf8-fcopy.txt) w]
fconfigure $out -encoding utf-8 -translation lf
puts $out "Á"
close $out
} -constraints {fcopy} -body {
# binary to encoding => the input has to be
# in utf-8 to make sense to the encoder
set in [open $path(utf8-fcopy.txt) r]
set out [open $path(kyrillic.txt) w]
# Using "-encoding ascii" means reading the "Á" gives an error
fconfigure $in -encoding ascii -strictencoding 1
fconfigure $out -encoding koi8-r -translation lf
proc ::xxx args {
set ::s0 $args
}
fcopy $in $out -command ::xxx
vwait ::s0
set ::s0
} -cleanup {
close $in
close $out
unset ::s0
} -match glob -result {0 {error reading "file*": illegal byte sequence}}
test io-52.23 {TclCopyChannel & encodings} -setup {
set out [open $path(utf8-fcopy.txt) w]
fconfigure $out -encoding utf-8 -translation lf
puts $out "Á"
close $out
} -constraints {fcopy} -body {
# binary to encoding => the input has to be
# in utf-8 to make sense to the encoder
set in [open $path(utf8-fcopy.txt) r]
set out [open $path(kyrillic.txt) w]
# Using "-encoding ascii" means writing the "Á" gives an error
fconfigure $in -encoding utf-8
fconfigure $out -encoding ascii -translation lf -strictencoding 1
proc ::xxx args {
set ::s0 $args
}
fcopy $in $out -command ::xxx
vwait ::s0
set ::s0
} -cleanup {
close $in
close $out
unset ::s0
} -match glob -result {0 {error writing "file*": illegal byte sequence}}
test io-53.1 {CopyData} {fcopy} {
file delete $path(test1)
@@ -9046,48 +9152,6 @@ test io-75.5 {invalid utf-8 encoding read is ignored (-nocomplainencoding 1)} -s
removeFile io-75.5
} -result 4181
test io-75.6 {invalid utf-8 encoding read is not ignored (-strictencoding 1)} -setup {
set fn [makeFile {} io-75.6]
set f [open $fn w+]
fconfigure $f -encoding binary
# \x81 is invalid in utf-8
puts -nonewline $f A\x81
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -eofchar "" -translation lf -strictencoding 1
} -body {
set d [read $f]
binary scan $d H* hd
lappend hd [catch {read $f} msg]
close $f
lappend hd $msg
} -cleanup {
removeFile io-75.6
} -match glob -result {41 1 {error reading "*": illegal byte sequence}}
test io-75.7 {invalid utf-8 encoding eof handling (-strictencoding 1)} -setup {
set fn [makeFile {} io-75.7]
set f [open $fn w+]
fconfigure $f -encoding binary
# \xA1 is invalid in utf-8. -eofchar is not detected, because it comes later.
puts -nonewline $f A\xA1\x1A
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -eofchar \x1A -translation lf -strictencoding 1
} -body {
set d [read $f]
binary scan $d H* hd
lappend hd [eof $f]
lappend hd [catch {read $f} msg]
lappend hd $msg
fconfigure $f -encoding iso8859-1
lappend hd [read $f];# We changed encoding, so now we can read the \xA1
close $f
set hd
} -cleanup {
removeFile io-75.7
} -match glob -result {41 0 1 {error reading "*": illegal byte sequence} ¡}
test io-75.8 {invalid utf-8 encoding eof handling (-strictencoding 1)} -setup {
set fn [makeFile {} io-75.8]
set f [open $fn w+]
+10
View File
@@ -376,6 +376,16 @@ test iocmd-8.21 {fconfigure command / -nocomplainencoding 0 error} -constraints
} -body {
fconfigure $console -nocomplainencoding 0
} -returnCodes error -result "bad value for -nocomplainencoding: only true allowed"
test iocmd-8.22 {fconfigure command / -nocomplainencoding 0, no error if -strictencoding already defined} -setup {
set console stdin
set oldmode [fconfigure $console -strictencoding]
} -body {
fconfigure $console -strictencoding 1
fconfigure $console -nocomplainencoding 0
fconfigure $console -nocomplainencoding
} -cleanup {
fconfigure $console -strictencoding $oldmode
} -result 0
test iocmd-9.1 {eof command} {
+85 -1
View File
@@ -634,6 +634,58 @@ test iortrans-4.9 {chan read, gets, bug 2921116} -setup {
}
}
namespace eval reflector {
proc initialize {_ chan mode} {
return {initialize finalize watch read}
}
proc finalize {_ chan} {
namespace delete $_
}
proc read {_ chan count} {
namespace upvar $_ source source
set res [string range $source 0 $count-1]
set source [string range $source $count end]
return $res
}
proc watch {_ chan events} {
after 0 [list chan postevent $chan read]
return read
}
namespace ensemble create -parameters _
namespace export *
}
namespace eval inputfilter {
proc initialize {chan mode} {
return {initialize finalize read}
}
proc read {chan buffer} {
return $buffer
}
proc finalize chan {
namespace delete $chan
}
namespace ensemble create
namespace export *
}
# Channel read transform that is just the identity - pass all through
proc idxform {cmd handle args} {
switch -- $cmd {
@@ -2089,7 +2141,39 @@ test iortrans.tf-11.1 {origin thread of moved transform destroyed during access}
thread::release $tidb
} -result {Owner lost}
# ### ### ### ######### ######### #########
test iortrans-ea69b0258a9833cb {
Crash when using a channel transformation on TCP client socket
"line two" does not make it into result. This issue should probably be
addressed, but it is outside the scope of this test.
} -setup {
set res {}
set read 0
} -body {
namespace eval reflector1 {
variable source "line one\nline two"
interp alias {} [namespace current]::dispatch {} [
namespace parent]::reflector [namespace current]
}
set chan [chan create read [namespace which reflector1::dispatch]]
chan configure $chan -blocking 0
chan push $chan inputfilter
chan event $chan read [list ::apply [list chan {
variable res
variable read
set gets [gets $chan]
append res $gets
incr read
} [namespace current]] $chan]
vwait [namespace current]::read
chan pop $chan
vwait [namespace current]::read
return $res
} -cleanup {
catch {unset read}
close $chan
} -result {line one}
cleanupTests
return
+3 -3
View File
@@ -69,8 +69,8 @@ test stringObj-4.2 {Tcl_SetObjLength procedure, string gets longer} {testobj dep
testobj freeallvars
teststringobj set 1 abcdef
teststringobj setlength 1 10
list [teststringobj length 1] [teststringobj length2 1]
} {10 10}
teststringobj length 1
} 10
test stringObj-4.3 {Tcl_SetObjLength procedure, string gets longer} {testobj utf32 deprecated} {
testobj freeallvars
teststringobj set 1 abcdef
@@ -78,7 +78,7 @@ test stringObj-4.3 {Tcl_SetObjLength procedure, string gets longer} {testobj utf
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {10 10 abcdefxyzq}
test stringObj-4.4 {Tcl_SetObjLength procedure, "expty string", length 0} {testobj deprecated} {
test stringObj-4.4 {Tcl_SetObjLength procedure, "empty string", length 0} {testobj deprecated} {
testobj freeallvars
testobj newobj 1
teststringobj setlength 1 0
+8 -5
View File
@@ -22,6 +22,9 @@ if {"::tcltest" ni [namespace children]} {
namespace import -force ::tcltest::*
}
# File permissions broken on wsl without some "exotic" wsl configuration
testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]
namespace eval ::tcltest::test {
namespace import ::tcltest::*
@@ -306,7 +309,7 @@ test tcltest-5.3 {testConstraint - constraint empty (tcltest::safeFetch)} {
#}
test tcltest-5.5 {InitConstraints: list of built-in constraints} \
-constraints {!singleTestInterp} \
-constraints {!singleTestInterp notWsl} \
-setup {tcltest::InitConstraints} \
-body { lsort [array names ::tcltest::testConstraints] } \
-result [lsort {
@@ -552,11 +555,11 @@ switch -- $::tcl_platform(platform) {
default {
# note in FAT/NTFS we won't be able to protect directory with read-only attribute...
catch {file attributes $notWriteableDir -readonly 1}
catch {testchmod 0 $notWriteableDir}
catch {testchmod 0o444 $notWriteableDir}
}
}
test tcltest-8.3 {tcltest a.tcl -tmpdir notReadableDir} {
-constraints {unix notRoot}
-constraints {unix notRoot notWsl}
-body {
child msg $a -tmpdir $notReadableDir
return $msg
@@ -572,7 +575,7 @@ testConstraint notFAT [expr {
}]
# FAT/NTFS permissions are fairly hopeless; ignore this test if that FS is used
test tcltest-8.4 {tcltest a.tcl -tmpdir notWriteableDir} {
-constraints {unixOrWin notRoot notFAT}
-constraints {unixOrWin notRoot notFAT notWsl}
-body {
child msg $a -tmpdir $notWriteableDir
return $msg
@@ -645,7 +648,7 @@ test tcltest-8.11 {tcltest a.tcl -testdir thisdirectoryisafile} {
-result {*not a directory*}
}
test tcltest-8.12 {tcltest a.tcl -testdir notReadableDir} {
-constraints {unix notRoot}
-constraints {unix notRoot notWsl}
-body {
child msg $a -testdir $notReadableDir
return $msg
+7 -5
View File
@@ -18,6 +18,8 @@ if {"::tcltest" ni [namespace children]} {
catch [list package require -exact tcl::test [info patchlevel]]
testConstraint testchmod [llength [info commands testchmod]]
# File permissions broken on wsl without some "exotic" wsl configuration
testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]
# These tests really need to be run from a writable directory, which
# it is assumed [temporaryDirectory] is.
@@ -94,7 +96,7 @@ if {[testConstraint unix] && [testConstraint notRoot]} {
test unixFCmd-1.1 {TclpRenameFile: EACCES} -setup {
cleanup
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
file mkdir td1/td2/td3
file attributes td1/td2 -permissions 0
file rename td1/td2/td3 td2
@@ -135,7 +137,7 @@ test unixFCmd-1.6 {TclpRenameFile: ENOTDIR} {emptyTest unix notRoot} {
} {}
test unixFCmd-1.7 {TclpRenameFile: EXDEV} -setup {
cleanup
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
file mkdir foo/bar
file attr foo -perm 0o40555
file rename foo/bar /tmp
@@ -219,7 +221,7 @@ test unixFCmd-2.4 {TclpCopyFile: src is fifo} -setup {
} -result {fifo fifo}
test unixFCmd-2.5 {TclpCopyFile: copy attributes} -setup {
cleanup
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
close [open tf1 a]
file attributes tf1 -permissions 0o472
file copy tf1 tf2
@@ -334,7 +336,7 @@ test unixFCmd-16.3 {SetOwnerAttribute - invalid owner} -setup {
test unixFCmd-17.1 {SetPermissionsAttribute} -setup {
catch {file delete -force -- foo.test}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
close [open foo.test w]
list [file attributes foo.test -permissions 0] \
[file attributes foo.test -permissions]
@@ -366,7 +368,7 @@ test unixFCmd-17.4 {SetPermissionsAttribute} -setup {
close [open foo.test w]
set ::i 4
proc permcheck {testnum permList expected} {
test $testnum {SetPermissionsAttribute} {unix notRoot} {
test $testnum {SetPermissionsAttribute} {unix notRoot notWsl} {
set result {}
foreach permstr $permList {
file attributes foo.test -permissions $permstr
+62 -55
View File
@@ -45,15 +45,20 @@ proc contents {file} {
set r
}
proc cleanupRecurse {args} {
# Assumes no loops via links!
# Need to change permissions BEFORE deletion
testchmod 0o777 {*}$args
foreach victim $args {
if {[file isdirectory $victim]} {
cleanupRecurse {*}[glob -nocomplain -directory $victim td* tf* Test*]
}
file delete -force $victim
}
}
proc cleanup {args} {
foreach p ". $args" {
set x ""
catch {
set x [glob -directory $p tf* td*]
}
if {$x != ""} {
catch {file delete -force -- {*}$x}
}
foreach p [list [pwd] {*}$args] {
cleanupRecurse {*}[glob -nocomplain -directory $p tf* td*]
}
}
@@ -245,8 +250,9 @@ test winFCmd-1.23 {TclpRenameFile: move dir into self} -setup {
test winFCmd-1.24 {TclpRenameFile: move a root dir} -setup {
cleanup
} -constraints {win testfile} -body {
# Error code depends on Windows version
testfile mv / c:/
} -returnCodes error -result EINVAL
} -returnCodes error -result {^(EINVAL|ENOENT)$} -match regexp
test winFCmd-1.25 {TclpRenameFile: cross file systems} -setup {
cleanup
} -constraints {win cdrom testfile} -body {
@@ -379,12 +385,12 @@ test winFCmd-1.38 {TclpRenameFile: check rename of conflicting inodes} -setup {
cleanup
} -constraints {win winNonZeroInodes knownMsvcBug notInCIenv} -body {
file mkdir td1
foreach {a b} [MakeFiles td1] break
lassign [MakeFiles td1] a b
file rename -force $a $b
file exists $a
} -cleanup {
cleanup
} -result {0}
} -result 0
test winFCmd-2.1 {TclpCopyFile: errno: EACCES} -setup {
@@ -450,11 +456,11 @@ test winFCmd-2.12 {TclpCopyFile: CopyFile succeeds} -setup {
cleanup
} -constraints {win testfile} -body {
createfile tf1 tf1
testchmod 0 tf1
file attribute tf1 -readonly 1
testfile cp tf1 tf2
list [contents tf2] [file writable tf2]
} -cleanup {
catch {testchmod 0o666 tf1}
testchmod 0o660 tf1
cleanup
} -result {tf1 0}
test winFCmd-2.13 {TclpCopyFile: CopyFile fails} -setup {
@@ -496,11 +502,10 @@ test winFCmd-2.17 {TclpCopyFile: dst is readonly} -setup {
} -constraints {win testfile testchmod} -body {
createfile tf1 tf1
createfile tf2 tf2
testchmod 0 tf2
file attribute tf2 -readonly 1
testfile cp tf1 tf2
list [file writable tf2] [contents tf2]
} -cleanup {
catch {testchmod 0o666 tf2}
cleanup
} -result {1 tf1}
@@ -578,7 +583,6 @@ test winFCmd-3.11 {TclpDeleteFile: still can't remove path} -setup {
testfile rm tf1
} -cleanup {
close $fd
catch {testchmod 0o666 tf1}
cleanup
} -returnCodes error -result EACCES
@@ -617,15 +621,18 @@ test winFCmd-5.1 {TclpCopyDirectory: calls TraverseWinTree} -setup {
test winFCmd-6.1 {TclpRemoveDirectory: errno: EACCES} -setup {
cleanup
} -constraints {win testfile testchmod knownMsvcBug notInCIenv} -body {
file mkdir td1
testchmod 0 td1
testfile rmdir td1
file exists td1
} -constraints {win testfile testchmod notInCIenv} -body {
# Parent's FILE_DELETE_CHILD setting permits deletion of subdir
# even when subdir DELETE mask is clear. So we need an intermediate
# parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
file mkdir td0/td1
testchmod 0o777 td0
testchmod 0 td0/td1
testfile rmdir td0/td1
file exists td0/td1
} -returnCodes error -cleanup {
catch {testchmod 0o666 td1}
cleanup
} -result {td1 EACCES}
} -result {td0/td1 EACCES}
# This next test has a very hokey way of matching...
test winFCmd-6.2 {TclpRemoveDirectory: errno: EEXIST} -setup {
cleanup
@@ -633,7 +640,7 @@ test winFCmd-6.2 {TclpRemoveDirectory: errno: EEXIST} -setup {
file mkdir td1/td2
list [catch {testfile rmdir td1} msg] [file tail $msg]
} -result {1 {td1 EEXIST}}
test winFCmd-6.3 {TclpRemoveDirectory: errno: EACCES} {win emptyTest} {
test winFCmd-6.3 {TclpRemoveDirectory: errno: EACCES} {win emptyTest trashSystem} {
# can't test this w/o removing everything on your hard disk first!
# testfile rmdir /
} {}
@@ -669,17 +676,7 @@ test winFCmd-6.8 {TclpRemoveDirectory: RemoveDirectory fails} -setup {
createfile tf1
list [catch {testfile rmdir tf1} msg] [file tail $msg]
} -result {1 {tf1 ENOTDIR}}
test winFCmd-6.9 {TclpRemoveDirectory: errno == EACCES} -setup {
cleanup
} -constraints {win testfile testchmod knownMsvcBug notInCIenv} -body {
file mkdir td1
testchmod 0 td1
testfile rmdir td1
file exists td1
} -returnCodes error -cleanup {
catch {testchmod 0o666 td1}
cleanup
} -result {td1 EACCES}
# winFCmd-6.9 removed - was exact dup of winFCmd-6.1
test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} -setup {
cleanup
} -constraints {win testfile notInCIenv} -body {
@@ -689,15 +686,19 @@ test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} -setup {
} -returnCodes error -match regexp -result {^/ E(ACCES|EXIST)$}
test winFCmd-6.13 {TclpRemoveDirectory: write-protected} -setup {
cleanup
} -constraints {win testfile testchmod knownMsvcBug notInCIenv} -body {
file mkdir td1
testchmod 0 td1
testfile rmdir td1
file exists td1
} -constraints {win testfile testchmod notInCIenv} -body {
# Parent's FILE_DELETE_CHILD setting permits deletion of subdir
# even when subdir DELETE mask is clear. So we need an intermediate
# parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
file mkdir td0/td1
testchmod 0o770 td0
testchmod 0o444 td0/td1
testfile rmdir td0/td1
file exists td0/td1
} -cleanup {
catch {testchmod 0o666 td1}
testchmod 0o770 td0/td1
cleanup
} -returnCodes error -result {td1 EACCES}
} -returnCodes error -result {td0/td1 EACCES}
# This next test has a very hokey way of matching...
test winFCmd-6.15 {TclpRemoveDirectory: !recursive} -setup {
cleanup
@@ -791,11 +792,12 @@ test winFCmd-7.11 {TraverseWinTree: call TraversalCopy: DOTREE_PRED} -setup {
} -constraints {win testfile testchmod} -body {
file mkdir td1
createfile td1/tf1 tf1
testchmod 0 td1
testchmod 0o770 td1/tf1; # Else tf2 will have no ACL after td1 testchmod
testchmod 0o400 td1
testfile cpdir td1 td2
list [file exists td2] [file writable td2]
} -cleanup {
catch {testchmod 0o666 td1}
testchmod 0o660 td1
cleanup
} -result {1 1}
test winFCmd-7.12 {TraverseWinTree: call TraversalDelete: DOTREE_PRED} -setup {
@@ -862,11 +864,12 @@ test winFCmd-7.19 {TraverseWinTree: call TraversalCopy: DOTREE_POSTD} -setup {
} -constraints {win testfile testchmod} -body {
file mkdir td1
createfile td1/tf1 tf1
testchmod 0 td1
testchmod 0o770 td1/tf1; # Else tf2 will have no ACL after td1 testchmod
testchmod 0o400 td1
testfile cpdir td1 td2
list [file exists td2] [file writable td2]
} -cleanup {
catch {testchmod 0o666 td1}
testchmod 0o660 td1
cleanup
} -result {1 1}
test winFCmd-7.20 {TraverseWinTree: call TraversalDelete: DOTREE_POSTD} -setup {
@@ -893,11 +896,12 @@ test winFCmd-8.2 {TraversalCopy: DOTREE_PRED} -setup {
cleanup
} -constraints {win testfile testchmod} -body {
file mkdir td1/td2
testchmod 0 td1
testchmod 0o770 td1/td2; # Else td2 will have no ACL after td1 testchmod
testchmod 0o400 td1
testfile cpdir td1 td2
list [file writable td1] [file writable td1/td2]
} -cleanup {
catch {testchmod 0o666 td1}
testchmod 0o660 td1
cleanup
} -result {0 1}
test winFCmd-8.3 {TraversalCopy: DOTREE_POSTD} -setup {
@@ -918,15 +922,19 @@ test winFCmd-9.1 {TraversalDelete: DOTREE_F} -setup {
} -result {}
test winFCmd-9.3 {TraversalDelete: DOTREE_PRED} -setup {
cleanup
} -constraints {win testfile testchmod knownMsvcBug notInCIenv} -body {
file mkdir td1/td2
testchmod 0 td1
testfile rmdir -force td1
} -constraints {win testfile testchmod notInCIenv} -body {
# Parent's FILE_DELETE_CHILD setting permits deletion of subdir
# even when subdir DELETE mask is clear. So we need an intermediate
# parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
file mkdir td0/td1/td2
testchmod 0o770 td0
testchmod 0o400 td0/td1
testfile rmdir -force td0/td1
file exists td1
} -cleanup {
catch {testchmod 0o666 td1}
testchmod 0o770 td0/td1
cleanup
} -returnCodes error -result {td1 EACCES}
} -returnCodes error -result {td0/td1 EACCES}
test winFCmd-9.4 {TraversalDelete: DOTREE_POSTD} -setup {
cleanup
} -constraints {win testfile} -body {
@@ -1417,7 +1425,6 @@ test winFCmd-19.9 {Windows devices path names} -constraints win -body {
# }
#}
# cleanup
cleanup
::tcltest::cleanupTests
return
+1 -4
View File
@@ -19,9 +19,6 @@ if {"::tcltest" ni [namespace children]} {
catch [list package require -exact tcl::test [info patchlevel]]
testConstraint testwinclock [llength [info commands testwinclock]]
# Some things fail under all Continuous Integration systems for subtle reasons
# such as CI often running with elevated privileges in a container.
testConstraint notInCIenv [expr {![info exists ::env(CI)]}]
# The next two tests will crash on Windows if the check for negative
# clock values is not done properly.
@@ -43,7 +40,7 @@ test winTime-1.2 {TclpGetDate} {win} {
# with the Windows clock. 30 sec really isn't enough,
# but how much time does a tester have patience for?
test winTime-2.1 {Synchronization of Tcl and Windows clocks} {testwinclock notInCIenv} {
test winTime-2.1 {Synchronization of Tcl and Windows clocks} testwinclock {
# May fail due to OS/hardware discrepancies. See:
# http://support.microsoft.com/default.aspx?scid=kb;en-us;274323
set failed {}
+32
View File
@@ -486,6 +486,38 @@ test zlib-8.18 {Bug dd260aaf: fconfigure} -setup {
catch {close $inSide}
catch {close $outSide}
} -result {{one two} {one two}}
test zlib-8.19 {zlib transformation, bug f9eafc3886} -constraints zlib -setup {
set file [makeFile {} test.gz]
} -body {
set f [zlib push gzip [open $file w] -header [list comment [string repeat A 500]]]
} -cleanup {
catch {close $f}
removeFile $file
} -returnCodes 1 -result {Comment too large for zip}
test zlib-8.20 {zlib transformation, bug f9eafc3886} -constraints zlib -setup {
set file [makeFile {} test.gz]
} -body {
set f [zlib push gzip [open $file w] -header [list filename [string repeat A 5000]]]
} -cleanup {
catch {close $f}
removeFile $file
} -returnCodes 1 -result {Filename too large for zip}
test zlib-8.21 {zlib transformation, bug f9eafc3886} -constraints zlib -setup {
set file [makeFile {} test.gz]
} -body {
set f [zlib push gzip [open $file w] -header [list comment \u100]]
} -cleanup {
catch {close $f}
removeFile $file
} -returnCodes 1 -result {Comment contains characters > 0xFF}
test zlib-8.22 {zlib transformation, bug f9eafc3886} -constraints zlib -setup {
set file [makeFile {} test.gz]
} -body {
set f [zlib push gzip [open $file w] -header [list filename \u100]]
} -cleanup {
catch {close $f}
removeFile $file
} -returnCodes 1 -result {Filename contains characters > 0xFF}
test zlib-9.1 "check fcopy with push" -constraints zlib -setup {
set sfile [makeFile {} testsrc.gz]
-5
View File
@@ -71,11 +71,6 @@ encodings: clean txt2enc $(EUC_ENCODINGS)
done
@echo
@echo Compiling special versions of encoding files.
@for p in ascii.txt; do \
enc=`echo $$p | sed 's/\..*$$/\.enc/'`; \
echo $$enc; \
./txt2enc -m $$p > $$enc; \
done
@for p in jis0208.txt; do \
enc=`echo $$p | sed 's/\..*$$/\.enc/'`; \
echo $$enc; \
+3 -5
View File
@@ -106,7 +106,7 @@ main(int argc, char **argv)
fputs(" -f\tfallback character (default: QUESTION MARK)\n", stderr);
fputs(" -t\toverride implicit type with single, double, or multi\n", stderr);
fputs(" -s\tsymbol+ascii encoding\n", stderr);
fputs(" -m\tdon't implicitly include range 0080 to 00FF\n", stderr);
fputs(" -m\tdon't implicitly include 007F\n", stderr);
return 1;
}
@@ -208,10 +208,8 @@ main(int argc, char **argv)
toUnicode[0][i] = i;
}
if (fixmissing) {
for (i = 0x7F; i < 0xA0; i++) {
if (toUnicode[i] == NULL && toUnicode[0][i] == 0) {
toUnicode[0][i] = i;
}
if (toUnicode[0x7F] == NULL && toUnicode[0][0x7F] == 0) {
toUnicode[0][0x7F] = 0x7F;
}
}
}
+30
View File
@@ -0,0 +1,30 @@
#! /usr/bin/env tclsh
proc main {sourcetype source} {
switch $sourcetype {
file {
set chan [open $source]
try {
set data [read $chan]
} finally {
close $chan
}
}
string {
set data $source
}
default {
error [list {wrong # args}]
}
}
set found [regexp -inline -all {blocks are\
(?:(?:(?:definitely|indirectly|possibly) lost)|still reachable)} $data]
if {[llength $found]} {
puts 0
} else {
puts 1
}
flush stdout
}
main {*}$argv
+137
View File
@@ -1,3 +1,17 @@
#{
# Tcl_GetChannelOption/TcpGetOptionProc/TcphostPortList/getnameinfo/gethostbyaddr_r
# Memcheck:Leak
# match-leak-kinds: reachable
# fun:malloc
# fun:strdup
# ...
# fun:module_load
# ...
# fun:getnameinfo
# ...
# fun:Tcl_GetChannelOption
#}
{
TclCreatesocketAddress/getaddrinfo/calloc
Memcheck:Leak
@@ -8,6 +22,16 @@
fun:TclCreateSocketAddress
}
{
TclCreatesocketAddress/getaddrinfo/malloc
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
...
fun:getaddrinfo
fun:TclCreateSocketAddress
}
{
TclCreatesocketAddress/getaddrinfo/malloc
Memcheck:Leak
@@ -18,6 +42,18 @@
fun:TclCreateSocketAddress
}
{
TclpDlopen/decompose_rpath
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:decompose_rpath
...
fun:dlopen_doit
...
fun:TclpDlopen
}
{
TclpDlopen/load
Memcheck:Leak
@@ -71,6 +107,46 @@
fun:TclpGetGrNam
}
{
TclpGeHostByName/gethostbyname_r/strdup/malloc
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:strdup
...
fun:dl_open_worker
...
fun:do_dlopen
...
fun:TclpGetHostByName
}
{
TclpGeHostByName/gethostbyname_r/calloc
Memcheck:Leak
match-leak-kinds: reachable
fun:calloc
...
fun:dl_open_worker
...
fun:do_dlopen
...
fun:TclpGetHostByName
}
{
TclpGeHostByName/gethostbyname_r/malloc
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
...
fun:dl_open_worker
...
fun:do_dlopen
...
fun:TclpGetHostByName
}
{
TclpGetPwNam/getpwname_r/__nss_next2/calloc
Memcheck:Leak
@@ -104,6 +180,57 @@
fun:TclpGetPwNam
}
{
TclpGetGrGid/getgrgid_r/module_load
Memcheck:Leak
match-leak-kinds: reachable
fun:calloc
...
fun:module_load
...
fun:TclpGetGrGid
}
{
TclpGetGrGid/getgrgid_r/module_load
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
...
fun:module_load
...
fun:TclpGetGrGid
}
{
TcphostPortList/getnameinfo/module_load/calloc
Memcheck:Leak
match-leak-kinds: definite,reachable
fun:calloc
...
fun:dl_open_worker_begin
...
fun:module_load
...
fun:getnameinfo
fun:TcpHostPortList
}
{
# see sourceware glibc Bug 14984 - getnameinfo() might be leaking memory
TcphostPortList/getnameinfo/module_load/mallco
Memcheck:Leak
match-leak-kinds: definite,reachable
fun:malloc
...
fun:dl_open_worker_begin
...
fun:module_load
...
fun:getnameinfo
fun:TcpHostPortList
}
{
TclpThreadExit/pthread_exit/calloc
Memcheck:Leak
@@ -124,3 +251,13 @@
fun:TclpThreadExit
}
{
TclpThreadExit/pthread_exit/malloc
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
...
fun:pthread_exit
fun:TclpThreadExit
}
+22 -2
View File
@@ -952,6 +952,26 @@ valgrind: ${TCL_EXE} ${TCLTEST_EXE}
$(TOP_DIR)/tests/all.tcl -singleproc 1 -constraints valgrind \
$(TESTFLAGS)
testresults/valgrind/%.result: ${TCL_EXE} ${TCLTEST_EXE}
@mkdir -p testresults/valgrind
$(SHELL_ENV) $(VALGRIND) $(VALGRINDARGS) ./${TCLTEST_EXE} \
$(TOP_DIR)/tests/all.tcl -singleproc 1 -constraints valgrind \
-file $(basename $(notdir $@)) > $@ 2>&1
.PRECIOUS: testresults/valgrind/%.result
testresults/valgrind/%.success: testresults/valgrind/%.result
@printf '%s' valgrind >&2
@printf ' %s' $(basename $(notdir $@)) >&2
@printf '\n >&2'
@status=$$(./${TCLTEST_EXE} $(TOP_DIR)/tools/valgrind_check_success \
file $(basename $@).result); \
if [ "$$status" -eq 1 ]; then exit 0; else exit 1; fi
valgrind_each: $(addprefix testresults/valgrind/,$(addsuffix .success,$(notdir\
$(wildcard $(TOP_DIR)/tests/*.test))))
valgrindshell: ${TCL_EXE}
$(SHELL_ENV) $(VALGRIND) $(VALGRINDARGS) ./${TCL_EXE} $(SCRIPT)
@@ -1051,9 +1071,9 @@ install-libraries: libraries
@echo "Installing package msgcat 1.7.1 as a Tcl Module"
@$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl \
"$(MODULE_INSTALL_DIR)/8.7/msgcat-1.7.1.tm"
@echo "Installing package tcltest 2.5.5 as a Tcl Module"
@echo "Installing package tcltest 2.5.6 as a Tcl Module"
@$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl \
"$(MODULE_INSTALL_DIR)/8.5/tcltest-2.5.5.tm"
"$(MODULE_INSTALL_DIR)/8.5/tcltest-2.5.6.tm"
@echo "Installing package platform 1.0.19 as a Tcl Module"
@$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl \
"$(MODULE_INSTALL_DIR)/8.4/platform-1.0.19.tm"
-50
View File
@@ -7631,56 +7631,6 @@ printf "%s\n" "#define _LARGEFILE64_SOURCE 1" >>confdefs.h
tcl_flags="$tcl_flags _LARGEFILE64_SOURCE"
fi
if test ${tcl_cv_flag__largefile_source64+y}
then :
printf %s "(cached) " >&6
else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/stat.h>
int
main (void)
{
char *p = (char *)open64;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
tcl_cv_flag__largefile_source64=no
else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _LARGEFILE_SOURCE64 1
#include <sys/stat.h>
int
main (void)
{
char *p = (char *)open64;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
tcl_cv_flag__largefile_source64=yes
else $as_nop
tcl_cv_flag__largefile_source64=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then
printf "%s\n" "#define _LARGEFILE_SOURCE64 1" >>confdefs.h
tcl_flags="$tcl_flags _LARGEFILE_SOURCE64"
fi
if test "x${tcl_flags}" = "x" ; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
printf "%s\n" "none" >&6; }
-3
View File
@@ -2329,7 +2329,6 @@ AC_DEFUN([SC_TCL_LINK_LIBS], [
# Might define the following vars:
# _ISOC99_SOURCE
# _LARGEFILE64_SOURCE
# _LARGEFILE_SOURCE64
#
#--------------------------------------------------------------------
@@ -2353,8 +2352,6 @@ AC_DEFUN([SC_TCL_EARLY_FLAGS],[
[char *p = (char *)strtoll; char *q = (char *)strtoull;])
SC_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>],
[struct stat64 buf; int i = stat64("/", &buf);])
SC_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>],
[char *p = (char *)open64;])
if test "x${tcl_flags}" = "x" ; then
AC_MSG_RESULT([none])
else
-3
View File
@@ -492,9 +492,6 @@
/* Add the _LARGEFILE64_SOURCE flag when building */
#undef _LARGEFILE64_SOURCE
/* Add the _LARGEFILE_SOURCE64 flag when building */
#undef _LARGEFILE_SOURCE64
/* # needed in sys/socket.h Should OS/390 do the right thing with sockets? */
#undef _OE_SOCKETS
+6 -6
View File
@@ -1033,10 +1033,10 @@ TcpGetOptionProc(
if ((len == 0) || ((len > 1) && (optionName[1] == 'k') &&
(strncmp(optionName, "-keepalive", len) == 0))) {
#if defined(SO_KEEPALIVE)
socklen_t size;
#endif
int opt = 0;
#if defined(SO_KEEPALIVE)
socklen_t size = sizeof(opt);
#endif
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-keepalive");
@@ -1053,10 +1053,10 @@ TcpGetOptionProc(
if ((len == 0) || ((len > 1) && (optionName[1] == 'n') &&
(strncmp(optionName, "-nodelay", len) == 0))) {
#if defined(SOL_TCP) && defined(TCP_NODELAY)
socklen_t size;
#endif
int opt = 0;
#if defined(SOL_TCP) && defined(TCP_NODELAY)
socklen_t size = sizeof(opt);
#endif
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-nodelay");
+2 -2
View File
@@ -889,8 +889,8 @@ install-libraries: libraries install-tzdata install-msgs
done;
@echo "Installing package msgcat 1.7.1 as a Tcl Module";
@$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl "$(MODULE_INSTALL_DIR)/8.7/msgcat-1.7.1.tm";
@echo "Installing package tcltest 2.5.5 as a Tcl Module";
@$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl "$(MODULE_INSTALL_DIR)/8.5/tcltest-2.5.5.tm";
@echo "Installing package tcltest 2.5.6 as a Tcl Module";
@$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl "$(MODULE_INSTALL_DIR)/8.5/tcltest-2.5.6.tm";
@echo "Installing package platform 1.0.19 as a Tcl Module";
@$(COPY) $(ROOT_DIR)/library/platform/platform.tcl "$(MODULE_INSTALL_DIR)/8.4/platform-1.0.19.tm";
@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
+2 -2
View File
@@ -379,7 +379,7 @@ TclWinDriveLetterForVolMountPoint(
if (!alreadyStored) {
dlPtr2 = (MountPointMap *)ckalloc(sizeof(MountPointMap));
dlPtr2->volumeName = (WCHAR *)TclNativeDupInternalRep(Target);
dlPtr2->driveLetter = (char) drive[0];
dlPtr2->driveLetter = (WCHAR) drive[0];
dlPtr2->nextPtr = driveLetterLookup;
driveLetterLookup = dlPtr2;
}
@@ -405,7 +405,7 @@ TclWinDriveLetterForVolMountPoint(
dlPtr2 = (MountPointMap *)ckalloc(sizeof(MountPointMap));
dlPtr2->volumeName = (WCHAR *)TclNativeDupInternalRep((void *)mountPoint);
dlPtr2->driveLetter = -1;
dlPtr2->driveLetter = (WCHAR)-1;
dlPtr2->nextPtr = driveLetterLookup;
driveLetterLookup = dlPtr2;
Tcl_MutexUnlock(&mountPointMap);
+3 -3
View File
@@ -700,7 +700,7 @@ FileInputProc(
if (ReadFile(infoPtr->handle, (LPVOID) buf, (DWORD) bufSize, &bytesRead,
(LPOVERLAPPED) NULL) != FALSE) {
return bytesRead;
return (int)bytesRead;
}
Tcl_WinConvertError(GetLastError());
@@ -757,7 +757,7 @@ FileOutputProc(
return -1;
}
infoPtr->dirty = 1;
return bytesWritten;
return (int)bytesWritten;
}
/*
@@ -1572,7 +1572,7 @@ NativeIsComPort(
const WCHAR *nativePath) /* Path of file to access, native encoding. */
{
const WCHAR *p = (const WCHAR *) nativePath;
int i, len = wcslen(p);
size_t i, len = wcslen(p);
/*
* 1. Look for com[1-9]:?
+31 -37
View File
@@ -1457,21 +1457,39 @@ TclpGetUserHome(
if (domain == NULL) {
const char *ptr;
/*
* No domain. Firstly check it's the current user
*/
/*
* Treat the current user as a special case because the general case
* below does not properly retrieve the path. The NetUserGetInfo
* call returns an empty path and the code defaults to the user's
* name in the profiles directory. On modern Windows systems, this
* is generally wrong as when the account is a Microsoft account,
* for example abcdefghi@outlook.com, the directory name is
* abcde and not abcdefghi.
*
* Note we could have just used env(USERPROFILE) here but
* the intent is to retrieve (as on Unix) the system's view
* of the home irrespective of environment settings of HOME
* and USERPROFILE.
*
* Fixing this for the general user needs more investigating but
* at least for the current user we can use a direct call.
*/
ptr = TclpGetUserName(&ds);
if (ptr != NULL && strcasecmp(name, ptr) == 0) {
/*
* Try safest and fastest way to get current user home
*/
ptr = TclGetEnv("HOME", &ds);
if (ptr != NULL) {
Tcl_JoinPath(1, &ptr, bufferPtr);
rc = 1;
result = Tcl_DStringValue(bufferPtr);
HANDLE hProcess;
WCHAR buf[MAX_PATH];
DWORD nChars = sizeof(buf) / sizeof(buf[0]);
/* Sadly GetCurrentProcessToken not in Win 7 so slightly longer */
hProcess = GetCurrentProcess(); /* Need not be closed */
if (hProcess) {
HANDLE hToken;
if (OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
if (GetUserProfileDirectoryW(hToken, buf, &nChars)) {
result = Tcl_WCharToUtfDString(buf, nChars-1, (bufferPtr));
rc = 1;
}
CloseHandle(hToken);
}
}
}
Tcl_DStringFree(&ds);
@@ -1543,30 +1561,6 @@ TclpGetUserHome(
if (wDomain != NULL) {
NetApiBufferFree((void *) wDomain);
}
if (result == NULL) {
/*
* Look in the "Password Lists" section of system.ini for the local
* user. There are also entries in that section that begin with a "*"
* character that are used by Windows for other purposes; ignore user
* names beginning with a "*".
*/
char buf[MAX_PATH];
if (name[0] != '*') {
if (GetPrivateProfileStringA("Password Lists", name, "", buf,
MAX_PATH, "system.ini") > 0) {
/*
* User exists, but there is no such thing as a home directory
* in system.ini. Return "{Windows drive}:/".
*/
GetWindowsDirectoryA(buf, MAX_PATH);
Tcl_DStringAppend(bufferPtr, buf, 3);
result = Tcl_DStringValue(bufferPtr);
}
}
}
return result;
}
+2 -2
View File
@@ -56,10 +56,10 @@ Tcl_ConsolePanic(
if (IsDebuggerPresent()) {
OutputDebugStringW(msgString);
} else if (_isatty(2)) {
WriteConsoleW(handle, msgString, wcslen(msgString), &dummy, 0);
WriteConsoleW(handle, msgString, (DWORD)wcslen(msgString), &dummy, 0);
} else {
buf[0] = '\xEF'; buf[1] = '\xBB'; buf[2] = '\xBF'; /* UTF-8 bom */
WriteFile(handle, buf, strlen(buf), &dummy, 0);
WriteFile(handle, buf, (DWORD)strlen(buf), &dummy, 0);
WriteFile(handle, "\n", 1, &dummy, 0);
FlushFileBuffers(handle);
}
+165 -151
View File
@@ -22,9 +22,8 @@
/*
* For TestplatformChmod on Windows
*/
#ifdef _WIN32
#include <aclapi.h>
#endif
#include <sddl.h>
/*
* MinGW 3.4.2 does not define this.
@@ -414,176 +413,189 @@ TestExceptionCmd(
return TCL_OK;
}
/*
* This "chmod" works sufficiently for test script purposes. Do not expect
* it to be exact emulation of Unix chmod (not sure if that's even possible)
*/
static int
TestplatformChmod(
const char *nativePath,
int pmode)
{
static const SECURITY_INFORMATION infoBits = OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
/* don't reset change permissions mask (WRITE_DAC, allow test-cases restore it to cleanup) */
static const DWORD readOnlyMask = FILE_DELETE_CHILD | FILE_ADD_FILE
| FILE_ADD_SUBDIRECTORY | FILE_WRITE_EA | FILE_APPEND_DATA
| FILE_WRITE_DATA
| DELETE;
/*
* References to security functions (only available on NT and later).
* Note FILE_DELETE_CHILD missing from dirWriteMask because we do
* not want overriding of child's delete setting when testing
*/
static const DWORD dirWriteMask =
FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA |
FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | STANDARD_RIGHTS_WRITE | DELETE |
SYNCHRONIZE;
static const DWORD dirReadMask =
FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_LIST_DIRECTORY |
STANDARD_RIGHTS_READ | SYNCHRONIZE;
/* Note - default user privileges allow ignoring TRAVERSE setting */
static const DWORD dirExecuteMask =
FILE_TRAVERSE | STANDARD_RIGHTS_READ | SYNCHRONIZE;
const BOOL set_readOnly = !(pmode & 0222);
BOOL acl_readOnly_found = FALSE, curAclPresent, curAclDefaulted;
SID_IDENTIFIER_AUTHORITY userSidAuthority = {
SECURITY_WORLD_SID_AUTHORITY
};
BYTE *secDesc = 0;
DWORD secDescLen, attr, newAclSize;
ACL_SIZE_INFORMATION ACLSize;
PACL curAcl, newAcl = 0;
WORD j;
SID *userSid = 0;
char *userDomain = 0;
static const DWORD fileWriteMask =
FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_WRITE_DATA |
FILE_APPEND_DATA | STANDARD_RIGHTS_WRITE | DELETE | SYNCHRONIZE;
static const DWORD fileReadMask =
FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_READ_DATA |
STANDARD_RIGHTS_READ | SYNCHRONIZE;
static const DWORD fileExecuteMask =
FILE_EXECUTE | STANDARD_RIGHTS_READ | SYNCHRONIZE;
DWORD attr, newAclSize;
PACL newAcl = NULL;
int res = 0;
/*
* Process the chmod request.
*/
HANDLE hToken = NULL;
int i;
int nSids = 0;
struct {
PSID pSid;
DWORD mask;
DWORD sidLen;
} aceEntry[3];
DWORD dw;
int isDir;
TOKEN_USER *pTokenUser = NULL;
res = -1; /* Assume failure */
attr = GetFileAttributesA(nativePath);
/*
* nativePath not found
*/
if (attr == 0xFFFFFFFF) {
res = -1;
goto done; /* Not found */
}
isDir = (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
goto done;
}
/*
* If nativePath is not a directory, there is no special handling.
*/
if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
/* Get process SID */
if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dw) &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
goto done;
}
pTokenUser = (TOKEN_USER *)ckalloc(dw);
if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dw, &dw)) {
goto done;
}
aceEntry[nSids].sidLen = GetLengthSid(pTokenUser->User.Sid);
aceEntry[nSids].pSid = ckalloc(aceEntry[nSids].sidLen);
if (!CopySid(aceEntry[nSids].sidLen,
aceEntry[nSids].pSid,
pTokenUser->User.Sid)) {
ckfree(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */
goto done;
}
/*
* Set the result to error, if the ACL change is successful it will be
* reset to 0.
* Always include DACL modify rights so we don't get locked out
*/
res = -1;
/*
* Read the security descriptor for the directory. Note the first call
* obtains the size of the security descriptor.
*/
if (!GetFileSecurityA(nativePath, infoBits, NULL, 0, &secDescLen)) {
DWORD secDescLen2 = 0;
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
goto done;
aceEntry[nSids].mask = READ_CONTROL | WRITE_DAC | WRITE_OWNER | SYNCHRONIZE |
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
if (pmode & 0700) {
/* Owner permissions. Assumes current process is owner */
if (pmode & 0400) {
aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
}
secDesc = (BYTE *)ckalloc(secDescLen);
if (!GetFileSecurityA(nativePath, infoBits,
(PSECURITY_DESCRIPTOR) secDesc, secDescLen, &secDescLen2)
|| (secDescLen < secDescLen2)) {
goto done;
if (pmode & 0200) {
aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
}
if (pmode & 0100) {
aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
}
}
++nSids;
/*
* Get the World SID.
*/
if (pmode & 0070) {
/* Group permissions. */
userSid = (SID *)ckalloc(GetSidLengthRequired((UCHAR) 1));
InitializeSid(userSid, &userSidAuthority, (BYTE) 1);
*(GetSidSubAuthority(userSid, 0)) = SECURITY_WORLD_RID;
TOKEN_PRIMARY_GROUP *pTokenGroup;
/*
* If curAclPresent == false then curAcl and curAclDefaulted not valid.
*/
/* Get primary group SID */
if (!GetTokenInformation(
hToken, TokenPrimaryGroup, NULL, 0, &dw) &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
goto done;
}
pTokenGroup = (TOKEN_PRIMARY_GROUP *)ckalloc(dw);
if (!GetTokenInformation(hToken, TokenPrimaryGroup, pTokenGroup, dw, &dw)) {
ckfree(pTokenGroup);
goto done;
}
aceEntry[nSids].sidLen = GetLengthSid(pTokenGroup->PrimaryGroup);
aceEntry[nSids].pSid = ckalloc(aceEntry[nSids].sidLen);
if (!CopySid(aceEntry[nSids].sidLen, aceEntry[nSids].pSid, pTokenGroup->PrimaryGroup)) {
ckfree(pTokenGroup);
ckfree(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */
goto done;
}
ckfree(pTokenGroup);
if (!GetSecurityDescriptorDacl((PSECURITY_DESCRIPTOR) secDesc,
&curAclPresent, &curAcl, &curAclDefaulted)) {
goto done;
}
if (!curAclPresent || !curAcl) {
ACLSize.AclBytesInUse = 0;
ACLSize.AceCount = 0;
} else if (!GetAclInformation(curAcl, &ACLSize, sizeof(ACLSize),
AclSizeInformation)) {
goto done;
/* Generate mask for group ACL */
aceEntry[nSids].mask = 0;
if (pmode & 0040) {
aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
}
if (pmode & 0020) {
aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
}
if (pmode & 0010) {
aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
}
++nSids;
}
/*
* Allocate memory for the new ACL.
*/
if (pmode & 0007) {
/* World permissions */
PSID pWorldSid;
if (!ConvertStringSidToSidA("S-1-1-0", &pWorldSid)) {
goto done;
}
aceEntry[nSids].sidLen = GetLengthSid(pWorldSid);
aceEntry[nSids].pSid = ckalloc(aceEntry[nSids].sidLen);
if (!CopySid(aceEntry[nSids].sidLen, aceEntry[nSids].pSid, pWorldSid)) {
LocalFree(pWorldSid);
ckfree(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */
goto done;
}
LocalFree(pWorldSid);
newAclSize = ACLSize.AclBytesInUse + sizeof(ACCESS_DENIED_ACE)
+ GetLengthSid(userSid) - sizeof(DWORD);
newAcl = (PACL) ckalloc(newAclSize);
/* Generate mask for world ACL */
/*
* Initialize the new ACL.
*/
aceEntry[nSids].mask = 0;
if (pmode & 0004) {
aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
}
if (pmode & 0002) {
aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
}
if (pmode & 0001) {
aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
}
++nSids;
}
/* Allocate memory and initialize the new ACL. */
newAclSize = sizeof(ACL);
/* Add in size required for each ACE entry in the ACL */
for (i = 0; i < nSids; ++i) {
newAclSize +=
offsetof(ACCESS_ALLOWED_ACE, SidStart) + aceEntry[i].sidLen;
}
newAcl = (PACL)ckalloc(newAclSize);
if (!InitializeAcl(newAcl, newAclSize, ACL_REVISION)) {
goto done;
}
/*
* Add denied to make readonly, this will be known as a "read-only tag".
*/
if (set_readOnly && !AddAccessDeniedAce(newAcl, ACL_REVISION,
readOnlyMask, userSid)) {
goto done;
}
acl_readOnly_found = FALSE;
for (j = 0; j < ACLSize.AceCount; j++) {
LPVOID pACE2;
ACE_HEADER *phACE2;
if (!GetAce(curAcl, j, &pACE2)) {
goto done;
}
phACE2 = (ACE_HEADER *) pACE2;
/*
* Do NOT propagate inherited ACEs.
*/
if (phACE2->AceFlags & INHERITED_ACE) {
continue;
}
/*
* Skip the "read-only tag" restriction (either added above, or it is
* being removed).
*/
if (phACE2->AceType == ACCESS_DENIED_ACE_TYPE) {
ACCESS_DENIED_ACE *pACEd = (ACCESS_DENIED_ACE *) phACE2;
if (pACEd->Mask == readOnlyMask
&& EqualSid(userSid, (PSID) &pACEd->SidStart)) {
acl_readOnly_found = TRUE;
continue;
}
}
/*
* Copy the current ACE from the old to the new ACL.
*/
if (!AddAce(newAcl, ACL_REVISION, MAXDWORD, (PACL *) pACE2,
((PACE_HEADER) pACE2)->AceSize)) {
for (i = 0; i < nSids; ++i) {
if (!AddAccessAllowedAce(newAcl, ACL_REVISION, aceEntry[i].mask, aceEntry[i].pSid)) {
goto done;
}
}
@@ -593,36 +605,38 @@ TestplatformChmod(
* to remove inherited ACL (we need to overwrite the default ACL's in this case)
*/
if (set_readOnly == acl_readOnly_found || SetNamedSecurityInfoA(
(LPSTR) nativePath, SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION /*| PROTECTED_DACL_SECURITY_INFORMATION*/,
NULL, NULL, newAcl, NULL) == ERROR_SUCCESS) {
if (SetNamedSecurityInfoA((LPSTR)nativePath,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION |
PROTECTED_DACL_SECURITY_INFORMATION,
NULL,
NULL,
newAcl,
NULL) == ERROR_SUCCESS) {
res = 0;
}
done:
if (secDesc) {
ckfree(secDesc);
if (pTokenUser) {
ckfree(pTokenUser);
}
if (hToken) {
CloseHandle(hToken);
}
if (newAcl) {
ckfree(newAcl);
}
if (userSid) {
ckfree(userSid);
}
if (userDomain) {
ckfree(userDomain);
for (i = 0; i < nSids; ++i) {
ckfree(aceEntry[i].pSid);
}
if (res != 0) {
return res;
}
/*
* Run normal chmod command.
*/
/* Run normal chmod command */
return chmod(nativePath, pmode);
}
/*